<株進捗>8/13 株売買テスト基盤

やったこと

  • 株売買テスト基盤の設計と一部製造

株売買テストの設計

今回は丁寧に設計してやってみています。
設計しているときが一番面白いですね。
いろいろなパターンでテストするときにプログラムをいちいち書き換えずにすむように、機能単位にクラス化しました。

  • TradeController
    Tradeクラスを管理+損益を管理するクラス。こいつがおおもと。
  • Trade
    株単位にトレードを実行するクラス
    Deciderクラスに売買を判断させ、実際に売買を行う。
  • Decider
    ChartクラスとPredictorクラスから将来の株価を予想→TradeAlgorismクラスのアルゴリズムに従って売買決定するクラス
  • TradeAlgorism
    トレードのアルゴリズムが設定されている。将来株価の予想値をもとに、アルゴリズムに従って売買を判断する。
  • Chart
    各銘柄の値動きが設定されているクラス。
  • Predictor
    予想に使う学習モデルが設定されているクラス。

実装

Predictorクラスの実装がほぼ完了。
実装するにあたり、学習プログラム(learn.py)も修正。
なかなか整頓されたプログラムになってきた、ような気がします!
edit.pyは放置しているのでぐちゃぐちゃですが。

ソースコード

ソースコードは以下です。

github.com

学習プログラムはlearn.py(いったん完成)、株売買プログラムはtrade.py(未完成)です。

<株進捗>8/10-8/12 クラスタリング

進捗サマリ

今後の見通しの確認

今後の見通しについて再度整理しました。

  • 成果目標
    2016年度までを学習データとし、2017年度のデータで年利10%を記録する。

  • 作業の見通し

    • 学習プログラムの作成(今ここ)
      ★株のデータを学習するプログラム
    • 売買シュミレーションプログラムの作成
      ★学習プログラムが予想したチャートを元に、どこで買ってどこで売るのが一番利益的であるかを検証するプログラム
      • 売買アルゴリズムの設計 予想した値動きに従い、「どういう条件で買い、どういう条件で売るのか」をプログラム化。
      • 柔軟なシュミレーションが可能な設計にする パラメータを変動させて繰り返しテストできる作りにする。 (学習プログラムは作りがグダグダなので・・・)

株データのグルーピング

1銘柄を学習して1銘柄を予測するのは不可能であるため、学習対象のデータを増やす必要があります。
そのために、相関が高いと思われるデータをグルーピングしてみました。
観点は以下です。

  • 値動き
    「対象銘柄の直近100日分の値動き」と値動きが似ているデータを検索。その後の値動きをチェックする。
    例:銘柄Aの2017年5月〜7月の値動きを対象にする場合
    →データ検索の結果、銘柄Bの2017年2月〜4月が銘柄Aの値動きと近似しているので、銘柄Bの2017年2月〜4月+2017年5月〜7月を学習データとして取り込む

そして銘柄1301と相関のある60銘柄程度を選定し学習させてみました。
f:id:kurupical:20170813100415p:plain:w500
loss値というのが学習の精度でこれが低くなるほど学習がちゃんとできているということになるのですが、途中でnan(Not a Number)値になってしまっています。途中計算でおかしな計算をしているんでしょうか。。

雑感

ディープラーニングをやっている知り合いに今自分がやっていることを少し相談してみました。
そうすると、「そもそもディープラーニングってどういう定義なのかわかってる?」という話になりました。

この2つにはいろいろな定義が込められているため、正解はないと思うのですが、そこで話していた機械学習ディープラーニングの違い(+自分がディープラーニングに期待していたこと)についてメモしておきます。

機械学習ディープラーニングの違い

すごくざっくりなのですが。
機械学習は、「人が立てた仮説に基づきデータを加工・投入しコンピューターに演算させる」
ディープラーニングは、「データを投入するだけで、コンピューターが何らかの知見を出してくれる」

機械学習は、以下の手順で分析が行われる。
①データを集める
 (株データ(項目10個、5年分))
②人の手によりデータの中から特徴量を考える
 (株データは項目が10あるが、その中で「終値」に着目しよう…など)
③手順②で加工したデータを機械学習にかける

ディープラーニングは、上記手順から②を省いたもの。
つまり、分析に人の判断を介さないこと。

ディープラーニングに期待していたこと

データを投入しさえすれば何らかの知見を出してくれるってすごい!!と思って強い興味を持ってはじめました。
だけど今やってる株価分析はディープラーニングとは言えないなあと思います。
人による判断が沢山入っているからです。

  • 株価には「時系列」データである、という仮説。
    ディープラーニングの中の手法の一つ、「RNN」を使う
  • 終値」のみが株価に影響する、という仮説
    自分が保有する株データには項目が10個あるが、そのうち終値だけを分析対象として使っている。
  • 株データのグルーピング
    自分の仮説に基づいてグルーピングをしている

上記の3つも人が判断しなくてすむこと、それがディープラーニングに期待することでした。
ただ現実問題として、それらをすべて判断させるにはリソースが足りないので、上記は止むを得ない部分もあり難しいところですが…
ひとまず、「上記3つを自分の仮説に基づいてやっている」ということを認識しておくことが大事なのかなと思いました。

<株進捗>8/10やったこと・・・データ標準化の改修

今日やったことサマリ

  • データ標準化の機能を切り離してクラス化

今日やったこと

データ標準化のやりかた見直し

右往左往して、結局昨日のままで良いことがわかりました。

データ標準化の機能切り離し

もともとStockオブジェクトにデータ標準化の機能をゴリゴリ書いていましたが、データ標準化の機能だけを切り出してオブジェクト化しました。
オブジェクト指向の良さがなんとなくわかってきた、ような気がします。

実際の株データを予測(軽く)

対象銘柄:3597(自重道)
選定理由は、単調増加で割と予想しやすいかなと思ったからです。

なんとなく予想できています。 学習回数・学習データを増やせばもっと正確に予想できるかも。

今後の予定

学習モデルの構築はひとまずこれで終わりにします。
次はデータの前分析。
「どのようにデータを食わせるといいのか?」を検討しようと思います。
現在は1銘柄を食わせて1銘柄を予想していますが、それだとデータ量が不十分です。
なので、ある程度特徴の似た銘柄をひとまとめにして学習して1銘柄を予想させるようにします。
たとえば…
クラスタリング
 ・銘柄の時価総額
 ・値動き相関
 ・業種
 など

明日は機械学習もくもく会なので、そこでもくもくとかんがえます。

<株進捗>8/9やったこと・・・学習モデルのデバッグ、プログラムバグ修正

今日やったことサマリ

  • 学習モデルはそれなりに動いている
  • 標準化のバグが予測おかしくしていた?

今日やったこと

学習モデルのデバッグ

昨日の続きです。
株が学習できない理由の絞り込み。
仮説1:学習がうまく行っていないんじゃないの? に対する検証として、2次関数〜4次関数が学習できているかを確かめました。
今日会社に行く前に処理を流してからでかけ、帰ったら終わっていたので確認しました。
4次関数

学習3000回/5000回
f:id:kurupical:20170809235332p:plain:w300f:id:kurupical:20170809235409p:plain:w300

学習10000回/20000回
f:id:kurupical:20170809235426p:plain:w300f:id:kurupical:20170809235501p:plain:w300

右往左往しながらも、20000回の時点では学習が結構な精度でできていました。 他のものも確認したのですが、概ねできている。

仮説1:学習がうまく行っていない? → うまく行ってる!

標準化バグ修正

仮説2:プログラムバグ
標準化処理を行うことで学習が早くなると言われており、私もそれを実装しているのですが そこにバグがありました。(今回のデバッグにより発見!) 標準化処理を行わないで株の学習を行うと学習スピードが異常に遅い(というか止まる)ので、標準化処理は必須です。

標準化処理はざっくり以下の順番でやるつもりでした。

1.学習
①学習対象データを取り込み標準化
②学習する

2.予想
①予想に使うデータを取り込み標準化(1日目〜100日目の終値
②101日目の終値を予想する
③2日目〜100日目と、②で予想した101日目の終値を使用し102日目の終値を予想する
④3日目〜100日目と、②③で予想した101日目〜102日目の終値を使用し103日目の終値を予想する


(以下略)

ですが、2①の実装もれにより、学習時は標準化されたデータで学習しているにも関わらず予測時は生データを使って学習していました。
ですので、2次関数でもご覧のありさま。
f:id:kurupical:20170810000435p:plain:w300
2②の予想がうまくいかないのでそれに引きずられて2③、2④…と予想がおかしくなっていくということでした。

ということで修正して再度2次関数を予測
f:id:kurupical:20170810000950p:plain:w300
予想が実際の値より先走っているように見えます。何回か行ったのですが結果はすべておなじ。

ひょっとすると予想の正しい順番は
2.予想
①予想に使うデータを取り込み標準化(1日目〜100日目の終値
②101日目の終値を予想する
②' 2日目〜101日目のデータを標準化
③2日目〜100日目と、②で予想した101日目の終値を使用し102日目の終値を予想する
③' 3日目〜102日目のデータを標準化
④3日目〜100日目と、②③で予想した101日目〜102日目の終値を使用し103日目の終値を予想する


なのかもしれません。
今日はここで力尽きてしまったので、次回は上記を実装して検証→OKなら株でリベンジ!!したいと思います。

雑記

学習モデルをさんざん疑っていろいろ改造したのですが結局プログラムの凡ミスというありさまでした。
かなり回り道をしてしまったのですが、そこでいろいろ勉強できたのでよかったかなと…。

<株進捗>8/8やったこと・・・デバッグプログラムの作成、実行

今日やったこと

学習モデルのデバッグプログラム作成

ランダムに2次〜4次関数を作成→学習させる、というプログラムを作成。
N次関数を作るメソッド(N=(2,3,4))を昨日実装したので、イメージとしては以下の通りでいけるかと…

for i in [2,3,4]:
   for k in range(10): #テストしたい回数
       debug_file = make_func(dim=2)
       result_graph = learn(file) 

なかなか簡単にデバッグプログラムが組めず。
ソースコードがごちゃごちゃしてるからです。
たとえば、make_func()というメソッドという名前にもかかわらずなんか作った関数を分析しようとしたり…。
一つの関数に色んな物を詰め込みすぎです…。
理想としては、いろんなメソッドをとっかえひっかえし組み合わせてプログラムを組みたい。
ということで、リファクタリングが必要になりそうです。

デバッグ

道具を作ることに凝りすぎても本末転倒なので、前にも進まないといけないジレンマ。。
(綺麗に作るのちょっと楽しくなってきました。)

引き続き、2次関数〜4次関数を学習させてみます。
昨日は失敗したのですが、以下の通り変更したらうまく行きました。
テスト関数
f(x) = ax**2 + bx + c
について、
以前:a,b,cは-150〜150の間でランダム f(-150),f(-149),…,f(149),f(150)をテストデータ
→今回:a,b,cは-1.5〜1.5の間でランダム f(-1.50),f(-1.49),…,f(1.49),f(1.5)をテストデータ
にしたらうまくいきました。数字の大きさの問題??

2次関数(学習2000回)
f:id:kurupical:20170808224505p:plain:w400

3次関数(学習2000回)
f:id:kurupical:20170808224658p:plain:w400

ということで、3次関数と4次関数をランダムに100個ずつ生成してそれを20000回ずつ学習させる、というデバッグを今夜流してみます。
ついでに、パラメータをいくつか調整して学習の速さもみてみます。

今後やること

データの標準化バグ修正

データ標準化がバグっていたので修正→デバッグ→株価分析リベンジ!!!!
4次関数まで予想できれば、とりあえずそこそこのモデルは構築できていると判断します。
これでも予測できなかったら………
ちょっと考えます。

<株進捗>8/7やったこと・・・プログラムの検証

東京で仕事帰りに泊まりがけで遊んで帰って、プログラムの進捗が遅れてました。
一度習慣が崩れるとダメですね…。

今日やったことのサマリ

プログラムが悪いのか、株価予想はそもそも無理なのか検証!

  • (ここまでくるのにもグダグダ…)
  • いくつかのベンチマークを設定し性能テスト

    • y=√x
      f:id:kurupical:20170807205636p:plain:w400
      →データを標準化(平均0,標準偏差1)に変換して戻しの処理がバグっていました。とりあえず、データ標準化モードを外して学習させました。
      f:id:kurupical:20170807205355p:plain:w400
      →1000回、隠れ層=1で学習完了。
      他サイトでは4000回で学習完了とか書いてあったので、優秀な成績。

    • 2次関数(定数a,b,cはランダム)
      f:id:kurupical:20170807210052p:plain:w400
      →学習のスピードがかなり遅いです。

    • 3次関数(定数a,b,c,dはランダム)
      f:id:kurupical:20170807210316p:plain:w400
      →2次関数と同じ。

    • 4次関数(定数a,b,c,d,eはランダム)
      →2次関数、3次関数と同じになるだろうと思ったのでやっていません。

  • 株価予想をする前にクリアすべき課題

    • 2次関数〜4次関数を予想できるようプログラム修正
    • テストプログラムの作成 上記4つの関数の予想テストがすぐできるプログラムを作っておく

そもそも

…株価予想なんか難しいことする前に、自分が作った学習モデルが正しく学習するのかという検証をちゃんと行わないとダメでした。
y=sin(x)とy=√xが予想できたからOKかと思っていましたが、まさか2次関数がアウトとは…。
2次関数すら予想できないようでは、そりゃ当然株価も予想できません。。
実務でAI作る時もこういう形での性能テストが必要なんだろうなと思いました。
例えば、わざとわかりやすいデータを作って(株でいえば、終値出来高も単調増加・終値は単調増加だが出来高は単調減少など…)、予想できるかテストするというような。
生データを食わせるのはその先ですね。。

<株進捗>8/3やったこと・・・チューニング

8/3やったこと

  • tensorboardの導入
    ネットワークが可視化できる。
    実装自体は簡単。ただ、見てもさっぱり分からない…
    f:id:kurupical:20170803220143p:plain 勉強で作ったsin波予測プログラムと今回の株予測プログラムを比較して、変なところがないか確認してちょこちょこ修正しました。

  • ハイパーパラメータの調整
    テストデータのサイズを変えてみました。
    f:id:kurupical:20170803223417p:plain
    →点線が実績値、実線が予想値です。
    うまくいかず。
    どうパラメータを調整しても、予測の最初にバイーンってなるのはなぜなんでしょう…。

  • データ加工
    株価ではなく、株価の前日比増減を学習させてみる


    • 1000→1100→900→990→…という値動きは
      0→(1100/1000)→(900/1100)→(990/900)…
      = 0→1.1→0.82→0.9…
      とやってみました。
      f:id:kurupical:20170803223542p:plain
      →これもダメっぽい…?
      今夜またいろんなパラメータ与えてぶん回ししてみます。

若干(かなり?)行き詰まっています。
こーしてみたら?的なアドバイスがあれば欲しいです。
データさえ食わせたらそれなりの予想してくれるっしょ!っていう考えは甘かった…!

そういえば、新しいPC、処理速度が落ちてきた気が…
やっぱりSSD上でディープラーニングはまずかったんでしょうか笑。