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

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

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

プログラミングの独学はとても難しい


プログラミングは小学校の義務教育にも導入され始めており、これから社会人として生きていく上でプログラミングはもはや出来て当たり前、出来なれば論外というエクセルレベルの必須スキルになりつつあります。そしてそういう話を聞いて参考書なりを購入して独学でプログラミング勉強しようと思っている人も少なくないでしょう。しかしプログラミングを独学で勉強し始めようと思うものの



・「分からない箇所で詰まって挫折してしまった」

・「勉強する時間が足りない」

・「ネットの記事だと情報が断片的でよくわからない」

・「コードのエラーの原因が分からない」



という壁にぶち当たって、プログラミングの勉強を止めてしまう方が少なくありません。独学でプログラミングを勉強してる時間のほとんどはつまづいている時間です。実際僕も最初のころ独学でプログラミングを勉強していた頃はエラーの原因が分からず丸1日を不意にしてしまった・・・そんな苦い経験がありました。



それで僕は一度はプログラミングの学習を諦めてしまいましたが、就活で現実を知る中で「プログラミングを勉強して、いずれフリーランスとして自由な生き方がしたい」「エンジニアとして若いうちから高収入を得たい」という気持ちから一念発起して「侍エンジニアのwebサービスコース」に申し込み、プロのエンジニアの方に対面でマンツーマンでPythonによるWebサービス作り方とWeb技術の基本を教えてもらい、ようやくプログラミングが理解でき、今ではエンジニアとしてそこそこの暮らしができるようになりました。





侍エンジニアでは、とりあえずプログラミングやインターネットの基本を知っておきたい人から、HTML・cssなどでWebサイトやWebアプリを作ってみたい人やPythonを勉強してデータサイエンティストやAIエンジニアになりたい人まで幅広いニーズに応えた様々なコースが用意されています。



IT業界と言ってもエンジニアの仕事はプログラミング言語次第でサーバーから機械学習・ディープラーニングまで多種多様ですし、侍エンジニアの無料レッスン(カウンセリング)を受けてみて、自分のやりたいITの仕事は何なのか?を見つけるのがエンジニアへの第一歩になります。ちなみに今侍エンジニアの無料レッスンを受けると1000円分のAmazonギフト券がもらえるので、試しに受けてみるだけもお得です。


自分は半端に独学やオンラインスクールで勉強して金と時間を無駄にするくらいなら、リアルのプログラミングスクールに通ってしっかりプログラミングを勉強した方がいいと思います。ちなみに今、侍エンジニアに申し込むと、25歳以下の学生の方であれば、受講料が20%OFFになるので超お得です。


そして、プログラミングは大勢で授業を受けたり漫然とオンライン学習をするよりも自分が分からない箇所をピンポイントでプロの講師に直接質問して、ちゃんと納得するというスタイルの方がお金は確かに少し掛かりますが、独学で学ぶよりも絶対にモノになります。


シェアする

  • このエントリーをはてなブックマークに追加

フォローする