はじめに
Bitcoinのチャートの予測(明日の価格の上げ下げ)を予測するプログラムを作るために、pythonでscikit-learnの決定木アルゴリズムを用いて価格予測をすることにしました。
過去N日間の価格(N個のパラメータ)から次の日の価格が上がるか下がるか変わらないのかを予測するというものです。
なお、bitcoinの価格データは、Bitcoin Historical Data からダウンロードしたbitstampUSD_1-min_data_2012-01-01_to_2017-10-20.csv
というファイルを利用しました。
コード
python
from sklearn import tree
import pandas as pd
import numpy as np
#教師データ作成
train_data_num=100
test_data_num=20
parameter_num=30
train_y=[]
test_y=[]
df = pd.read_csv("bitcoin.csv")
df = df[df.Timestamp > 1483196400]
df = df[df.Timestamp%86400==0]
df = df.loc[:,['Close']]
dfx = pd.DataFrame(index=[], columns=['1'] * parameter_num)
dfy = pd.DataFrame(index=[], columns=['1'])
testdfx = pd.DataFrame(index=[], columns=['1'] * parameter_num)
testdfy = pd.DataFrame(index=[], columns=['1'])
for i in range(train_data_num):
#教師データx
t_df_x = df[i:i+parameter_num].T
t_df_x = t_df_x.as_matrix()[0]
s_df_x = pd.Series(t_df_x, index=dfx.columns)
dfx = dfx.append(s_df_x, ignore_index = True)
#教師データy
t_df_y1=df[i+parameter_num-1:i+parameter_num].T
t_df_y1 = t_df_y1.as_matrix()[0]
t_df_y2=df[i+parameter_num:i+parameter_num+1].T
t_df_y2 = t_df_y2.as_matrix()[0]
t_df_y=t_df_y2-t_df_y1
s_df_y = pd.Series(t_df_y, index=dfy.columns)
train_y.append(s_df_y.values[0])
for i in range(test_data_num):
#評価データx
test_t_df_x = df[i+train_data_num+train_data_num:i+train_data_num+train_data_num+parameter_num].T
test_t_df_x = test_t_df_x.as_matrix()[0]
test_s_df_x = pd.Series(test_t_df_x, index=testdfx.columns)
testdfx = testdfx.append(test_s_df_x, ignore_index = True)
#評価データy
test_t_df_y1=df[i+train_data_num+train_data_num+parameter_num-1:i+train_data_num+train_data_num+parameter_num].T
test_t_df_y1 = test_t_df_y1.as_matrix()[0]
test_t_df_y2=df[i+train_data_num+train_data_num+parameter_num:i+train_data_num+train_data_num+parameter_num+1].T
test_t_df_y2 = test_t_df_y2.as_matrix()[0]
test_t_df_y=test_t_df_y2-test_t_df_y1
test_s_df_y = pd.Series(test_t_df_y, index=testdfy.columns)
test_y.append(test_s_df_y.values[0])
train_x =np.array(dfx.as_matrix())
train_x = (train_x - np.mean(train_x))/np.std(train_x) #正規化
train_y = np.array(np.sign(train_y))
test_x =np.array(testdfx.as_matrix())
test_x = (test_x - np.mean(test_x))/np.std(test_x) #正規化
test_y = np.array(np.sign(test_y))
#分類器(決定木)
clf = tree.DecisionTreeClassifier(max_depth=5)
#学習
clf = clf.fit(train_x, train_y)
#予測
predicted = clf.predict(test_x)
#精度の出力
print(sum(predicted == test_y) / len(test_y))
#決定木の出力(Python)
import pydotplus
from sklearn.externals.six import StringIO
dot_data = StringIO()
tree.export_graphviz(clf, out_file=dot_data)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
from IPython.display import Image
Image(graph.create_png())
pandasの使い方がいまいちよく分かっていませんので、おかしなことを書いているかもしれません。
*2017/11/28 修正
データの正規化を忘れていて、コメントで指摘を頂いたので、正規化コードを追加しました。データの平均を0, 標準偏差を1に設定しました。
結果
df = df[df.Timestamp > 1483196400]
のタイムスタンプの値を色々変えて、精度を確かめてみたところ、0.45~0.65の値を取りました。
使える精度ではないかもしれません。
参考文献
機械学習で未来を予測する - scikit-learn の決定木で未来の株価を予測
scikit-learn で決定木分析 (CART 法)