きっかけ
ML.NETで、Webカメラで雑に集めたじゃんけんやパン画像のクラス分類をやってみたら(ツールはこちら)すごく簡単に、そしてほぼ正確に予測できた。
これを株価チャートに応用できないだろうか。
株価チャートには、例えば「三尊天井は売りシグナル」など、チャートの形状を売り/買いのシグナルとして捉えるいにしえからの言い伝えがある。
仮にこれが本当だとして、
・何をもってチャートを「~型」と判断するか
・日経225銘柄だけでもそれらのチャート形状をサラリーマンが毎日確認・判断するのはほぼ不可能
という問題がある。
そこで、「チャートの形状を画像分類問題に当てはめてみたらどうなるのだろう」という素朴な疑問から、短絡的に上記のツールで実験してみることにした。
やり方
- 日足の株価データを用意する(今回は2006年5月頃~2018年4月頃までの10年以上、銘柄選定は適当に7201日産/8604野村/9984ソフトバンクの3銘柄とした)
- プログラマブルな株価データ取得・チャート表示ツールを用意する
- ある時点D日の終値から10日後の終値が、+10%以上, +5%以上, -10%以下, -5%以下になる場合、D日をチャートの最終日としたチャートを画像とし、前述の騰落率に応じたフォルダに保存する
- プラスマイナス5%以内に収まる場合のチャートは数が多くなりすぎるため分類対象としない
フォルダ分けの結果、各画像枚数は下表の通りとなった。
+10%以上 | +5%以上 | -5%以下 | -10%以下 |
---|---|---|---|
786枚 | 1233枚 | 1224枚 | 649枚 |
- フォルダ分けした画像を上記のGUIツールで分類しようとしたら固まったので、こちらのCUIツール(GPU版)で実行した
#ポエムなので詳しい方法は割愛させていただきますことをご了承ください
結果
わかりやすく指標の見方を整理されている方の記事を参考にしたところ、Recall(再現率:実際に正であるもののうち,正であると予測されたものの割合)が0.430と、使い物にならない数値となっていることがわかる。
どうにか改善できないか
とりあえず、上がるか下がるかどっちかさえわかればオプションに使えるかも?ということで、チャート画像を次のようにフォルダ分けして再度試してみた。
10日後の終値が+5%以上 | 10日後の終値が-5%以下 |
---|---|
2019枚 | 1873枚 |
4クラスから2クラスへの分類に変えただけで、再現率が0.430→0.703とかなりアップした。
チャート画像を見ると…
お!?(-5%以下88.12%の予測に対し実際も-5%以下。この場合は-10%以下)
おおっ!!?(-5%以下98.16%の予測に対し実際も-5%以下。この場合は-10%以下)
マジすか!!!?(-5%以下92.72%の予測に対し実際も-5%以下)
ズコーーーーーーーーーー (5%以上95.51%の予測に対し実際は-10%以下)
まとめ
チャート画像だけから分類して再現率が7割となると、勝ち負けが同額ならば期待値は、
1.05 x 0.7 + 0.95 x 0.3 = 1.02
となり、1を上回る。つまり、計算上は勝ちゲームとなる。
しかし95%と高い確率の予測ながらハズしている場合もあり、まだまだ検証する必要がある。
あまり期待してはいなかったが、全体的には可能性を感じる(?)結果となった。
もっと銘柄数を増やして検証/バックテストを行ってみる価値はあると感じた。
追記@2021/05/05
検討の結果「使えない」ことがわかりましたので追記です。
最初の検討から、
- 銘柄数を100程度
- 予測の日数を6, 8, 10, 12日先の4通り
- 予測日数までの騰落率をプラスマイナス10, 12, 14, 14, 16%の計10通り
としてチャートを学習させました。(前述の「ImageClassification 」を使用)
同ImageClassificationのClassifier.GetBulkImagePrediction
メソッドに対し、
学習済みモデルおよび銘柄ごとの2010年から2018年までの日足チャート画像約2500ファイルを渡し、予測結果を得ました。ファイル数分の予測結果の中から、確度が95%以上の場合はシグナルとして出力するようにしました。(LINQ使えよ…)
// 作成済みモデルで予測する
var results = ImageClassificationGPU.Classifier.GetBulkImagePrediction(modelDir + "\\pipeline.zip", modelDir + "\\model.zip", tempDir);
results.Sort((a, b) => a.FileName.CompareTo(b.FileName));
foreach (var r in results)
{
if (r.HighScore >= 0.95f)
{
// Scoreが95%以上ならチャート表示用ファイルにフラグを記録する
string dt = r.FileName.Replace($"[{code}]", "").Replace("-", "/").Replace(".png", "");
File.AppendAllText(codeFile, $"{dt},{di.Name},{r.PredictedLabel},{r.HighScore:P}{Environment.NewLine}");
}
}
出力したシグナルファイルをチャートから読み込むように設定し、チャートを確認しました。
部分的に「おっ!?」というシグナルがあると思いきや、全体的には「使えない」ことがわかりました。
これは条件を振った各パターンでも同様でした。
例えば次のような感じです。
例1)ImageClassificationのみで出力した「10日以内に10%以上上げ」シグナル(こんな感じを期待していた)
例2)でも、↓の上げシグナルはハズしている
例3)↓この下げシグナルはまあまあ当たっているが…
例4)上昇トレンド中に下げシグナルが出まくる現象があったり…
そもそもシグナルが少なすぎる上に、期待値を算出するまでもなくハズレが多い感じです。
残念でした~(当たり前か)。
参考サイト
https://qiita.com/hiromasa-masuda/items/e1a3ea60f0c838f17589
https://qiita.com/hiromasa-masuda/items/e0fdfa998856e6428c10
https://qiita.com/FukuharaYohei/items/be89a99c53586fa4e2e4