<株進捗>8/15 売買プログラムのテスト

目次

  1. 売買プログラム実装
  2. 売買プログラムのテストコード作成
  3. 雑感

1.売買プログラム実装(trade.py)

今日は以下の赤文字部分を実装しました。

①学習モデルを用意 (完了)
②学習モデルの読み込み (完了)
③現在日付の設定 (完了) →2017/1/1からスタート

 ★④〜⑦を、2017年度分データのすべてが読み込み終わるまで繰り返し
 ④現在日付から過去N日分のデータを基に、M日分の株価を予測 (完了)
 ⑤予測した株価を基に、売買の判定を行う
 ⑥(売買があった場合、株の購入記録を残す)
 ⑦現在日付を1日進める。

⑧売買の成績を算出する

設計ミスが少しあったので、一部書きなおしたりしつつ…。
売買履歴・保有している株の一覧などが出力できるようになりました。

2.売買プログラムのテストコード作成(test_trade.py)

テストコードを作成中です。
具体的には、予測可能な簡単な関数(1次関数、2次関数)を株価データとし、正しく予測に従って売買ができるかをテストするものです。 「設定ファイルを入力にして繰り返しテスト」ができるようにしました。
テストするたびにソースコードをいじりたくないので…。
テストはできるようになりましたが、結果の検証方法は設計がまだです。

3.雑感

・本質のディープラーニングから離れてしまっているので早く戻りたいのですが、プログラム作成は目に見えて出来上がっていくのが見えて楽しくて、なかなか戻れません。笑
学習データを60銘柄程度にすると、損失関数(ざっくり言うと学習の進捗を表すもの)がNanになってしまうという致命的なバグの修正が待っているので…
GitHubのissueでタスク管理をするようにしたのですが、これが結構やりやすいので続けてみようと思います。

GitHubソースコード公開しています。
今日は以下を修正しました。
(いつか、README的なドキュメント書かないと…)
trade.py
test_trade.py

github.com

<株進捗>8/14 売買アルゴリズムの作成

目次

  1. 売買アルゴリズムの作成
  2. GitHubを使いこなす(Issue管理)
  3. 雑感

1.売買アルゴリズムの作成

株売買のパフォーマンス計測ができるまでの流れを以下にまとめてみました。

①学習モデルを用意 (完了)
②学習モデルの読み込み (完了)
③現在日付の設定 (完了) →2017/1/1からスタート

 ★④〜⑦を、2017年度分データのすべてが読み込み終わるまで繰り返し
 ④現在日付から過去N日分のデータを基に、M日分の株価を予測 ←今日はここ
 ⑤予測した株価を基に、売買の判定を行う ←今日はここ
 ⑥(売買があった場合、株の購入記録を残す)
 ⑦現在日付を1日進める。

⑧売買の成績を算出する

売買の判定アルゴリズムをサンプルで1つ作成しました。端的にいうと以下の通りです。
「基準日の終値と、予測したM日分の終値の最大値を比較し、N%以上上がっていたら買い、N%以上下がっていれば売り」

アルゴリズムは複数種類作って、パフォーマンスを確かめたいと思っています。

2.GitHubを使いこなす(Issue管理)

今日は会社のスーパー同期とご飯に行きいろいろ話して(というか教えてもらって)、その中で参考になるところがあったので取り入れることにしました。
Issueでタスク管理し、GitHubのコミットはタスク単位でやることにします。
(今更感が半端ないですが…)
そうすることで、自分がやるべきタスクが見えやすいかなあと。

3.雑感

・お盆休みいろんな人と飲みに行ったのですが、「ブログみてるよ!」と言っていただき(特に同業者のかた)とてもモチベがあがりました。
・実績公開ということで、一連のプログラム実装が終わったらWebに予想を公開するプロジェクトも平行してやろうと思います。ちょっと前にかじったRailsを使って実装する予定です。

<株進捗>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次関数まで予想できれば、とりあえずそこそこのモデルは構築できていると判断します。
これでも予測できなかったら………
ちょっと考えます。