Contents
株価データを機械学習する上での前処理の方法
Qiitaに非常にわかりやすい画像があったので、使わせてもらいます。
参照:https://qiita.com/ynakayama/items/6a472e5ebbe9365186bd
普通の機械学習の流れは、有名なアヤメ(iris)の例でいくと以下のようになります。
変数①(花弁の長さ) | 変数②(茎の長さ)… | 正解ラベル(アヤメの種類) |
---|---|---|
5.0 | 3.0… | 1 |
4.6 | 3.2… | 0 |
ですが、時系列データの場合は変数となるのは過去の自分のデータになるので以下のようになります。
変数①(7日前の株価)… | …変数②(1日前の株価データ) | 正解ラベル(当日の株価データ) |
---|---|---|
18000円… | …17800円 | 18100円 |
16700円… | …17000円 | 16700円 |
機械学習のモデルに当てはめる場合は、価格データをそのまま放り込むとモデルの精度が悪くなるので、変化率や対数変化率に当てはめることが一般的です。
機械学習用に株価データを用意する
Pythonでの株価データの取得(スクレイピング)がpandas-datareaderで簡単にできます。
#ライブラリのインストール import pandas_datareader.data as web import datetime #日経平均株価を取得する nikkei=web.DataReader("NIKKEI225","fred","1950/5/16","2019/5/17") nikkei.head()
NIKKEI225 | |
---|---|
DATE | |
1950-05-16 | 95.16 |
1950-05-17 | 96.10 |
1950-05-18 | 96.02 |
1950-05-19 | 97.72 |
1950-05-22 | 96.87 |
これで機械学習のもとになる株価データ自体は用意はできました、ここからこの株価データを機械学習モデルに当てはめられるように前処理していきます。
機械学習における株価データ(時系列データ)の前処理
・株価データは対数収益率に変換する
#対数収益率に変換する nikkei['log_change']=np.log(nikkei['NIKKEI225'])-np.log(nikkei['NIKKEI225'].shift(1))
これで株価を対数収益率に変換することができました。次の株価データなどの前処理としては、1週間の株価の値動きを1つのデータとして、1日づつずらしたデータセットを作成する運びとなります。
例えばもし10日間分の株価データがあったとして、それを3日間分の値動きを教師データにして4日目の価格を正解データにしたい場合はデータを以下のように成型する必要があります。
元データ | 機械学習できるように前処理した株価データ | ||||||
1日目の株価 | 変数① | 変数② | 変数③ | 正解ラベル | |||
2日目の株価 | 1日目の株価 | 2日目の株価 | 3日目の株価 | 4日目の株価 | |||
3日目の株価 | 2日目の株価 | 3日目の株価 | 4日目の株価 | 5日目の株価 | |||
4日目の株価 | → | 3日目の株価 | 4日目の株価 | 5日目の株価 | 6日目の株価 | ||
5日目の株価 | 4日目の株価 | 5日目の株価 | 6日目の株価 | 7日目の株価 | |||
6日目の株価 | 5日目の株価 | 6日目の株価 | 7日目の株価 | 8日目の株価 | |||
7日目の株価 | 6日目の株価 | 7日目の株価 | 8日目の株価 | 9日目の株価 | |||
8日目の株価 | 7日目の株価 | 8日目の株価 | 9日目の株価 | 10日目の株価 | |||
9日目の株価 | |||||||
10日目の株価 |
term=7 pricedata=[] answer=[] nikkei2=nikkei['log_change'].values length=len(nikkei2) for i in range(0,length-term-1): pricedata.append(nikkei2[i:i+term]) answer.append(nikkei2[i+term]) data=pd.DataFrame(np.array(pricedata).reshape(-1,7)) df=pd.concat([data,pd.DataFrame(answer)],axis=1) df.columns = ['1日目', '2日目', '3日目','4日目', '5日目', '6日目','7日目','label(8日目)'] df.head()
先頭に欠損値が入っているので削除します。
#欠損値を削除する df=df.dropna()
これで機械学習用に株価データが整形できました。株価データの機械学習やディープラーニングでよく使う期間は1週間(7日)や1か月(30日)です。
そして機械学習の分析アプローチには「回帰」と「分類」の2種類があり、分類で機械学習を行う場合であれば、正解ラベルは上がった(1)か、下がった(0)かの1と0の2つのラベルのしておきます。
for i in range(1,len(df)): if df['label(8日目)'][i]>0: df['label(8日目)'][i]=1 elif df['label(8日目)'][i]<0: df['label(8日目)'][i]=0 df.head()
次はデータをテストデータと訓練用データに分割します
#Xデータ,Yデータを用意する x=np.array(df.drop(['label(8日目)'],axis=1)) y=np.array(df['label(8日目)']) #XとYを訓練用とテスト用に分割する from sklearn.model_selection import train_test_split (X_train, X_test,y_train, y_test) = train_test_split(x, y, test_size=0.3, random_state=0,shuffle=False)
今回の分析対象は時系列データなので、テストに未来のデータが来るようにするため、引数の部分をrandom_state=0,shuffle=Falseとして、データを混ぜずにそのままスッパリ分割するようします。
XとYの中身は↓のようになっています。
これで前処理は完了ですので、本題の決定木による株価データの機械学習に移っていきたいと思います。
株価データを機械学習モデルに当てはめる
機械学習アルゴリズムはいろいろありますが、今回はまず決定木という機械学習アルゴリズムを使って機械学習を行っていきたいと思います。なぜ決定木なのかというと、決定木はコンピュータ^がなにを持って分類しているかが分かりやすくかつ、比較的精度が高いことが多いからです。
#決定木アルゴリズムで計算する from sklearn import tree clf = tree.DecisionTreeClassifier(max_depth=10) clf = clf.fit(X_train, y_train) #作成した機械学習モデルをテストデータに当てはめる predicted = clf.predict(X_test) # モデルのテストデータに対する精度を確認 score=sum(predicted == y_test) / len(y_test) print('モデルの精度は{}%です'.format(score*100))
<実行結果>
モデルの精度は50.84548104956268%です
・・・ダメみたいですね。
モデルによる収益リターンを確認する
ここまでがよくある機械学習での分類ですが、今回は株価データなので、そのモデルに従って取引した結果のリターンがどうなったのかも確認していきます。
リターンの確認方法は実際の対数収益率にモデルによる判断(1 or 0)を掛け合わせた累積収益率を計算するだけです。
#データを分割する train_answer,test_answer=train_test_split(answer,test_size=0.3, random_state=0,shuffle=False) #リターンを計算する returns=predicted*np.array(test_answer) total_return=(1 + returns).cumprod() print('モデルによる{}日間のトレードのリターンは{}%です'.format(len(total_return),total_return[-1])) #csvにして出力する nikkei.to_csv(path_or_buf='nikkei_0520.csv')
<実行結果>
モデルによる5145日間のトレードのリターンは0.7145870969923697%です。
リターンは0.71%なので10000円から始めて、5145日間トレードすると71円になる計算になります。散々な結果到底使えません。
終わり
株価データは基本的に何のひねりも入れずに機械学習やディープラーニングをしても他のデータのようにきれいな結果はでません。
テクニカル指標やボラティリティなんかで場合わけしたりすると予測精度が上がるかもしれません。私自身現在いろいろと試行錯誤している最中です。
関連記事:【Scikit-learn】ビットコインの価格を機械学習で予測してみる
関連記事:【Python】株価データをローソク足にして移動平均と一緒にプロットしてみる
コメント
[…] 関連記事:【Python】機械学習で株価を予測する~Scikit-Learnの決定木アルゴリズムを使う […]