SW/주가 예측

비트코인 주식 예측 프로그램 : 파이썬, 텐서플로우, 케라스, RNN 예제

얇은생각 2019. 6. 14. 12:30
반응형

주식 예측 프로그램을 만들기 전에 공부 차원에서 비트코인 프로그램을 만들어 보겠습니다. 해당 프로그램은 파이썬과 케라스를 활용합니다. 우선 해당 라이브러리는 다음과 같습니다.



get_ipython().run_line_magic('matplotlib', 'inline')
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import plotly as py
import plotly.graph_objs as go
import requests
from keras.layers import *
from keras.models import *
from keras.callbacks import *
from datetime import datetime
from sklearn.preprocessing import MinMaxScaler
plt.style.use('bmh')



'''
https://poloniex.com/public?
command=returnChartData&currencyPair=USDT_BTC&
start=1405699200&end=9999999999&period=14400
'''


poloniex에서 제공하는 api를 활용합니다. url을 들어가보면 해당 비트코인의 일봉 데이터를 확인할 수 있습니다.




ret = requests.get('https://poloniex.com/public?command=returnChartData&
currencyPair=USDT_BTC&start=1405699200&end=9999999999&period=86400')
print(ret)


<Response [200]>


데이터를 잘 받아왔다면 위와 같이 리턴합니다.





js = ret.json()
print(js)

# [{'date': 1424304000,
# 'high': 244,
# 'low': 225,
# 'open': 225,
# 'close': 244,
# 'volume': 46.27631267,
# 'quoteVolume': 0.19311748,
# 'weightedAverage': 239.62777823},
# {'date': 1424390400,
# 'high': 245,
# 'low': 240.25,
# 'open': 240.25011809,
# 'close': 240.25,
# 'volume': 55.894897,
# 'quoteVolume': 0.23042935,
# 'weightedAverage': 242.56847926}, ...


받은 값을 json으로 변환하여 프린트해봅니다. 위 주석과 같이 나오면 정상적으로 동작한 것입니다. 해당 날짜에 포함하는 데이터들 종류와 값들을 확인하실 수 있습니다.





df = pd.DataFrame(js)
scaler = MinMaxScaler()
df[['close']] = scaler.fit_transform(df[['close']])
print(df)

# close date high low open \
# 0 0.003428 1424304000 244.000000 225.000000 225.000000
# 1 0.003231 1424390400 245.000000 240.250000 240.250118
# 2 0.003480 1424476800 245.000000 245.000000 245.000000
# 3 0.002955 1424563200 249.000000 235.000000 245.000000
# 4 0.002955 1424649600 235.001000 235.000000 235.000002
# 5 0.003205 1424736000 239.750000 235.000000 235.000000



이제 해당 데이터 중에 종가를 가지고 예측 프로그램을 만들 것입니다. 따라서 해당 값들을 MinMaxScaler를 활용하여 변형해줍니다. 위 주석과 같이 종가 데이터가 변형된 것을 확인할 수 있습니다.





price = df['close'].values.tolist()
print(price)

# [0.0034278368698297933, 0.0032309273586996947, 0.0034803460727978203,
# 0.0029552540431175573, 0.0029552540431175573, 0.003204672757215681,
# 0.003099654351279629, ...



이제 종가 데이터를 price라는 변수웨 담도록 하겠습니다. price에 다음과 같이 리스트에 담긴 것을 확인할 수 있습니다.





window_size = 5
x = []
y = []

for i in range(len(price) - window_size):
x.append([price[i+j] for j in range(window_size)])
y.append(price[window_size + i])
print(x)
print(y)

# [[0.0034278368698297933, 0.0032309273586996947, 0.0034803460727978203,
# 0.0029552540431175573, 0.0029552540431175573], [0.0032309273586996947,
# 0.0034803460727978203, 0.0029552540431175573, 0.0029552540431175573,
# 0.003204672757215681], ...


5일치의 데이터를 가지고 다음 데이터를 예측하도록 모델링을 해보았습니다. 따라서 5일치 만큼 x에 값을 넣어주고 6일 째에는 y 데이터를 넣어주는 방식으로 값을 담아줍니다. 위와 같이 잘 담기는 것을 확인할 수 있습니다.





x = np.asarray(x)
y = np.asarray(y)
print(x)
print(y)

# [[0.00342784 0.00323093 0.00348035 0.00295525 0.00295525]
# [0.00323093 0.00348035 0.00295525 0.00295525 0.00320467]
# [0.00348035 0.00295525 0.00295525 0.00320467 0.00309965]
# ...
# [0.43918916 0.44873165 0.41690845 0.39448956 0.39879563]
# [0.44873165 0.41690845 0.39448956 0.39879563 0.39938984]
# [0.41690845 0.39448956 0.39879563 0.39938984 0.41037416]]
#
# [0.00320467 0.00309965 0.00313904 ... 0.39938984 0.41037416 0.40618453]


데이터를 보기 좋게 정렬을 해봅니다. 5개의 데이터들이 들어가 있고, y데이터는 1개씩 들어가 있는 것을 확인할 수 있습니다. numpy가 아직 익숙하지 않지만 잘 활용하면 매우 유용할 것 같습니다.





train_test_split = 1000

x_train = x[:train_test_split, :]
y_train = y[:train_test_split]

x_test = x[train_test_split:, :]
y_test = y[train_test_split :]

print(x_test.shape)
# (566, 5)

print(x_train[0])
# [0.00342784 0.00323093 0.00348035 0.00295525 0.00295525]



이제 훈련 데이터를 분리해보겠습니다. 천개의 데이터를 훈련 데이터로 활용하겠습니다. 저는 금일 확인해본결과 테스트 데이터는 566개이네요. 날이 갈수록 늘어나니 유의해주세요. 훈련 데이터는 잘 담겼는지 한개만 찍어보았습니다. 잘 들어가있는 것을 확인하였습니다.





model = Sequential()
model.add(LSTM(128, input_shape=(5,1,)))
model.add(Dropout(0,2))
model.add(Dense(1, activation='linear'))
model.compile(loss='mse', optimizer='adam')
model.summary()

# _________________________________________________________________
# Layer (type) Output Shape Param #
# =================================================================
# lstm_1 (LSTM) (None, 128) 66560
# _________________________________________________________________
# dropout_1 (Dropout) (None, 128) 0
# _________________________________________________________________
# dense_1 (Dense) (None, 1) 129
# =================================================================
# Total params: 66,689
# Trainable params: 66,689
# Non-trainable params: 0
# _________________________________________________________________


모델은 다음과 같이 구현하였습니다. LSTM을 활용하였습니다. 여러가지의 모델을 만들어서 실습을 진행해보아도 재밌는 결과들이 나타날 것 같습니다.





model.fit(x_train, y_train, epochs=100, batch_size=1)

# Epoch 1/100
# 1000/1000 [==============================] - 6s 6ms/step - loss: 4.0569e-04
# Epoch 2/100
# 1000/1000 [==============================] - 6s 6ms/step - loss: 1.5022e-04
# Epoch 3/100 ...


이제 훈련데이터를 활용해 훈련을 진행해보겠습니다. 저는 10번과 100번을 나누어 훈련을 진행해보았습니다.




train_predict = model.predict(x_train)
test_predict = model.predict(x_test)

plt.figure(figsize=(10,10))
plt.plot(price)

split_pt = train_test_split + window_size
plt.plot(np.arange(window_size, split_pt, 1), train_predict, color='g')

plt.plot(np.arange(split_pt, split_pt + len(test_predict), 1), test_predict, color='r')




훈련한 데이터와 예측한 데이터와 실제 데이터를 그래프로 표현해보았습니다. 파랑색이 실제 데이터입니다. 초록색은 훈련한 데이터입니다. 빨간색은 실제 예측한 데이터입니다. 생각보다 유효한 결과를 확인할 수 있었습니다.





trace = go.Scatter(x=np.arange(1,len(price),1), y=price,
mode = 'lines', name='original')
trace2 = go.Scatter(x=np.arange(window_size,split_pt,1), y=train_predict.reshape(1000),
mode = 'lines', name='train')
trace3 = go.Scatter(x=np.arange(split_pt,split_pt + len(test_predict),1), y=test_predict.reshape(566),
mode = 'lines', name='pred')

data = [trace, trace2, trace3]
py.offline.plot(data)


이제 좀 더 자세한 그래프를 보기 위해 Scatter와 plotly를 사용하였습니다. 결과는 아래와 같습니다.


1. 10번 훈련



2. 100번 훈련한 결과


위와 같이 100번 훈련한 결과가 훨씬 잘 예측하고 있다는 것을 확인할 수 있었습니다. 적절한 모델과 훈련 정도, 데이터들을 활용한다면 어느정도 유의미한 결과를 도출할 수 있다는 생각이 들었습니다.


그렇다면 이 프로그램을 활용해서 실제 비트코인을 예측할 수 있을까요? 개인적으로 위험하다고 생각합니다.


하지만 여러 알고리즘과 시그널들을 활용해서 실질적으로 도입하고 있는 업계도 있는 것으로 알고 있습니다. 단순히 현재 이 프로그램만으로는 예측이 어렵지만 충분한 공부와 노력을 통한다면 유의미한 결과도 얻어낼 수 있을 것이라 생각합니다.



반응형