ここまでの検証作業では採用閾値変えたり、アンダーサンプリング数変えたり、検証データ複数試したり・・・と検証パターンが大量にあるので試行錯誤に結構時間かかってました。最初は1回の学習自体は数十秒でしたが、データ量増やしたあたりから1分以上かかるようにもなり結構な苦痛です。

 

 だんだんやってられなくなって来たし今後もいろいろなパターンで随時検証していくことも考え、学習モデルの保存と読み込みに対応させたいと思います。 (もっと早くやっとけ!今更気づくなよって話ですが)

 

学習モデルの保存・読み込み

 モデルの読み書きをしてくれるモジュールは「pickle」と「joblib」があるようです。「joblib」は保存サイズを圧縮して小さくしてくれるようですが、その分読み込みも遅くなるとのことなので、とりあえず「pickle」を使ってみます。

 

 「pickle」の使い方は、保存したい場合は

pickle.dump(model , open(filename,'wb'))
#model:学習したモデル、filename:保存先のファイル

 

 

 読み込みたい場合は

model = pickle.load(open(filename, 'rb'))
#model:読み込んだモデルを格納する変数、filename:保存先のファイル

 

これでできるようです。'wb'は書き込みモード(writeのw)とバイナリモード(binaryのb)だそうで、読み込みの場合は'rb'(readのr)ですね。

 

 サイズは「350kb」程度でした。学習モデルってこんなに小さいですね。圧縮なんて必要なさそうです。読み込み時間もほぼ瞬殺。検証データのdataframeへの読み込みと前処理に時間は多少かかって数十秒待ちますが、全体時間は体感的にかなり早くなりました。

 

 プログラム自体は、学習・予測はバギングのため10個モデルを作って予測の平均を取るプログラムでしたので、保存も10回、読み込みも10回行ってバギングにも対応させてます。

 

 学習モデル生成して保存するとき

##学習モデル作成 バギングのためのbagging()関数を10回読んでモデルを配列に格納
model=[]
for i in range(10):
    model.append(bagging(i,X,y))
##bagging関数の内容はLightGBMで学習・検証別記事ご参照。

# 構築したモデルの保存
for m in model:
    filename = "ファイル名" +str( m+1) + ".pkl" ## バギング用に複数ファイル作成対応。連番を付けてモデル格納配列分ファイル名が変わるように。0番をなくすため+1してある。
    pickle.dump(m,open(filename,'wb'))

 

 学習モデルを読み込むとき

##学習モデル読み込み。 バギング分10回読んでモデルを配列に格納
model=[]
for i in range(10):
    filename = "ファイル名" + str(i+1) + ".pkl"
    model.append(pickle.load(open(filename, 'rb')))

 

 これで少しストレスから解放されて検証作業ができるようになる・・・かな。

 投稿がしばらく空いてしまいましたがまた少しずつ書いていきたいと思います。

 

 今回は学習データを思い切って変えてみました。これまでは週次で約52週分の騰落データで様々なアルゴリズムなどを試してきましたが、これを日次騰落ベースにしてみます。

 

新データの概要

 新しいデータは日次の騰落ベースになりますが、以下の条件は変えていません。

  • 学習データは2017年~2021年の株価で週次ベースと同じ約2000銘柄
  • 目的変数は変更せず1週~4週後の株価の騰落率(基本2週後をターゲットに試す)
  • 目的変数は10%以上の上昇(売りケースは下落)を正解とする

 

 データの内容はざっとは以下のような感じにしました。

  • 2017年以降の毎日を基準日に
  • 基準日から見て30日(30取引日)前からの騰落率をセット
  • 株価の騰落率に加えて出来高の増減率も30日分セット
  • 30日間の最大値、最小値と基準日の株価の乖離率をセット(ついでに出来高の最大、最小との乖離も)
  • 基準日の5日平均、25日平均、75日平均との乖離率をセット

 

検証結果(2022年データ)

 2022年のデータで検証しました。週次ベースと比較のため同じようなプログラムで動くように以下の条件は固定で検証しています

  • アルゴリズムはLightGBM
  • アンダーサンプリングは5倍で実施。(正解(目的変数が1)に対し0の行数を5倍に設定
  • バギングは週次ベースの時と同じく10回
  • 検証データの正解は0%以上の上昇(もしくは0%以上の下落)とする
  • 検証データの予測対象日は2022年の全日

 

 この条件で結果を見ていきたいと思います。表の学習データは以下の条件です。

  • 学習1:学習データを火曜のみに絞る
  • 学習2:学習データを全ての日を対象にする

 

買い:0%以上上昇したか?の結果
採用閾値 学習1 学習2
× ×
50%以上 891 824 48.0% 1680 1551 48.0%
55%以上 476 442 48.1% 974 943 49.2%
60%以上 213 220 50.8% 529 511 49.1%
65%以上 89 109 55.1% 260 248 48.8%
70%以上 36 39 52.0% 95 81 46.0%
75%以上 6 7 53.8% 39 22 36.1%
80%以上 0 0 -% 8 7 46.7%

 

 なんとも使えなさそうなモデルですね。採用する予測確率上げても結果は良くなってきません。どの確率でも平均的に勝ちも負けも予測してしまっていますので、何の特徴も捉えられてないってことでしょう。単純に日次の動きからはなかなかパターン化できないようです。

 例えば直近数日の特徴量がプラスだと上がりやすいだとか、チャート理論に近いパターンを見つけるんじゃないかと期待していたんですが、単純に日別に並べただけではダメなようですね。この辺はもうちょっと工夫が必要そうです。

 

 次に売りを見てみます。

 

売り:0%以上下落したか?の結果
採用閾値 学習1 学習2
× ×
50%以上 1645 2666 61.8% 1430 2441 63.1%
55%以上 847 1602 65.4% 765 1531 66.7%
60%以上 450 975 68.4% 411 954 69.9%
65%以上 247 603 70.9% 227 585 72.0%
70%以上 135 380 73.8% 117 351 75.0%
75%以上 51 181 78.0% 42 177 80.8%

<

 

 売りの方はまずまずの結果になりました。なんで同じデータで売りと買いでこんなに傾向が異なってくるか不思議ですが、売りは予想確率が高いほど成績が良い結果になっていて、きちんと傾向捉えて予測できている感じですね。予想確率70%以上だと正答率も75%をただき出してくれてますので利用価値はありそうです。今までの検証結果から推測すると実際に売買しても75%正答率なら利益は出てるでしょう。

 

 あとは、火曜に絞るか全日かでは大きな違いは出なく少し全日データの方が成績も良い状況なのでデータ量が増えた方が精度も多少上がるという感じですね。

 とりあえずデータ変更の結果と考察はこんなところです。

 

 今回は、予測用データ(検証データ)を改良して予測対象日を増やすことを考えてみた記録です。

 

データの改良

 これまで作ってきた機械学習モデルは、主に2017年~2021年の株価を学習データとして2022年度の予測と結果検証を中心に行ってきました。

 データの構造としては週次ベースでの騰落を見てましたので、学習データも検証データも週1回(原則火曜日)を基準日としたデータで行っていました。

 

 これだと毎週火曜日のみが予測日となりますが、検証結果を見ていると予測数に大きな波があってある日に集中したりとか数か月対象がなかったりというケースも見て取れました。もう少し予測での推奨対象を増やすことができないかと思い、毎日予測できるように検証データ側を改良してみたいと思います。

 

 やってみたことはデータの構造は変えずに、データ作成の基準日を週次⇒毎日化する改良です。イメージとしては以下のような感じですね。

 

 

データ変更のイメージ
データ変更イメージ

 

 

 予測用データ作成のプログラムを見直したついでに、学習データも毎日データを作れるようにしました。これで、

  • ①:元々の2017年~2021年の学習データ
  • ②:2017年から2021年の全ての取引日(毎日版)
  • ③:②をベースに火曜だけに絞った版

の3つの学習データパターンとなりました。

 

 ①と③の違いですが、元のデータは火曜が祝日や非取引日の場合は週初の取引日(月曜も祝日なら水曜以降)のデータを作る仕様でした。②は完全に火曜だけのデータに絞ってるので少しだけ違う形になります。

 

データ改良後の正答率の変化

 予測データを毎日化した後の正答率の変化を見てみたいと思います。学習データも3パターンになりましたのでそれぞれで。もちろんアルゴリズムはLightGBM版です。

 予測データの比較対象は「元の予測用データ(火曜ベースの祝日対応あり(学習データの①と同等))」と「毎日対応版データ」の2パターンで年度は2022年度になります。アンダーさんプリンは5倍のみに固定。正答率はとにかく騰がったか(0%以上騰がったか)どうかのみ確認しました。

 

 「買い」と「売り」両方を検証しています。まずは買いから。

 

買い(0%以上上昇したか?)の結果
採用閾値 学習データ① 学習データ② 学習データ③
元の予測データ 毎日化データ 元の予測データ 毎日化データ 元の予測データ 毎日化データ
× × × × × ×
45%以上 317 953 75.0% 1075 2408 69.1% 326 321 49.6% 1515 1440 48.7% 304 985 76.4% 990 2274 71.6%
50%以上 104 687 86.9% 319 1466 81.9% 102 105 50.7% 469 470 50.1% 112 694 86.1% 260 1411 84.4%
55%以上 49 490 90.9% 106 899 89.5% 25 33 56.9% 141 151 51.7% 43 501 92.1% 86 920 91.5%
60%以上 17 314 94.9% 39 503 92.8% 4 10 71.4% 44 45 50.6% 21 344 94.2% 36 578 94.1%
65%以上 10 181 94.8% 17 245 93.5% 1 2 66.7% 12 15 55.6% 11 192 94.6% 21 287 93.2%

 

 ますは元々の学習データ①の中での毎日化の結果から。毎日化することで少し悪化しています。それでも閾値50%以上でも正答率は80%以上は維持してるので充分使えそうですね。対象も約3倍に増えてるので売買機会も増加が期待できそうです(日々の予測対象の発生有無の偏りまでは見てませんが)

 

 次に②の学習データで見ると、ん?、成績も悪化してるし予測対象数も減っている。銘柄数を増やしたときには成績が圧倒的に上がったんですが、同じ銘柄数で対象日数増やすとこうなるんですね。過学習とか不均衡データなどの機械学習の問題なのか株価変動の特性なのか良く分かりませんが。

 ②のデータで火曜だけに絞った場合の③の学習データは①とほぼ近い値をたたき出してくれてます。大半のデータは同じはずなので当たり前でしょうが、少し成績が上がってるのがうれしいところですね。

 

 ここで少し面白いことに気づきました。学習データが毎日化された②は、検証データが火曜のパターンと毎日化のパターンで予測対象数に約5倍の差があります。ほぼ曜日が増えた分だけきれいに対象数が増えてる感じです。これに比べて①と③は約3倍程度です。ここから見るとそもそも株価自体に曜日特性があって、火曜の変動パターンが見事にはまってくれてるのかもしれません。他の曜日でも同じ波動で動く上昇をうまくとらえて予測してくれてると思いました。まあとにかく最初に火曜を選択して学習データ作ったこと自体がラッキーだったのかもしれませんが火曜ベースの学習データは結構使えることが分かりました。

 

 次に「売り」に関してです。まずは結果から

 

売り(0%以上下落したか?)の結果
採用閾値 学習データ① 学習データ② 学習データ③
元の予測データ 毎日化データ 元の予測データ 毎日化データ 元の予測データ 毎日化データ
× × × × × ×
65%以上 74 149 66.8% 1107 1284 53.7% 154 198 56.3% 821 1068 56.5% 79 177 69.1% 1028 1302 55.9%
70%以上 33 87 72.5% 570 739 56.5% 73 108 59.7% 342 575 62.7% 44 99 69.2% 543 739 57.6%
75%以上 11 49 81.7% 267 367 57.9% 21 48 69.6% 95 237 71.4% 14 55 79.7% 242 388 61.6%
80%以上 3 10 76.9% 115 165 58.9% 2 14 87.5% 18 52 74.3% 5 27 84.4% 92 155 62.8%
85%以上 0 3 100% 33 50 60.2% 0 3 100% 0 5 100% 1 9 90.0% 10 33 76.7%

 

 売りの方は良く分かりません。とりあえず学習データ①も③毎日化で正答率が大幅に悪化。予測数も10倍に増えてる。なんで買いとこんなに変わるのかは分かりませんが、火曜オンリーのモデルな感じです。ただ、②のデータは予測データが火曜日ベースと毎日化で5倍程度の違いなのでとにかく学習データ②は買いでも売りでもまんべんなく平均的な動きを予測してるんだろうとは思います。

 ②の毎日化学習データで予測データも毎日化を対象とすると閾値75%以上だと正答率が70%超えてきてますのでこれは使えそうです。ここまでの仮装売買結果見てると正答率が70%超えてこれば確実に儲かる感じでしたし(仮想売買結果をここだけ見てみましたがやはり300万程度儲かっていた)。売りは②と③を予測日で使い分けたり組み合わせたりする感じですね。

 

 ②と③での予測対象の比較とか、曜日特性ももっと深堀するといろいろ見えてくるかもしれませんがここで止めておきます。

 

 結果からみると「買いモデル」は①か③で毎日予測しても使えそうで、「売りモデル」は火曜日を①か③のモデルメインに他の曜日は②を使いつつという感じですね。(何度も同じこと書きますがあくまで22年に売買していた場合!ですけどね)