Pythonと線形回帰で株価の動向を学習するプログラムを実装する

Pythonと線形回帰で株価の動向を学習するプログラムを実装する


いつからかシステムトレードソフトを作ってみたいと思うようになりました。
そのためにまずは株価の動向を予測するプログラムを作ってみたいと思います。

以下の書籍の一部を参考にしました。

Python Machine Learning By Example: The easiest way to get into machine learning


この書籍の後半で株価を終値を予測するサンプルが紹介されていました。

なのでこれに倣いプログラムを実装してみたいと思います。


予測に必要な特徴量を抽出


株価を予測すると言っても方法はいろいろあると思います。

今回は線形回帰モデルを使い具体的な値を求めることで株価を予測しますが、
その場合学習させるためにいろいろとパラメーターを準備する必要があります。

今回実装するモデルでは37個の特徴量が必要になります。
この特徴量を入力されたデータから抽出します。

今回使用するヤフーファイナンスからダウンロードできるcsvのフォーマットは以下のような構成です。
https://finance.yahoo.com/sector/ms_technology


そしてこのデータから以下の37個の数値を抽出します。

  1. 過去5日間の終値の平均
  2. 過去30日間の終値の平均
  3. 過去365日間の終値の平均
  4. 過去5日間の終値の平均 / 過去30日間の終値の平均
  5. 過去5日間の終値の平均 / 過去365日間の終値の平均
  6. 過去30日間の終値の平均 / 過去365日間の終値の平均
  7. 過去5日間の出来高の平均
  8. 過去30日間の出来高の平均
  9. 過去365日間の出来高の平均
  10. 過去5日間の出来高の平均 / 過去30日間の出来高の平均
  11. 過去5日間の出来高の平均 / 過去365日間の出来高の平均
  12. 過去30日間の出来高の平均 / 過去365日間の出来高の平均
  13. 過去5日間の終値の標準偏差
  14. 過去30日間の終値の標準偏差
  15. 過去365日間の終値の標準偏差
  16. 過去5日間の終値の標準偏差 / 過去30日間の終値の標準偏差
  17. 過去5日間の終値の標準偏差 / 過去365日間の終値の標準偏差
  18. 過去30日間の終値の標準偏差 / 過去365日間の終値の標準偏差
  19. 過去5日間の出来高の標準偏差
  20. 過去30日間の出来高の標準偏差
  21. 過去365日間の出来高の標準偏差
  22. 過去5日間の出来高の標準偏差 / 過去30日間の出来高の標準偏差
  23. 過去5日間の出来高の標準偏差 / 過去365日間の出来高の標準偏差
  24. 過去30日間の出来高の標準偏差 / 過去365日間の出来高の標準偏差
  25. 過去1日の収益率
  26. 過去5日の収益率
  27. 過去30日の収益率
  28. 過去365日の収益率
  29. 過去5日間の移動平均
  30. 過去30日間の移動平均
  31. 過去365日間の移動平均
  32. その日の始値
  33. 前日の始値
  34. 前日の終値
  35. 前日の高値
  36. 前日の安値
  37. 前日の出来高

実装


やることがそこそこ多いのでひとつずつやっていきたいと思います。

csvからデータを取得


上で記載したヤフーファイナンスから株価データをもらいます。
どんな企業の株価データでも問題ないと思います。

時々「null」という単語が含まれている場合があります。
手動で消してから処理に通します。

csvからデータを持ってくるソースコードです。
単純に一行ずつ配列に入れているだけですね。

特徴量抽出


次は特徴量の抽出です。
先ほど挙げた37個の値を生成します。
そのソースコードがこちらです。

他の方法(LSTMなど)では調べが足りていないのでわかりませんが、
線形回帰で特徴量を抽出する場合少なくとも365日分以上のデータが必要になります。
ですから株価データの初めから366番めを予測するデータの先頭とします。


そしてこの関数から呼ばれる関数たちです。


これで特徴量を抽出出来ました。
ただひとつ問題があります。

今回SGDで学習していくわけですが、
SGDはパラメーター間の規模が大きすぎるとどうやらうまく学習できないそうなので、
特徴量をそれぞれ正規化します。

それを行う処理がこちらです。


これは特徴量 - 特徴量の平均 / 特徴量の標準偏差を計算します。
ちなみに平均と標準偏差はすべてのデータの同じ種類の特徴量の平均と標準偏差です。
例えば特徴量データが100個あり「過去5日間の終値」の平均を求める場合、
100個の「過去5日間の終値」の平均を求めるということです。


そしてターゲットパラメーター(正解の値)も同じように正規化します。
やっていることは上とほぼ同じです。

予測


実際に入力データ(特徴量)から株価を予測する処理です。
データと重みの内積を計算し結果を返します。
その結果が予測した値ということです。


そして誤差を求める関数です。

重み更新


重みを更新する関数です。

訓練


実際に動かします。
そのテストコードです。
だいぶ適当な作りですが、このあたりは人によって違ってくるのかなと思います。

とりあえず役に立ちそうな値を出力するようにしています。


これを実行する訓練10000回ごとに誤差が表示されます。
10000回終了したらテストに入ります。
テスト時に以下のような情報を表示するようにしました。


今回はAppleの株価データを使用しました。
訓練データ9000個に対してテストデータは700個ほどです。
訓練データが少なすぎるとうまく学習できません。
個数に関してはうまく調整する必要があると思います。

所感


書籍だけではなくネットでもいろいろ調べたのですが、ピンとくるものが見つかりませんでした。

なので特徴量抽出など間違っていそうな部分があるので、
テストの結果が本当に正しいものなのか正直疑問です。

株価の予測について今回試した方法だけではなく他にもいろいろあるんですかね。

あと作り終わって動かしてから気づいたのですが、
今回作成したプログラムだとその日の終値しか予測できないので使いもにはならないような。

でも一応学習はしているし、予測もまったくの的外れではないんですよね。

これからいろいろ調べて機能を拡張していきたいと思います。