computer_IT

(파이썬 증권데이터 분석) 순환신경망을 이용한 주가 예측(딥러닝)

LifenLight 2022. 7. 24. 20:35
반응형

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를 이용한 계좌정보 조회, 매수/매도 주문은 여건상 생략하였다.

반응형