2010年12月19日日曜日

ニューラルネットワーク、遺伝的アルゴリズムによる学習

トレードルールはシンプルであればあるほど良いと良く言われますが、私もきっとそのとおりだろうと思っています。RSIにしてもADXにしてもまた前回の記事で書いたボラティリティーのスクイーズや、しばらく前に書いたNaked Close等、それぞれ特有の相場の状況をより分かり易く表してくれていると思います。しかし実際にシステムにそれらを組み合わせて活かしきることは難しいなぁと感じています。

前々からニューラルネットワークとか遺伝アルゴリズムとかには興味があったのですが、今まではニューラルネットは複雑性を増してしまい「シンプル」からほど遠くなってしまいそうだったので手を出さずにいました。が今回はどうしてもニューラルネットワークを試してみたくなりました。というのも最近Webで情報集めをしていた時に見つけた海外の論文の中に、株価の予測(明日上がるか下がるか)を重回帰やARIMAなどの従来の手法で行う場合とニューラルネットワークを使う場合を比較研究したものがあり、興味をひかれたからです。それによるとニューラルネットワークの成績が他と比べてかなり良い感じで、その理由としてニューラルネットワークの非線形性をうたっていました。その論文を読んで即座に影響を受けてしまいとうとうニューラルネットワークを試すことにしました。手始めにニューラルネットワークについて書かれた情報をいろいろ集めました。取りあえず一番スタンダード(っぽい)一方向にだけ情報が流れる3層のニューラルネットワークを試すことにしました。

まずは指標の組み合わせにより、次の足で上がるか下がるかだけでもわかればと思って検証してみようと思いました。

今回は4年分16通貨ペア程度のデータで学習させて使っていない他のデータで検証するということを試みました。入力として与えてみたのは:
現在のRSI(9)、ひとつ前のRSI(9)、二つ前のRSI(9)、現在のCorrelation(24)、ひとつ前のCorrelation(24)、二つ前のCorrelation(24)の6つの値です。
※RSI(9)は期間=9のRSI、Correlation(24)は期間=24の終値とインクリメント値(現在が24、ひとつ前が23、その前が22というような一つずつ変わる数字)との相関値です。

ニューラルネットワークに学習させる方法として(これも標準的な方法なようですが)バックプロパゲーションなる方法をまず使って見ました。オーバーフィッティングを避ける方法として(これも海外のどこかの論文に書かれていて良く利用される方法なようです)学習用のデータとは別に検証用のデータでのパフォーマンスをウォッチしながら、検証用データでのパフォーマンスが伸びなくなったら学習をやめるという方法を用いました。

例えばEURUSD2004-2008を学習用データとしてニューラルネットワークに教え込んでいきます。教え込む際に現在のニューラルネットワークが答えとして返す値と実際の本当の値を比較して、その誤差が小さくなるように繰り返し処理を行います。学習用のデータであるEURUSD2004-2008では繰り返すほど誤差が小さくなっていくのですが、ある程度以上繰り返すとあとはいわゆるオーバーフィッティングになってしまうことになります。そこでEURUSD2004-2008とは別に例えばEURUSD2003を検証用に使うということを行います。(以下がそのイメージ)

学習用データの誤差(EURUSD2004-2008) 繰り返すごとに誤差が小さくなる
繰り返し1:100
繰り返し2:50
繰り返し3:30
繰り返し4:20
繰り返し5:17
繰り返し6:15
繰り返し7:14

検証用データの誤差(EURUSD2003) 繰り返しても誤差が小さくならない地点がある
繰り返し1:200
繰り返し2:110
繰り返し3:67
繰り返し4:50
繰り返し5:51  ★ここらへんで学習をやめる
繰り返し6:50
繰り返し7:52

この方法でバックプロパゲーションを用いて学習をさせて見ました。結果は少しだけ上手く行ったがいろいろ問題ありという感じでした。 学習にはある程度時間がかかることを覚悟していましたので数時間とかのレベルであれば良しとしようと当初から思っていました。また仮に1週間かかろうとよい学習をしてくれれば最終的には使えるはずと思っていました。

ところが実際にやってみると本当の問題は学習に時間をかけても必ずしも良い結果に行きつくとは限らないという点であることに気付きました。 Webでバックプロパゲーションについてもう少し詳しく調べるとバックプロパゲーションの弱点の一つに局所的な最適解にはまってしまう点があると書かれていました。 本当は日本海溝を探しだしたいのにそのあたりの溝に落ち込んでそこが一番深いところだと思い込んでいるような感じです。これを回避するための方法がいろいろ研究されているとのことでした。

そこで回避方法のなかで(プログラムを作る立場として)一番簡単そうな遺伝的アルゴリズムを利用してニューラルネットワークを学習させるという方法を試してみました。イメージとしてはバックプロパゲーションでニューラルネットワーク内のリンクの重みを決定するのではなく、遺伝的アルゴリズムで重みを決定するという感じです。

結果は以下の通りで個人的には「これならいけそうだ」と思えるものでした。今後につなげたいと思います。

データ:2003年~2006年(1時間足)
通貨ペア=15 "EURUSD", "GBPUSD", "USDCHF",
                      "USDJPY", "EURJPY", "GBPCHF",
                      "GBPJPY", "CHFJPY", "USDCAD",
                      "AUDUSD", "AUDJPY", "EURCAD",
                      "EURCHF", "EURGBP", "NZDJPY",
                      "NZDUSD"
※検証用は上記のうち 2003EURUSD, 2004GBPUSD, 2004CHFJPY, 2005EURJPY, 2005AUDJPY, 2006EURCADの6ペア/期間で残りを学習用データとして利用しました。
※検証用データにおいての勝率(上がるか下がるかがあたった確率)は52.68% (35,086本の足において) まだこれだと実戦には使えませんが、もう少し入力を工夫したりすればもっといけるのではないだろうかと感じています。(ちなみに学習用データでの勝率は53.08%でした。)

以下にニューラルネットワークを可視化してみた際の図を示します。(青が正の重み、赤が負の重みを表し、線の太さが重みの大きさを表しています。一番左の列が入力で上から(RSI現在、RSI一つ前、RSI二つ前、相関現在、相関ひとつ前、相関ふたつ前、そして一番下はバイアス(常に1)です)を表しています。真ん中の列は隠れ層、右側が出力です。)


今後やっていきたい事ですが:
※最終的には上がるか下がるかではなくて「今安全にエントリーできる場所かどうか」というような事を教え込みたいと思っています。
※データを年毎、カレンシーペア毎に分けて、あるいはもっと細かく分けてそれぞれのパフォーマンス(誤差二乗和で現在は測っている)だけでなく、それらのばらつきがより小さいものを探すようにさせたい。(ある年だけ上手く行くルールではなくてどんな年でも上手く行くようなものをより良いものとして判断するようにさせたい)


0 件のコメント: