かじったばかりのディープラーニングで日経平均のアップダウン予測を試みました。
株の知識はほとんどないものの、単純な方法、「サルでも勝てる」投資法が運よく見つかればいいな、うまくいくようなら実際の売買も始めようかな、と割と本気で考えました。
やろうとしたのはこんな感じ。

過去 n 日の騰落(上昇 or 下落)をもとに明日の騰落を当てる。
・・・・
全然ダメでした。
n をいろいろ変えて試しましたが、予測正解率は安定的にほぼ 50 %。。どうしようもない数字。
せめて性能が悪いほうに振れて、正解率 20% とかを叩きだしてくれれば逆方向に賭けることもできるのですが。
株もディープラーニングもまったく素人なので当たり前といえば当たり前の結果かもしれません。
で、予測のほうは一旦中止して、なぜ予測が上手くいかないのか考えてみました。
とりあえず、日経平均を python の pandas に読み込み、いろいろ探ってみます。
株価データはこちらで入手。
株価読み込み
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import numpy as np import pandas as pd from pandas import Series files = [u'日経平均_2010.csv', u'日経平均_2011.csv', u'日経平均_2012.csv', u'日経平均_2013.csv', u'日経平均_2014.csv', u'日経平均_2015.csv', u'日経平均_2016.csv'] dfs = [] for f in files: dfs.append(pd.read_csv(f, encoding='shift-jis')) df = dfs[0] for i in range(1, len(dfs)): df = df.append(dfs[i]) df = df.sort_values(by=u'日付').reset_index(drop=True) |
df の中身はこうなってます。
1 2 3 4 5 6 7 8 9 10 11 12 |
日付 始値 高値 安値 終値 0 2010-01-04 10609.34 10694.49 10608.14 10654.79 1 2010-01-05 10719.44 10791.04 10655.57 10681.83 2 2010-01-06 10709.55 10768.61 10661.17 10731.45 3 2010-01-07 10742.75 10774.00 10636.67 10681.66 4 2010-01-08 10743.30 10816.45 10677.56 10798.32 ... ... ... ... ... ... 1622 2016-08-15 16866.89 16932.11 16844.58 16869.56 1623 2016-08-16 16878.66 16887.57 16596.51 16596.51 1624 2016-08-17 16596.26 16772.11 16596.26 16745.64 1625 2016-08-18 16649.91 16714.61 16481.41 16486.01 1626 2016-08-19 16558.38 16613.04 16452.62 16545.82 |
騰落を追加
ここに、今日の騰落と翌日~4日後までの騰落を追加します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
yesterday = df[u'終値'].shift(1) df[u'騰落率'] = np.round(((df[u'終値'] - yesterday)/yesterday * 100.0), 2) df[u'騰落'] = [1 if x > 0 else 0 for x in df[u'騰落率']] df[u'騰落(+1)'] = df[u'騰落'].shift(-1) df[u'騰落(+2)'] = df[u'騰落'].shift(-2) df[u'騰落(+3)'] = df[u'騰落'].shift(-3) df[u'騰落(+4)'] = df[u'騰落'].shift(-4) df = df.drop([u'始値', u'高値', u'安値'], axis=1) df = df.dropna().reset_index(drop=True) df[u'騰落(+1)'] = df[u'騰落(+1)'].astype(np.int) df[u'騰落(+2)'] = df[u'騰落(+2)'].astype(np.int) df[u'騰落(+3)'] = df[u'騰落(+3)'].astype(np.int) df[u'騰落(+4)'] = df[u'騰落(+4)'].astype(np.int) |
こうなります。
1 2 3 4 5 6 7 |
日付 終値 騰落率 騰落 騰落(+1) 騰落(+2) 騰落(+3) 騰落(+4) 0 2010-01-05 10681.83 0.25 1 1 0 1 1 1 2010-01-06 10731.45 0.46 1 0 1 1 0 2 2010-01-07 10681.66 -0.46 0 1 1 0 1 3 2010-01-08 10798.32 1.09 1 1 0 1 1 4 2010-01-12 10879.14 0.75 1 0 1 1 0 ... ... ... ... .. ... ... ... ... |
1 が上昇、0 が下落です。
これで、5日分の騰落がどう推移するか見てみます。
騰落の推移
まず、上昇した日と下落した日の割合を確認してみます。
1 2 3 4 5 6 |
df.groupby(u'騰落').size() #------------ # 騰落 # 0 769 # 1 853 #------------ |
下落が 769日、上昇が 853日です。
比率になおすと、下落が 47% 強、上昇が 52% 強で、ほぼ半々です。
今日と明日
では、今日の騰落と明日の騰落はどのように推移するのでしょうか。
1 2 3 4 5 6 7 8 |
df.groupby([u'騰落', u'騰落(+1)']).size() #------------------------ # 騰落 騰落(+1) # 0 0 356 # 1 413 # 1 0 414 # 1 439 #------------------------ |
下落した翌日は、356日が下落、413日が上昇。比率は 46% と 54% です。
上昇した翌日は、414日が下落、439日が上昇。比率は 49% と 51% です。
続落または連騰した翌日
では、続落または連騰した翌日はどうでしょう。
逆方向に動きがちなら、そちらに賭けて丸儲けですが。。。
1 2 3 4 5 6 7 8 9 10 11 12 |
df.groupby([u'騰落', u'騰落(+1)', u'騰落(+2)']).size() #---------------------------------- # 騰落 騰落(+1) 騰落(+2) # 0 0 0 165 ← 続落後の下落 # 1 191 ← 続落後の上昇 # 1 0 196 # 1 217 # 1 0 0 191 # 1 223 # 1 0 218 ← 連騰後の下落 # 1 221 ← 連騰後の上昇 #---------------------------------- |
続落した翌日は、下落が 46%、上昇が 54% です。
連騰した翌日は、下落と上昇がほぼ 50% です。
ダメですね。丸儲けできません。
3日続落、または3連騰の翌日
では、3日続落、または3連騰の翌日はどうでしょうか。
さすがに方向感があるのでは。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
df.groupby([u'騰落', u'騰落(+1)', u'騰落(+2)', u'騰落(+3)']).size() #------------------------------------------ # 騰落 騰落(+1) 騰落(+2) 騰落(+3) # 0 0 0 0 75 ← 続落後の下落 # 1 90 ← 続落後の上昇 # 1 0 85 # 1 106 # 1 0 0 92 # 1 104 # 1 0 114 # 1 103 # 1 0 0 0 90 # 1 101 # 1 0 112 # 1 111 # 1 0 0 99 # 1 119 # 1 0 103 ← 連騰後の下落 # 1 118 ← 連騰後の上昇 #------------------------------------------ |
3日続落した翌日は、下落が 45%、上昇が 55% です。
3日連騰した翌日は、下落が 47%、上昇が 53% です。
方向感、まったくなし。
4日続落、または4連騰の翌日
最後、4日続落、または4連騰の翌日はどうでしょうか。
なんか、期待薄ですが、一応見てみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
df.groupby([u'騰落', u'騰落(+1)', u'騰落(+2)', u'騰落(+3)', u'騰落(+4)']).size() #--------------------------------------------------- # 騰落 騰落(+1) 騰落(+2) 騰落(+3) 騰落(+4) # 0 0 0 0 0 30 ← 続落後の下落 # 1 45 ← 続落後の上昇 # 1 0 35 # 1 55 # # ~ 省略 ~ # # 1 0 0 44 # 1 59 # 1 0 56 ← 連騰後の下落 # 1 62 ← 連騰後の上昇 #--------------------------------------------------- |
4日続落した翌日は、下落が 40%、上昇が 60% です。
4日連騰した翌日は、下落が 47%、上昇が 53% です。
騰落の推移を見て明日の騰落を当てるのは無理っぽいです。
50% 前後に落ち着くというのは、つまり、コイントスの裏表を見て次はどっちか当てるようなもので、確率 2分の1で当たり外れが続くだけです。
…というのが結論ですが、次節でもう少しだけ見てみます。
騰落の率を考慮
株価が上がるといっても 1円 上がるのと 100円あがるのでは重みが違います。そこで、騰落の大きさを考慮しようと思うのですが、そもそも、日経平均というのは、どの程度の変動幅で動くのでしょうか。
1 |
df[u'騰落率'].hist(bins = 20) |
横軸が騰落率、縦が件数です。
大半の日は 2% 未満の騰落率に収まっています。
単純な想像ですが、
2% 以上、つまり大幅に上下した翌日は逆方向に動きやすいのでは?
2% 以上 上昇した翌日
1 2 3 4 5 6 |
df[df[u'騰落率'] >= 2.0].groupby(u'騰落(+1)').size() #-------------- # 騰落(+1) # 0 51 # 1 61 #-------------- |
下落が 46%、上昇が 54% でした。
2% 以上 下落した翌日
1 2 3 4 5 6 |
df[df[u'騰落率'] <= -2.0].groupby(u'騰落(+1)').size() #-------------- # 騰落(+1) # 0 45 # 1 67 #-------------- |
下落が 40%、上昇が 60% でした。
大幅に上下した翌日でも、どちらに動くかはほぼ半々なようです。
今日と明日の騰落率を可視化
今日の騰落率が明日の騰落率に影響する(つまり、相関性がある)かどうか可視化してみます。
1 2 3 4 5 6 7 8 9 |
import matplotlib.pyplot as plt df[u'騰落率(+1)'] = df[u'騰落率'].shift(-1) df = df.dropna().reset_index(drop=True) plt.scatter(df[u'騰落率'], df[u'騰落率(+1)']) plt.gca().set_aspect('equal', adjustable='box') plt.xlabel('today') plt.ylabel('tommorow') |
どうなんでしょうか。
大半のデータは中央の円に収まっているので相関性はないような気がします。
率が 5% を超えるような場合は、右下がりになっているようにも見えますが(つまり、5% 超動いた翌日は反対に動く ?)、件数は微々たるもので、あまり当てにはなりません。
5%以上動く日数は
1 2 3 4 5 6 7 8 9 |
(np.abs(df[u'騰落率']) >= 5.0).sum() #----- # 11 #----- len(df) #------ # 1621 #------ |
1621日中、11日しかありません。
まとめ
単純に騰落を当てるのは無理でした。
為替やアメリカ株を取り入れれば少しは当たるのかもしれませんが、それだと仕込むタイミングが難しい。
移動平均を求めてゴールデンクロスやデッドクロスを考慮すれば、あるいは、という気もしますが。
ちなみに、移動平均は rolling_mean で求まります。
1 2 |
df[u'終値'].rolling(5).mean() # 5日移動平均 df[u'終値'].rolling(25).mean() # 25日移動平均 |
そもそも株価は時系列な情報ですから、RNN で処理するといいのかもしれません。でも、RNN はハードル高そう。。。
hoge says:
関係者ではありませんが,keras がオススメです
http://qiita.com/yukiB/items/5d5b202af86e3c587843
管理人 says:
hogeさん、どうも。
読んでみました。tensorflowのラッパーなんですね。
windowsで簡単に動くようですし、取っつきやすいかもしれませんね。
sin波のように株価を当ててみたいです。
匿名 says:
good
ミヤタ シンイチ says:
サイトからの突然のコメントで申し訳ございません。
初めまして。投資情報サイトGogoJungleを運営しています株式会社ゴゴジャンの宮田と申します。
サイトを拝読しましてコメントしました。
今回、コメントしました理由としましては、プログラミングに関しまして、目にとまってしまいました。
また、恐縮ではございますが、プログラミングの知識を、インジケーター・投資ナビ+の記事として投資情報サイトGogojungleでご掲載していただけいる力は十分にお持ちではないかと思い、コメント致しました。
ただ、どんな会社かもお分かりにくいかと思います。
初めての方でも商品作成~販売まで全て無料でサポートいたしますので、お気軽にお問合せください。
◆掲載ページ◆
https://www.gogojungle.co.jp/
詳しくはメールにてお問い合わせください!
ご連絡心よりお待ちしています。
株式会社ゴゴジャン smiyata@gogojungle.co.jp
宮田
ささ says:
正解率が50%当たりになるのは当然なのです。騰落率の上がる下がるの回数比も50%当たりで特徴がないからです。特徴のあるデータに加工して入力するのがよいですよ