ARIMA, LSTM을 이용한 시계열 분석 입문

choonsikmom·2022년 1월 27일
0

시계열 분석

목록 보기
1/4
post-thumbnail

📈 시계열 분석?


주식을 시작했다. 😂

시장가격이 조만간 계속 하락할 것 같아서 조금씩 매입하려는 생각인데,
아직은 실시간으로 오르락내리락 하는 그래프만 보고 있어도 꽤 재미있다.
하지만 과감하게 투자했다가는 평생 하락 길만 걷다가 종토방 망령이 될 지도 모를 일이다.
그래서 말인데, 내가 산 주식 가격이 앞으로 어떻게 될지 미리 아는 방법은 없을까? (그럼 평생 먹고 살 걱정은 없겠네 😏)

그래서 공부해 본 것은 시계열 분석이다. 사실 주식은 외부 조건에 따라 생기는 크고 작은 변수가 너무 많아서 분석 결과를 그닥 신뢰할 순 없지만.. 시계열 분석 입문에 적용해보기 좋은 주제이다.

글에서는 두 가지 방법으로 삼성전자 주식 동향을 예측해 보고자 한다.

1. ARIMA(Autoregressive Integrated Moving Average)
2. LSTM(Long Short-Term Memory)

📣 방법론 소개


방법론의 개념에 대해서는 검색하면 무수히 나오므로 간단하게 짚고 넘어가겠다.

1. ARIMA


ARIMA는 전통적인 시계열 분석 방법론으로, AR(Auto-Regressive)MA(Moving Average) 을 통합한 형태이다. 두 방법론에 대해 간단하게 정리해 보자.

* AR : 과거 시점의 데이터들을 회귀식을 사용하여 현재 시점의 데이터에 반영
* MA : 과거 데이터의 변화율을 현재 시점의 데이터에 반영

--> AR의 경우 stationary한 데이터는 잘 설명하지만 추세가 바뀌는(e.g. 떡락하던 주식이 따상한다던가?)데이터를 잘 설명하지 못하고, MA는 그러한 상황의 데이터를 설명하기 용이하므로, AR과 MA을 결합한 방법론이 나오게 된 것 같다.

2. LSTM


LSTM은 RNN(Recurrent Neural Network) 의한 종류로, RNN에서 long-term 데이터를 사용 할 때 과거 정보가 점차 소실되는 문제를 해결하기 위해 설계된 신경망이다. LSTM은 RNN의 hidden state에 cell-state를 추가했는데, cell-state는 데이터의 term이 길어지더라도 과거의 정보를 잃지 않도록 한다.

✅ yfinance


먼저 분석에 사용할 주식 데이터를 준비해야 한다.

** yfinance란? [공식 문서]
야후에서 제공하는 finance data이다. 날짜별로 시가, 종가, 저가, 고가, 거래량 등을 dataframe 형식으로 다운받을 수 있다.

# *-- 데이터 로드 --*
#!pip install yfinance
import yfinance as yf

#삼성전자 주가 다운로드(2020-01-01 ~ 2021-12-01)
samsung = yf.download('005930.KS', #삼성전자주 코드
			start='2020-01-01', end='2021-12-01')

# [close == 종가]
samsung = samsung[['Close']]
samsung.reset_index(inplace=True)
samsung = samsung.rename(columns = {'Close' : 'Price})
samsung.head(3)

----------------------------------------------------

# 날짜별 주가 확인(line-plot)
samsung.plot(x='Date', y='Price', kind='line')

데이터 준비는 이제 끝이 났다. 😮

✅ ARIMA


ARIMA를 사용하여 삼성 주가 예측을 진행한다.

# *-- ARIMA 방법론 구현 --*
# !pip install statsmodels==0.11.0rc1
from statsmodels.tsa.arima.model import ARIMA
import statsmodels.api as sm

# ARIMA model 생성
model = ARIMA(samsung.Price.values, order=(2,1,2)) # order 안의 파라미터는 (AR, Difference, MA)
fit = model.fit()
fit.summary() # 생성 모델에 대한 summary 확인
- AR : AR이 몇 번째 과거까지를 바라보는지에 대한 파라미터
- Difference : 차분
- MA : MA이 몇 번째 과거까지를 바라보는지에 대한 파라미터
# *-- 예측 결과를 시각화 --*
import matplotlib.pyplot as plt
import pandas as pd
pred = pd.DataFrame(fit.predict())
preds[1:].plot()
samsung['Price'].plot()
plot.show()

# 잔차 시각화
residuals = pd.DataFrame(fit.resid)
residuals[1:].plot()

# 이후 10일에 대한 주가 예측을 시도
fit.forecast(steps=10)
주가 예측 결과가 실제 데이터와 잘 맞는지 확인하기 위해서는, 
분석에 사용한 데이터의 10일 이후 데이터를 불러와서 비교해 보면 된다.
# *-- 실제 데이터 확인 --*
forecasts = yf.download('005930.KS',
                     start='2021-12-01',
                     end='2021-12-10')
print(forecasts['Close'].values)                     

✅ LSTM


LSTM을 사용하여 삼성 주가 예측을 진행한다.

# *-- 데이터 전처리 --*
# sklearn을 활용한 data scaling
from sklearn.preprocessing import RobustScaler
# RobustScaler : Scale features using statistics that are robust to outliers.
rb = RobustScaler()

samsung_scaled = rb.fit_transform(samsung[['Price']])
samsung['Price'] = samsung_scaled
samsung.head() # 스케일링 결과 확인(-1~1 사이의 값으로 스케일링)

# train, test set 분리
test_size = 100 # data split size
train_data = samsung[:-test_size]
test_data = samsung[-test_size:]

# 당일 데이터 예측에 +n일의 과거 데이터를 반영한다.
import pandas as pd
window_size = 15 # 예측에 반영할 과거 데이터 일수
for i in range(1, 15) :
	train_data[f'Price_{i}'] = train_data['Price'].shift(i)
    	test_data[f'Price_{i}'] = test_data['Price'].shift(i)
        # train, test 데이터를 하루 씩 옮기면서 과거 데이터를 형성

# 데이터 확인
train_data.head(3)        

# 과거 데이터가 채워지지 않으면 drop함
train_data.dropna(inplace=True)
X_train = train_data.drop('Price', axis=1)
y_train = train_data[['Price']]
test_data.dropna(inplace=True)
X_test = test_data.drop('Price', axis=1)
y_test = test_data[['Price']]

# train, test 사이즈를 확인하고, 신경망 학습을 위해 reshape한다
X_train= X_train.values
X_test= X_test.values
y_train = y_train.values
y_test = y_test.values
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)

X_train = X_train.reshape(X_train.shape[0], 14, 1 )
X_test= X_test.reshape(X_test.shape[0], 14, 1 )

# *-- 신경망 생성 --*
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, LSTM
from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint
from tensorflow.keras import backend as K
K.clear_session()

model = Sequential()
model.add(LSTM(14, return_sequences = True, input_shape = (14, 1)))
model.add(LSTM(28, return_sequences=False))
model.add(Dense(1, activation='linear'))

model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()

# 모델 학습
es = EarlyStopping(monitor='loss', patience=5, verbose= 1)
model.fit(X_train, y_train, epochs = 50, batch_size=16, verbose=1,
         callbacks=[es])

# 모델 예측
y_pred = model.predict(X_test)

# *-- 결과 시각화 --*
# 예측 결과와 실제 값을 시각화
y_test_val = pd.DataFrame(y_test, index=test_data.index)
y_pred_val = pd.DataFrame(y_pred, index=test_data.index)

import matplotlib.pyplot as plt
ax1 = y_test_val.plot()
y_pred_val.plot(ax=ax1)
plt.legend(['test','pred'])
profile
춘식이랑 함께하는 개발일지.. 그런데 이제 먼작귀를 곁들인

0개의 댓글