(파이썬 증권데이터 분석) 순환신경망을 이용한 주가 예측(딥러닝)
2022.07.24 - [computer_IT] - (파이썬 증권데이터 분석) 백트레이더를 활용한 백테스트
(파이썬 증권데이터 분석) 백트레이더를 활용한 백테스트
2022.07.24 - [computer_IT] - (파이썬 증권데이터 분석) 슬랙으로 알림메시지 보내기 (파이썬 증권데이터 분석) 슬랙으로 알림메시지 보내기 2022.07.24 - [computer_IT] - (파이썬 증권데이터 분석) 장고 웹서
lifenlight.tistory.com
순환신경망(RNN : Recurrent Neural Network)는 이전의 데이터를 통해 학습된 상태 정보가 다음 데이터를 학습시킬 때 다시 사용되는 알고리즘이다. 시계열 데이터를 처리할 때 적합하다. 기본적인 순환신경망은 단기 기억을 저장할 수 있지만 데이터들의 연관 정보를 파악하려면 기억을 더 길게 유지시켜야 한다. 이를 위해 장단기 기억 알고리즘(LSTM : Long Short-Term Memory)이 탄생했다. 텐서플로에 이미 RNN과 LSTM을 구현해두었기 때문에 사용법만 익혀도 충분하다.
pip install tensorflow 로 텐서플로를 설치한다. 삼성전자 액면분할 상장일이던 2018년 5월 4일부터 2022년 7월 현재까지를 데이터를 사용하며 훈련용 데이터로 70%, 테스트용 데이터로 30% 사용해보자. 데이터를 분리해서 사용하는 이유는 학습과정에서 사용된 적이 없는 테스트용 데이터를 분리해야 학습이 객관적으로 잘 이루어졌는지 점검할 수 있기 때문이다.
import sys
sys.path.insert(0, '/home/05_Stock_Price_API/') # Investar폴더의 상위폴더까지 지정
from tensorflow.keras import Sequential
from tensorflow.keras.layers import Dense, LSTM, Dropout
import numpy as np
import matplotlib.pyplot as plt
from Investar import Analyzer
mk = Analyzer.MarketDB()
raw_df = mk.get_daily_price('삼성전자', '2018-05-04', '2022-07-22')
window_size = 10
data_size = 5
def MinMaxScaler(data):
"""최솟값과 최댓값을 이용하여 0 ~ 1 값으로 변환"""
numerator = data - np.min(data, 0)
denominator = np.max(data, 0) - np.min(data, 0)
# 0으로 나누기 에러가 발생하지 않도록 매우 작은 값(1e-7)을 더해서 나눔
return numerator / (denominator + 1e-7)
dfx = raw_df[['open','high','low','volume', 'close']]
dfx = MinMaxScaler(dfx) # 가격정보를 0~1 사이값으로 변환
dfy = dfx[['close']]
x = dfx.values.tolist()
y = dfy.values.tolist()
data_x = []
data_y = []
for i in range(len(y) - window_size):
_x = x[i : i + window_size] # 다음 날 종가(i+windows_size)는 포함되지 않음
_y = y[i + window_size] # 다음 날 종가
data_x.append(_x)
data_y.append(_y)
print(_x, "->", _y)
# 훈련용 데이터셋
train_size = int(len(data_y) * 0.7)
train_x = np.array(data_x[0 : train_size])
train_y = np.array(data_y[0 : train_size])
# 테스트용 데이터셋
test_size = len(data_y) - train_size
test_x = np.array(data_x[train_size : len(data_x)])
test_y = np.array(data_y[train_size : len(data_y)])
# 모델 생성
model = Sequential()
model.add(LSTM(units=10, activation='relu', return_sequences=True, input_shape=(window_size, data_size)))
model.add(Dropout(0.1)) # 드롭아웃 10% 지정. 입력값의 일부분 선택해서 그 값을 0으로 치환하여 과적합을 방지
model.add(LSTM(units=10, activation='relu'))
model.add(Dropout(0.1))
model.add(Dense(units=1)) # 유닛이 하나인 출력층 추가
model.summary()
model.compile(optimizer='adam', loss='mean_squared_error') # 최적화도구는 adam, 손실함수는 평균제곱오차를 이용
model.fit(train_x, train_y, epochs=60, batch_size=30) # 훈련용 데이터 학습 : 데이터 30개를 60회 학습
pred_y = model.predict(test_x) # 테스트 데이터셋을 이용하여 예측치 데이터셋 생성
# Visualising the results
plt.figure()
plt.plot(test_y, color='red', label='real SEC stock price')
plt.plot(pred_y, color='blue', label='predicted SEC stock price')
plt.title('SEC stock price prediction')
plt.xlabel('time')
plt.ylabel('stock price')
plt.legend()
plt.savefig('RNNtest.png') #plt.show()
# raw_df.close[-1] : dfy.close[-1] = x : pred_y[-1]
# 내일의 예측 종가 출력
print("Tomorrow's SEC price :", raw_df.close[-1] * pred_y[-1] / dfy.close[-1], 'KRW')
결과 그래프
2022년 7월 22일 삼성전자 종가가 61300원인데 다음 종가 예측치가 56820원이 나왔다. 그리고 실행할 때마다 조금씩 다른 값이 나오는 것 같다. 좀 더 보완이 필요할 것으로 보인다.
이제까지 "파이썬 증권데이터 분석" 책의 내용을 리뷰하고 직접 실행해보는 시간을 가졌다. 8장의 대신증권 크레온 플러스 API를 이용한 계좌정보 조회, 매수/매도 주문은 여건상 생략하였다.