プロクラシスト

今日の寄り道 明日の近道

【Day-15】ベイズ的最適化で最強のゴールデンクロスを見つける


スポンサーリンク

f:id:imslotter:20171215132801p:plain

データ分析ガチ勉強アドベントカレンダー 15日目。

最強のゴールデンクロス、それは最も儲かるように移動平均線を引いたときの交点 である。

一説には、テクニカル分析は、チャートにすべての情報が詰まっているという前提があるそうですね。 ということは、データから最適な移動平均を求められるのでは?

というわけで、今回はベイズ最適化の勉強もかねて、最適な移動平均のwindow幅をデータから出してみようと思います。

※始めに実験を載せてます。理論が気になる方は理論のところから見ると良いでしょう。 [:contents]

ゴールデンクロス/デッドクロスとは?

昨日の記事をちょっとだけ復習。

www.procrasist.com

  • ゴールデンクロス : 株価が下落した後に短期移動平均線が、長期移動平均線下から上に抜ける現象。買いのサイン
  • デッドクロス : 株価が上昇した後に短期移動平均線が、長期移動平均線上から下に抜ける現象。売りのサイン
  • (わかる株式用語より)

    長期/短期2本の移動平均線が必要なわけです。

    【実験】

    実験設定

    二つの移動平均線を使って、売り買いを判断するシステムがあると仮定する。そいつの動きはこう

    • 2015年1月4日、資産100株&100万円からスタート
    • データとして使うのは3年分の日経平均
    • ゴールデンクロス買い(全資産)デッドクロス売り(全株)
    • 2017/12/13時点で株を全部売って、総資産を計算
    • 評価値は、何%資産が増えたか*1

    つまり、シグナルにあわせて売り注文、買い注文をしていき、資産の増分が評価になる。 昨日作ったアルゴリズムで、ゴールデンクロスデッドクロスを発見できるようになっているので、そこに売り買いを入れるだけ。いいタイミングで売り買いをし、波を捉えられるかというゲーム。

    最適化

    最適化については最後に理論的な説明を簡単につけているので、そこを参照。ベイズ的最適化を用いる。下記がその時に扱うものの設定

    要素 選択
    Acquisition function EI (Acqusition functionの参考)
    kernel Mattern52
    イテレーション回数 50

    尚、実装はgithubにまとめている。

    結果は・・・?

    さあ、ベイズ最適化で計算してみた結果どうなったか!! まずは図を御覧ください。

    最適化してみた結果の、平均、標準偏差、acquisition funciton *2

    試行を繰り返せば、一番右の図の濃い黄色の部分が、選ぶべき最適な点となっているはずです。

    この結果、

    window1=91, window2 = 208で移動平均を取ると、最も儲かる

    という結果を得ることができました。ちなみにこのとき、50%資産増でした。3ヶ月と7ヶ月で移動平均ですね!!

    ちなみに、その場合に移動平均を引いたらこうなる。

    あんまり売買しないほうが儲かるということかな?ちなみにまだ売りのタイミングは来ていないようです。 ここでのクロスポイントで、売るといいのかな?データを分析したらそういってる!!

    【実装】

    GPyOpt/GPy

    今回は、実装にGPyOptを利用することにする。GPyOptは、ガウス過程計算ライブラリGPyを利用してベイズ的最適化を行うライブラリ。なので、どちらもインストールしておく必要がある。

    pip install -U scipy #scipyも最新版にしておく
    pip install GPy
    pip install gpyopt

    ※実装は長くなるので、記事では割愛しますgithubを参考にしてください。評価関数を作って、GPyOptに投げ入れているだけです!(day15)

    github.com

    【理論】ベイズ的最適化とは?

    荒野の中から宝を探す

    こちらの記事が分かりやすかったです。ガウス過程に従うサンプルとしてモデル化して最適化を行うような手法

    難しいことは下記の参考に譲るとしましょう。どれも分かりやすくていい資料です!

    ざっくりとポイントだけ。

  • f(x)の最大値を求めたい
  • fの形は分かっていない
  • けれど、xを与えて、f(x)を計算するまでに時間がかかる
  • f(x)を何か別の関数で近似する方法がほしい
  • 普通の式ならいいのですが、たとえば、xがパラメータ、f(x)が何かしらのシミュレータの場合、 まずf(x)の形を定式化することが難しいです。コレをブラックボックスといいます。さらに、一回一回の評価にめちゃくちゃ時間がかかる**とすると、xをちょっとずつ変えて全探索など、厳しいですね。

    たとえて言うなら、荒野の中から、当てもなく土を掘り返して中に眠る宝を探すイメージです。途方もないですね。 その絶望的な状況でも、賢く範囲を絞っていこうというのが、ベイズ最適化です。

    関数近似

    ベイズ最適化を用いると、平均と標準偏差の確率分布が出てくる。点が与えられた場合はその値に収束するので自信を持ってそうだといえるが、それ以外の値はあてずっぽうなので、点以外の場所は自身がなくなる(≒分散が大きくなる)。つまり、グラフは下記のようになる。



    A Tutorial on Bayesian Optimization ...より。新しい点が与えられると、自信のない領域(青くマスクされた領域)が減っていることが確認できる。

    最適化のための指針、Acquisition function

    また、上の図のAcquisition Functionというのが、最適化のために次の点を探す指針となる。 acquisition関数にはいろんな物を設定できるが、EIやUCBなどが代表的。UCBの式は、平均と標準偏差の確率分布で、下記のようにあらわされる

    \displaystyle{UCB=\mu(x)+\sqrt{\beta}\sigma(x)}

    この関数の最大値を次の点に選ぶ。 第一項目の{\mu}が近似関数なのでその最大値を選べばよいが、自信のないところも探したいそれが第二項である*3。ここから新しい点を選んで、また関数近似してを繰り返すのが、ベイズ的最適化です。

    注意

    とても強力な手法だが、下記あたりはアルゴリズム上の欠点として注意したいところ。

    • 関数近似逆行列計算が入るので(データ数)3オーダーで計算が重くなっていく
    • どこからも離れた点では分散が大きくなるので、次元が大きくなると**選ばれる点が端っこに寄る

    ※今ではこれを解決するようないろんな工夫もなされているっぽい。

    まとめ

    実験的に最適化を行ってみました。ここ三年程好景気なので、波をつかめばかなり儲かるっぽいですね。あとはチャートと自分の作ったアルゴリズムを信じるのみ!!

    また、ベイズ的最適化は、探索と活用のバランス次第では、局所解に陥る可能性もあるので、試行によっては解が変わることもあります。安定させるためにまだ色々と改良できると思っていますので、試行錯誤を繰り返していきます。もうちょっとテストもしないといけなさそうだなぁ。

    とりあえず時系列データはこのあたりで一旦置いておいて、明日は深層学習について触れたいと思っています。それではまた明日!

    *1:手数料は考えない

    *2:実装上最小値にしたかったので、評価値に-1をかけている

    *3:いわゆる探索と活用のトレードオフ

    PROCRASIST