<株進捗>9/5-9/6 プログラムレビュー、パラメータチューニングの実装

目次

  1. レビュー受けました
  2. レビュー受けての感想
  3. 今日やったこと
  4. その他

1.レビュー受けました

僕が6月くらいからずっとお世話になってるもくもく会で、自分のAIプログラムの進捗の話をしました。
この日は結構盛り上がりました。
もくもく会はこれです↓
【大阪・ディープラーニング】Hackers' Salon 09/23【もくもく会】 - connpass

僕が話したこと

  • 現状
    • 過去N日の値動きを取り込み→次の5日で10%以上アップ(買いサイン)、-10%以下ダウン(売りサイン)、その他(サインなし)になる確率を予想
    • 銘柄の学習がうまく行かない。全部「サインなし」になる
    • 1次関数〜4次関数でテストするとそこそこの精度が出る
    • パフォーマンスチューニングはこれから

話しあったこと

  • 考えられる原因と、原因に対する対策は4つ
    • プログラムミス
      1次関数から4次関数は予想できていることから、ある程度動いてそう
    • ハイパーパラメータの調整
      (対策)パラメータを調整して回す。
    • 損失関数の誤り 現在は、出力層がSoftmaxで損失関数はCrossEntropyですが、CrossEntropyは少し問題があると思ってます。 例えば、答えが「10%以上」の学習データがあった場合、次の2つの間違った予想は、評価(損失関数の値)は同じ。「①10%以上である=50%、−10%以下である=50%」 「②10%以上である=50%、ー10%〜+10%である=50%」 ①より②のほうが、実態に近い予想をしていると思いますが、①と②は同じ評価がされてしまいます。 →(対策)新しい損失関数を探す(論文読むなど・・・)
    • そもそも相関がない より予想がしやすいよう、「取り込む値動きの期間を長くする」「予想する期間を短くする」

2.レビュー受けての感想

  • 自分の考えが浅い
    この話をしたとき、実際に作っている自分より相談受けてもらってる人のほうが真剣に考えていました。
    自分は、ある程度話して「ま、いっか!」と諦めかけていたのに。笑 深く考える習慣が全然身についてないなと反省しました。。
  • 「考えられる原因と、原因に対する対策」の考え方がAIとか機械学習では必要!
    AI機械学習関係の開発は、「何が悪いかわからないけどちゃんと動かない…。」なんてことが普通のプログラミング以上にあると思います。そんなときはこの視点で冷静に見ようと思います。

3.やったこと

各種パラメータが設定されているファイルを設定に従って自動生成する機能など、検証が簡単にできる仕組み作りを進めました。

そしていざテスト。

1次関数〜4次関数の予想

y=f(x)(X=1…200)に基づき、y=f(x)(X=201…205)の最大値を予想。
3%を超えれば「Buy」、ー3%を下回れば「Sell」、それ以外は「Stay」

10000回学習させた時の損失関数の推移
f:id:kurupical:20170906223803p:plain:w400

出力結果

2017-09-06 18:51:07,,(予想/結果)
2017-09-06 18:51:07,,(Buy:N%以上up/Sell:N%以上down/Stay:それ以外)
2017-09-06 18:51:07,,(Sell/Sell):356.0
2017-09-06 18:51:07,,(Sell/Stay):124.0
2017-09-06 18:51:07,,(Sell/Buy):68.0
2017-09-06 18:51:07,,(Stay/Sell):16.0
2017-09-06 18:51:07,,(Stay/Stay):644.0
2017-09-06 18:51:07,,(Stay/Buy):0.0
2017-09-06 18:51:07,,(Buy/Sell):28.0
2017-09-06 18:51:07,,(Buy/Stay):0.0
2017-09-06 18:51:07,,(Buy/Buy):1144.0

予想=結果になっているのが、(Sell/Sell)356 + (Stay/Stay)644 + (Buy/Buy)1144 = 2144件。
全体が2380件なので、だいたい90%の正解率です。
Buy/Sellもちゃんと予想できてます。
1次関数〜4次関数に近似する銘柄がもしあれば、このAIはボロ儲けしてくれます。

銘柄の予想

過去200日の値動きに基づき、翌5日の値動きの最大値を予想。
3%を超えれば「Buy」、ー3%を下回れば「Sell」、それ以外は「Stay」

10000回学習させた時の損失関数の推移
f:id:kurupical:20170906224326p:plain:w400

出力結果

2017-09-06 20:45:33,,(予想/結果)
2017-09-06 20:45:33,,(Buy:N%以上up/Sell:N%以上down/Stay:それ以外)
2017-09-06 20:45:33,,(Sell/Sell):0.0
2017-09-06 20:45:33,,(Sell/Stay):0.0
2017-09-06 20:45:33,,(Sell/Buy):0.0
2017-09-06 20:45:33,,(Stay/Sell):36.0
2017-09-06 20:45:33,,(Stay/Stay):1327.0
2017-09-06 20:45:33,,(Stay/Buy):345.0
2017-09-06 20:45:33,,(Buy/Sell):6.0
2017-09-06 20:45:33,,(Buy/Stay):22.0
2017-09-06 20:45:33,,(Buy/Buy):49.0

予想=結果になっているのが、(Stay/Stay)1327 + (Buy/Buy)49 = 1376件。
全体が1785件なので、正解率は77%です。
しかし、正解して欲しいのは「Buy」もしくは「Sell」です。
(「Stay」を正解しても、売買をしないので利益にならない)

「Buy」の正解率は…
正解件数 : (Buy/Buy) 49件
全体件数 : (Stay/Buy) 345件 + (Buy/Buy) 49件 = 394件
つまり、394回の買いどころがあったのに49回しか買えてないということになります。
また、買わなくていいのに買っちゃってるのが(Buy/Sell) 6件 + (Buy/Stay) 22件 = 28件あります。

この精度の予想では、まだまだ利益でなさそうですね・・・。

過去400日の値動きから翌5日、過去200日の値動きから翌3日、などいろいろな数字をチューニングした160パターンで学習テストしてみます。
次のブログでは良かったパラメータランキングを出してみようと思います。
結果が良かったパラメータを使って、今度は30銘柄ぐらい学習させてみようと思います。

4.その他

書籍「ゼロから作るDeepLearning」の読書会を開催することになりました。
osaka-prg-school.connpass.com
読書会行ったことありませんし、もくもく会以外の勉強会に行ったことありません。が、どうしてもやってみたかったので。
今からめっちゃ緊張しますが、楽しみでもあります!

株予想プログラムのソースコード以下で公開しています。
github.com

<株進捗>9/3 株価の3分類予想(+10%over / -10%〜+10% / -10%under)

目次

  1. 今日やったこと
  2. 学習モデルの構築
  3. 出力イメージ
  4. その他

1.今日やったこと

昨日記事に書いてた以下をやりました。

  • 1銘柄N日→先30日の終値の最大値、最小値を6分類する(値動き+10%以上、+5%〜+10%、0%〜+5%、-5%〜0%、-10%〜-5%、-10%以下)
    未完了

昨日はなんとなく6分類にしていました。
よく考えると、実際は「買う」「何もしない」「売る」の3つさえできればよいです。
具体的には、予想値が「+10%超え」なら買い、「ー10%未満」なら売り、それ以外は何もしない。

ということで、値動きを「〜ー10%」「ー10%〜+10%」「+10%〜」の3つに分類することを最終目標にしました。

2.学習モデルの構築

Input: 1銘柄N日分のデータ
Output: 先30日の終値の最大値、最小値が「〜ー10%」「ー10%〜+10%」「+10%〜」になる確率

出力層にはソフトマックス関数を使っています。分類の確率を出すためです。

損失関数は以下を考えました。

出力層がソフトマックス関数の場合、交差エントロピーが損失関数としてセットになることが多いみたいです。

ここで疑問が2つ。

  • 上記の例で、正解が「+10%以上」の学習データに対して以下の2つは同じ評価がされます。
    • 「+10%以上」50%、「ー10%〜+10%」50%  
    • 「+10%以上」50%、「〜ー10%」50%
  • 当てずっぽで全部「ー10%〜+10%」にする、になりそう。。
    「+10%以上」「ー10%以下」がそれぞれ5%程度、あとはすべて「ー10%〜+10%」くらいの分布になるので。しかし、大事なのは「ー10%〜+10%」を当てることじゃなくて、「+10%〜」「〜ー10%」を当ててもらうことです。単純に分類するだけでなく、「+10%〜」「〜ー10%」にインセンティブを与えるような損失関数がいるのか、どうなのか・・・。

結局、とりあえず以下の関数を作ってみました。誤差逆伝播とかの関係でこの関数じゃダメなのかもしれませんが、一度やってみようと思います。
Loss = 教師データ(※) - [(+10%〜である確率) - (〜ー10%である確率)]

(※)教師データ。以下のように表現されます
「+10%〜」であれば1
「〜ー10%」であれば-1
「ー10%〜+10%」であれば0

3.出力イメージ

とりあえず実装。簡単に出してみました。
f:id:kurupical:20170904000727p:plain:w400

一番したにちょこっとでてる3×3の行列が結果です。
縦列が予想です。
1行目から順に〜ー10%、ー10%〜+10%、+10%〜とそれぞれ予想した件数です。
2行目にすべての数字が出ているので、この例だとすべてのデータに対して「ー10%〜+10%」と予想しています。

横軸は実際の値です。
1列目から順に実際の値が〜ー10%、ー10%〜+10%、+10%〜となった件数です。
つまり、実際の値は514件が「ー10%〜+10%」、71件が「+10%〜」となっています。

縦横を合算すると、

  • 514件は、予想結果とも「ー10%〜+10%」で正解
  • 71件は、予想「ー10%〜+10%」に対して結果「+10%〜」で不正解

となります。

※5万件くらい予想させましたが全部、「ー10%〜+10%」で予想しやがります。
f:id:kurupical:20170904002009p:plain:w400

Loss関数を交差エントロピーにして、もう一度やってみます。。
3分類法、自分としてはかなり名案だと思ったのですが…。

4.その他

「どの程度予想があたれば統計的優位性があると認められるか」という計算もしたのですが、力尽きたので今日はここまでにします。

<株考察>9/2 考察、今後の予定

目次

  1. 現状の考察
  2. 今後の予定
  3. その他

1.現状の考察

なかなかうまくいかない(プログラムが間違ってる可能性もありますが)現状を鑑みるに、そもそもアプローチが間違っているのでは?という懸念が出てきました。

突然ですが、勝つ麻雀のAIを作るとしたらどうやって作りますか?

僕は、「14枚の手牌から期待値に基づき切る牌を正しく選択する」ことを正確にできるようにします。

間違っても、「次ツモる牌を高い精度で予想するモデルを作成し、その予想に基づいて切る牌を選択する」アプローチは取りません。

どの牌が山に残っているかの読みが正確にできても、その牌がツモれる確率が5%程度上がるだけです。
一番当たる確率の高いハイテイツモの予想ですら王牌14牌+ツモ1牌の15牌。特定の牌が4枚生きていると読んだとしても、ツモれる確率は4/15=26%程度。一番当たる確率の高いハイテイツモですらこの程度です。ツモる牌を高い精度で予想するなんて不可能です。(※以下のような場合を除く)

【数学】たかしくんが40枚一組のデッキの中から特定の切り札1枚を、第n回目のドローで引き当てる確率を求めなさい。ただし、たかしくんは真のデュエリストとし、たかしくんとカードの間の絆は十分に深いものとする。
※元ネタ:matome.naver.jp

今の僕がやっている株価予測、上の例でいうと後者をやろうとしている気がします。 こんなことを言っては元も子もないですが、株価の完全な予想なんてできません。
あくまで、期待値ベースで考えて期待値がプラスの行動を取るようにするべきだと思います。

なので、今のアプローチは間違っているんじゃないかと疑っています。 (RNN使いたくてとりあえず予想をやってみたという自分の無計画さが露呈しました。)

じゃあどうするか。
自分のなかでは、2択かなと考えています。

  • 株価の値を予測するのではなく、それぞれの確率を表示するようにする。
  • 強化学習(*)を用いる

(*)強化学習
説明は以下を参照ください。(自分もちゃんとわかってない) qiita.com

2.今後の予定

RNNで株価を予測するのは以下をやってひとまずおしまいにしようと思っています。

  • 1銘柄N日→次の日の終値の予想
    (完了、1次関数〜4次関数までほぼ正確に予測できたが、株価は予測できず)
  • 1銘柄N日→先30日の終値の最大値、最小値の予想
    (完了、1次関数は予測できたが2次関数は予測できず)
  • 1銘柄N日→先30日の終値の最大値、最小値を6分類する(値動き+10%以上、+5%〜+10%、0%〜+5%、-5%〜0%、-10%〜-5%、-10%以下)
    未完了
  • (・M銘柄N日→1銘柄の先30日の終値の最大値、最小値)
    ※自分的には結構パワフルなモデルになると思っています。が、M銘柄×N日→1銘柄を予想する汎用的なモデルをそもそも作れるのか、RNNの深い理解が必須です。。できればやる。

3.その他

  • 以下でソース公開しています。 github.com
  • 遊戯王のくだり、昔読んで爆笑したけどどこだったかなあと探すのに10分も費やしてしまいました。。
  • 最近いろいろと別のことしていてなかなか時間取れません。投資関係もこのブログで書いてみようかな…。

<株進捗>8/26-8/29 学習の検証

目次

  1. 学習の検証
  2. その他

1.学習の検証

今は、過去N日から先M日の最大/最小を予想するというところをやっているのですがいかんせんうまくいきません!

f:id:kurupical:20170829225608p:plain:w300
上記の例でいうと、2015/7/22から200日分のデータに基づき、201日目〜215日目の株価の最大値、最小値を予想しようとしています。
(201日目〜215日目は、点線の間に収まるだろうと学習モデルは予想しています。実際は最小値は近い値を出してますが最大値は的外れな金額を出しちゃってます)

モデル自体が正しいか検証。
1次関数だとうまくいく。
f:id:kurupical:20170829225845p:plain:w300

2次関数だと全然だめ。
f:id:kurupical:20170829230517p:plain:w300

2.その他

・毎日作業は結構やっているのですがなかなか進捗がなく、書くこともなく、という感じですね。。
ただ、2次関数だと全然学習モデルがよい予測をしないというのはわかったので、どうしたらいいか考えます。

<その他>8/25 ペアプログラミングやってみた

ペアプログラミングやってみた

  1. 経緯
  2. やったこと
  3. やってみて印象に残ったこと
  4. 感想

自分のメモ書きとして。

1.経緯

東京の同期が帰省していた時にご飯食べに行きました。
ペアプログラミングとかしてみたいと言ったらスカイプIDを教えてくれたので、やってみました。

2.やったこと

「株予測プログラムにログ機能を追加する」のを私がコーディングし、それを見てもらうことになりました。
売買プログラムが「なぜ売買したのか(株の値動きから株価をどう予想し、どういうアルゴリズムに基づいて売買を決定したのか)」のログを取るという機能です。

3.やってみて印象に残ったこと

  • プログラム構造の考え方
    • オブジェクト指向になってない/何をやっているかわからないクラスがある。
      オブジェクト指向は、それぞれのクラスで「責務」が明確になっていることが大事。
      無意識にやろうとしていたことを言葉にしてもらうとなるほどーってなります。ここは今後も意識していこう。
    • いいプログラム=機能カスタマイズ時に影響範囲が少ないプログラム(=「責務」が明確である)
  • 生産性の違い
    • お互いがわからないこと(pythonでstatic変数を書く、等)を調べて実装するまでのスピードが全然違う。
      自分は「実際のプログラムに組み込みながら検証する」、同期は「とにかく簡単なコードを書いて実装する」
      後者のほうがよさげ。
    • 単純に俊敏さが違うなと感じました。みるみるうちにテストコードが完成していくのを唖然と眺めているときも。
      自分は結構手が止まってしまう時間が多いので…
      その他、プログラム的に細かいところはいろいろあったのですが主に思ったのはこのくらいです。

4.感想

  • 自作(コピペなし)2000行のコードを説明するというのがあまりない経験で新鮮でした。
  • 調べものや簡単な実装など簡単な作業をするときは自分と同期で同時に行うのですが、自分とやり方が全然違ったりして勉強になりました。
  • 設計について語るのが単純に楽しかったです。
  • 実作業はあまり進まなかったです。自分のプログラムの説明から入ったのですが、説明下手だったり設計にツッコミどころが多くグダグダしてしまいました。。

<株進捗>8/23 株学習の準備(完了)、シュミレーション起動

目次

  1. 学習させる株データの作成(昨日の続き)
  2. シュミレーション実行!!
  3. 今後やりたいこと
  4. その他

1.学習させる株データの作成(昨日の続き)

昨日の記事(以下)の続きをやりました。

昨日まで以下の2つの仮説を検証すべく、学習フェーズのプログラムの改修を行っていました。

目標達成の仮説1:学習データを「100銘柄の100日分」とする。
目標達成の仮説2:過去100日のデータから、未来30日分の株価の「最大値」「最小値」を予想する→予想した最大値が、現在価格より10%以上であれば売り注文を出す。

これでトレードシュミレーションできる・・・と思いきや。
上記改修により売買フェーズも改修が必要になりました。
そりゃそうですよね。

ということで、赤文字部分の改修を行っています。

  1. [学習フェーズ]以下を指定し、AIに株の値動きを学習させる。
    • 翌営業日の株価を予想するために取り込むデータ数(例:100日分を取り込み次の1日の株価を予想)
    • 各種パラメータ(隠れ層の数(2次元)、学習率、分類器、学習回数)
    • 学習対象データの絞り込み(例:指定した銘柄の値動きと相関が高いものだけを学習データとする)
  2. [学習フェーズ]学習済モデル(いわゆるAI)ができる
  3. [売買フェーズ]以下を指定する
    • [学習フェーズ]でできた学習モデル
    • 適用する売買アルゴリズム(例:予想が10%以上上がっていれば買い)
    • 適用する資産管理ルール(例:総資産の10%は現金として保有する)
    • 売買対象の銘柄
    • 売買開始時期
    • 売買日数
  4. [売買フェーズ]売買プログラムを走らせる
  5. [売買フェーズ]以下のような結果が出力される
    • 売買履歴
    • 最終的な利益
    • (売買履歴をグラフ化したもの)…余裕があれば作りたいです。

結構時間がかかっていますが、今度こそコレが終わればトレードシュミレーションができるはずです。。

ごりごりと200行弱修正しました。
「複数銘柄から1銘柄を予想する」という考え方を受け入れる設計をしていなかったので、大変でした。
きっと試行錯誤するだろうからといろんなワガママを受け入れられるように設計したつもりでも、全然ダメですね。。

2.シュミレーション実行!!!

学習モデルも適当、予想する銘柄も適当ですが、とりあえず1本通ったのが嬉しくて流してしまいました。

  • 学習させたデータ:
    • 時価総額100億以下の銘柄9つ(1408,1770,1418,1768,1776,1400,1420,1724,1711)の2015年〜2016年
  • 取引期間:2016年12月31日から30営業日
  • 初期資金:1000万円
  • トレードアルゴリズム
     ★「先30営業日の値動きの最大値」について…
       現在の10%以上上がると予想 → 買う
       現在の10%以上下がると予想 → 売る    それ以外 → 何もしない
  • 資産管理ルール
    • 総資産の10%は現金で持つ
    • 1銘柄の総額が総資産の10%を超えてはならない
    • 1銘柄を7日間で2度以上買ってはならない

結果…
f:id:kurupical:20170823214141p:plain:w500

12/31に1000万円でスタートし、2/13に1008万円になりました。やったー。
※とりあえず1本流れただけで、この結果が正しいかも検証していません・・・。笑 目標は、年利10%(どのくらいの期間で?などかなり漠然としていますが笑)。

3.今後やりたいこと

  • ログ機能の追加
    取引の根拠など、過程をすべてログファイルに出力させるようにします。
  • パフォーマンスチューニング
    いろいろな学習モデル、トレードアルゴリズム、資産管理ルールでバックテストをします。
    わくわくが止まりません・・・!
  • 有意性の検証
    統計学的に、「どの程度のデータでどの程度の結果がでれば有意性があるのか?」を検証したいです。
    統計学さわりしか知りませんが・・・
  • (将来的に)オンライン処理対応
    毎日勝手に予想してくれるようにしたいです。
  • (将来的に)サイトに予想公開
    オンライン処理対応が終われば。

4.その他

  • 今日のプログラミングは正直やっつけ仕事でした。
    本当は頭で考えてから手を動かすべきなのですが、トライアンドエラーでやってしまいました。
    嫌だなと思っていたところをゴリゴリと推し進めることができたのですが、プログラムの質は全然よくないと思います。
    仕事で残業40H超えるとトライアンドエラー・無思考になっちゃってたなあと思い返しました。
    本当に悪い癖だと思います。
  • トレードアルゴリズム、資産管理ルール、アイデア募集中です!!
  • 以下にソースコード公開しています。(そろそろ説明書作らないと・・・)
    github.com

<株進捗>8/22 株学習の準備3

目次

  1. 学習させる株データの作成
  2. 雑多なタスク
  3. その他

1. 学習させる株データの作成に伴う改修

昨日まで以下の2つの仮説を検証すべく、学習フェーズのプログラムの改修を行っていました。

目標達成の仮説1:学習データを「100銘柄の100日分」とする。
目標達成の仮説2:過去100日のデータから、未来30日分の株価の「最大値」「最小値」を予想する→予想した最大値が、現在価格より10%以上であれば売り注文を出す。

これでトレードシュミレーションできる・・・と思いきや。
上記改修により売買フェーズも改修が必要になりました。
そりゃそうですよね。

ということで、赤文字部分の改修を行っています。

  1. [学習フェーズ]以下を指定し、AIに株の値動きを学習させる。
    • 翌営業日の株価を予想するために取り込むデータ数(例:100日分を取り込み次の1日の株価を予想)
    • 各種パラメータ(隠れ層の数(2次元)、学習率、分類器、学習回数)
    • 学習対象データの絞り込み(例:指定した銘柄の値動きと相関が高いものだけを学習データとする)
  2. [学習フェーズ]学習済モデル(いわゆるAI)ができる
  3. [売買フェーズ]以下を指定する
    • [学習フェーズ]でできた学習モデル
    • 適用する売買アルゴリズム(例:予想が10%以上上がっていれば買い)
    • 適用する資産管理ルール(例:総資産の10%は現金として保有する)
    • 売買対象の銘柄
    • 売買開始時期
    • 売買日数
  4. [売買フェーズ]売買プログラムを走らせる
  5. [売買フェーズ]以下のような結果が出力される
    • 売買履歴
    • 最終的な利益
    • (売買履歴をグラフ化したもの)…余裕があれば作りたいです。

結構時間がかかっていますが、今度こそコレが終わればトレードシュミレーションができるはずです。。

2. 雑多なタスク

残していた雑多なプログラムを終えました。

  • 資産管理ルールの追加
    • 1銘柄の保有資産が、資産全体のN%以上になってはいけない(Nは調整可能)
    • 1銘柄をN日間の間に2度以上買うことはできない(Nは調整可能)
  • 学習対象データの絞り込み
  • 学習データの範囲指定(2016年までを学習し、2017年でテスト等、未知データに対するパフォーマンスをみたいので)
    などなど…

3. その他

・今日はめんどくさいと思っているところを結構片付けられたので満足です。
・以下にソースコード公開しています。
github.com