【Python】機械学習で株価を予測する~Scikit-Learnの決定木アルゴリズムを使う

この記事は約9分で読めます。

 

株価データを機械学習する上での前処理の方法

 

Qiitaに非常にわかりやすい画像があったので、使わせてもらいます。

 

 

https://camo.qiitausercontent.com/b345519e51ec3bfed2e3aefbe74b053dc79e5c13/68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f33383530312f30396130336465642d363830312d393037302d346437362d3466303937393939636561312e706e67

参照: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()

 

 

f:id:oruka199665:20190520140158p:plain

 

先頭に欠損値が入っているので削除します。

 

 

#欠損値を削除する
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】株価データをローソク足にして移動平均と一緒にプロットしてみる

 

コメント

タイトルとURLをコピーしました