【SIGNATE】JPX ファンダメンタルズ分析チャレンジ②

学習記録

 

 前回の記事では、コンペに参加した際に行った一連の取り組み(探索的データ解析~モデル構築等)についてまとめました。予測モデルには、各銘柄の決算発表日の一時点の価格情報(テクニカル指標)や決算情報(ファンダメンタル情報)を入力データとして、RandomForestやGradientBoostingを利用しました。

 今回は、各銘柄の決算発表時点のファンダメンタル情報と直近のテクニカル情報の時系列データをインプットにしたディープラーニングモデル(CNNを利用)を作ってみたので記事に残しておきます。結果としては前回の機械学習モデルよりも改悪なモデルとなってしまいましたのでボツとしました。ただ、改善の余地は十分あると思っております。
(コンペの締め切り間際で改善をしている余裕がなかった・・・。)

モデル構築の経緯

 前回の記事で紹介した機械学習モデルでは、決算発表時のデータ(クロスセクションデータ)しか利用しておりませんでした。ファンダメンタル情報は時期列データとして利用するのは困難ですが、テクニカル情報を時系列データとして利用することで精度向上の可能性の余地がありそう。
(むしろファンダメンタル情報を使わなくても、テクニカル情報の推移だけで良い感じのモデルが作れそうな…?)

 各銘柄の価格情報がランダムウォーク(確率的トレンド)だとすると、過去の価格やテクニカル指標を利用した将来予測は困難です。しかし、世の中にはテクニカル分析という価格の形成パターンで将来予測(占い?)をして成果を出している猛者がいるのも確かです。

 将来の価格(今回の場合だと将来の最高値・最安値)が過去の価格情報・テクニカル情報をもとに形成されているのであれば、それらをモデルにうまく組み入れることができば予測精度は向上するはずです。

 とまぁ、こんな感じで浅はかな考えではあるものの、時系列データを利用してみる価値は大いにあるのではないかと思い、時系列モデルを作ってみた次第です。

 本来であれば、各銘柄の価格についてランダムウォークの検定をする等、モデルを構築までに様々なステップを踏まないといけないのかもしれません。今回は時間の都合上、そこまでの労力を費やすのは困難だったので、試してみてうまくいけばラッキー程度の気持ちで取り組んでみました。(この辺のアプローチの仕方について詳しくないので、勉強しないといけない…)

モデルについて

 今回のモデルには、1次元畳み込みニューラルネットワーク(1D-CNN)を利用しております。時系列モデルだとまず初めにRNNを思い浮かべるかもしれませんが、学習時間が短くて成果が出ている1D-CNN(正確にはTCN)を採用することにしました。

 モデルの学習(エポック数)は、val Loss(評価データの損失値)が一定の値に収束するまで動かしました。Google Colaboratoryで実行したのですが、セッションが切れてしまい、モデルの保存・読込みを繰り返してまう少し汚い処理となってしまいました。

 先日参加したKagleのコンペで同じようなモデルを作ったので、時間の都合上、それを流用してしまいました。Kaggleで使用したモデルについては以下の記事にまとめてます。

データセット

 モデル構築で使用したデータセットについては、機械学習モデルで利用した特徴量と大差ありません。違いとしては、テクニカル指標は決算日から過去\(n\)日間分の時系列データを入力データとして使用するようにした点だけです。

 ここで、\(n\)についてはこちらで設定する必要があります。今回は\(n\)の探索をしている余裕がなかったので、ひとまず\(n=5\)としました。\(n=5\)とした理由は、上で紹介したKaggleのコンペでスコアが良かったためです。そもそも今回のコンペとKaggleとでは、予測対象や入力データが異なるのでそのまま流用してよいのかはいささか疑問ですが・・・。今思えば、もう少し期間を長くしたほうが良かった気がします。

 また、時系列データの中には、決算発表日から\(n\)日経過してないものも存在したため、前処理でそのようなデータは除外するようにしました。

 なお、データセットを扱いやすくするため、PytorchのDatasetクラスを継承しております。全銘柄の情報を持つとメモリが不足してしまう可能性があります。そこで、このクラスでは、銘柄(正確にはインデックス番号)が指定されるたびに、対象となる銘柄の時系列データの生成とファンダメンタルデータ・ラベルデータの抽出を行い、データセットとして返すように工夫しております。

入力データ(特徴量)

 今回のモデルには、テクニカル指標の時系列データとファンダメンタル指標の2つを入力データとして利用します。

 ちなみに時系列データは、5×30(\(n\)×テクニカル指標の数)の形をしております。ファンダメンタル指標に関するデータは、1×46(ダミー変数を含むファンダメンタル指標の数)の形をしております。

 詳細については、以下にまとめておきます。

【テクニカル指標】

  • 出来高
  • 対数リターン
  • 変化率(5日、25日、75日)
  • 移動平均乖離率(5日、25日、75日)
  • ヒストリカルボラティリティ(5日、25日、75日)
  • 各HVの20日間移動平均
  • 過去n日間の最高値(最安値)に対する終値・高値(安値)との乖離率(n=5, 10, 20)
  • キリ番との乖離率
  • RSI
  • 終値に対する1日当たりの値幅
  • (高値-安値) / 終値の25日間移動平均

【ファンダメンタル指標】

  • 売上高営業利益率, 売上高経常利益率, 売上高当期純利益率
  • 前期比(成長率)
  • 来期予想成長率
  • 自己資本比率
  • ROE(当期純利益÷自己資本)
  • ROA
  • キャッシュフローの正負※
  • 配当利回り
  • セクター情報※
  • 決算レポートの種別※

※については、ダミー変数化(one-hotベクトル化)して利用しました。

ラベルデータ

 前回の機械学習モデルの時と同様に、以下の4つのラベルを使用します。

  • 20営業日のうちの最高値
  • 20営業日のうちの最安値
  • 20営業日の終値の平均値
  • 20営業日のうちの最高値と最安値の差分(幅)

 モデルの予測では、3点目、4点目の中間値・幅(最高値ー最安値)から最高値・最安値を算出します。そして、最終的にこれらを平均したものを予測ラベルとして利用します。

モデル構成

 ディープラーニングモデルは、上でも紹介しましたが、TCN(Temporal Convolutional Network)を利用しました。モデル構成のイメージ図は、以下の通りです。

 モデルの流れについて簡単に説明します。

 まずはじめに時系列データをTCNにより特徴量を集約します。次に集約された特徴量とファンダメンタルデータを結合します。そして結合された特徴量を全結合層を通して、予測結果を出力します。

学習の結果

 ざっと、40エポックほどで学習は落ち着きました。学習の経過をログでとっておくべきだったのですが、忘れてしまいました。取っていれば、グラフにして推移にするのが一番わかりやすいのですが。。。

 参考程度に、学習の経過記録を一部以下に記載しておきます。詳細は、最後に載せるノートブックをご参照いただければと思います。尚、Google Colaboratoryで学習をし、セッションが切れたりで途中で再学習を繰り返しております。その為、エポック数の数字が途中から初期化されております。

【1~3 エポック】
【40エポック~】

 左の画像が学習序盤で、右の画像は学習終盤の経過を表しております。学習序盤は、train Lossが5847でval lossが2435とかなり大きな値となっております。一方で終盤となると、train Lossは460程度で, val lossは170程度とかなり改善されている様子が見られました。

結果

 上記のモデルを投稿してみた結果は以下の通りです。

 一番上が今回のDLモデルで、下二つが前回の記事で紹介したMLモデルの結果です。MLモデルよりも評価が低いモデルとなってしまいました。

 モデルの予測値の基本統計量と予測値の分布は以下の通りです。

 以下の表は、ラベルデータ全体の基本統計量をまとめたものです。(前回の記事から引用)

 モデルの最高値に対する予測値は全体的に約0.09付近に偏っていることがわかります。一方で、ラベルデータ全体の平均は約0.09であるものの、全体のデータの取りうる幅は大きいです。つまり、ディープラーニングモデルは、ほとんどが平均付近しか出力できないものとなっています。最安値に対しても同様のことが言えます。

 損失関数にはMSE(平均二乗誤差)を利用しましたので、学習で予測が平均に偏ってしまうのもなんとなくイメージが湧きます。というのもの、平均付近の値を予測値とすることで全体的な損失値は下げることができるためです。train lossやval lossがある一定値に落ち着いているのは、平均付近を予測したためだと思われます。(線形回帰に近い予測になっている?)

 こういう問題を解決するにはどうしたらよいのですかね…。
 平均に偏らない予測ができるようにしていくとなると、教師データを調整するとか?
 現状は平均付近に教師データが集中しているので、平均付近のデータを減らしてみたり、外れ値のデータを丸め込んで同じようなデータ群としてみたりなど、工夫が必要なのかもしれません。
 ↑は思いつきなので他にちゃんとした対処法を知っている人がいれば教えてください。

 このような問題に対しては決定木モデルの方が特に何もしなくてもうまいことデータに適応するのかもしれません。その結果、前回のMLモデルの方がスコアが高くなったのかもしれません。

まとめ

 今回は、SIGNATEの日本証券取引所(JPX)主催のコンペで作成したディープラーニングモデルについて簡単に紹介してみました。

 結果はかんばしくなかったですが、時系列データ(テクニカルデータ)とある一時点のデータ(ファンダメンタル指標)を組み合わせたモデルを構築することができたのではないでしょうか。

 金融データは発生頻度が不均一です。(日次で得られるものもあれば、年次でしか得られないものもある。)このようなデータを最大限活用するアプローチとしては、今回のようなやり方が考えられるのではないでしょうか。つまり、時系列データを圧縮した特徴量とクロスセクションデータとConcatanete(結合)し、その特徴量(ベクトル)をモデルのインプットとして扱うということです。

 今回は時間の都合上、モデルの改善をしている余裕がありませんでした。個人的には、時系列データとクロスセクションデータを掛け合わせたモデルには可能性を感じています。なので、今後のシストレ開発に取り入れてみたいと思います。

 その前に、次はニュース分析のコンペに参加してみます!!

以上

ご参考

 今回の記事に関するプログラムはGithub(こちら)に公開ております。
 【ipynb】

 【src/src_DL】

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