バックテストとはあくまで過去のチャートデータをもとにEAがどのような作動をしたかテストをするツールです。
バックテストのチャートデータには、本当のリアルな値動きは実現できていないことと、当時のスプレッド幅はわからないという2点があります。
そのうえで、リアルタイムな運用上、そんな不確実なバックテスト結果に近づけるにはどうすればいいのか。考察し、対応いたしました。
ほとんどの場合フォワードテスト(リアル運用)はバックテストと相違が出る
バックテストを行う方はバックテストの結果を見て良好なトレードができているかどうかを図っているはずです。
そのバックテストの結果と、リアル運用の結果に相違が出ることだけは何とか避けたいものです。
しかしながら、リアルなスプレッド幅やリアルな値動きがバックテストでは反映されないため、そのほとんどの場合はフォワードとバックテストでは結果が変わってしまいます。
少しでも近づけるにはどうすればいいでしょう。
スプレッド幅制限
まず一つ目として、スプレッド幅に制限をかけるべきでしょう。
例えばUSDJPY通貨ペアの普段のスプレッド幅が0.5銭なら、0.5銭~0.7銭程度にするか、スプレッド幅制限を一切なしにするかです。
幅制限をなしにすれば、ポジションを持つ位置はバックテストとほぼ同じになるはずです。
ただし、幅が広がっているときにポジションを持つというのは基本的にはかなり不利な位置でポジションを持つことになりますから、スプレッドが広がっている場合はポジションを持たないという風に設定を変えるほうがいいでしょう。
こうすることで、バックテストよりポジション量は減るかもしれませんが、不利な位置でポジションを持たなくて済みますので、よりバックテストに近づくかもしれません。
ボラティリティの低い位置でポジションを持つEA作りを
例えば、米雇用統計発表のときに作動するEAを作ったとします。
大きく動いたときに作用するようなEAの場合、バックテストでは高い位置で売りを入れ、低い位置で買いを入れて反発してプラス域で決済。
これ完璧じゃんっていうのが作れます。
しかし、先述の通りスプレッド幅の広がりもありますので、ボラリティが高いタイミングでポジションを持つようなEAはリアルタイム運用ではほとんどの場合、バックテストのような動きをしません。
なので、ボラティリティの低いタイミングでトレードが起きるようなEAを作るほうがいいでしょう。
足のどの位置でトレードを持つか?意識したEAづくりを
バックテストは、スプレッド幅と、リアルな値動きは再現できません。
なので、バックテストのチャートデータで必ず一致するものというのは実は数個しかありません。
必ず一致するものは、以下の通りです。
上記の4点は、足の中では確実に決まっている位置です。
さらに言えば、開始位置は、足が始まるタイミングですから、リアルタイムでも追いかけることはできます。
それ以外は現在動いている足では読み切れませんが、1つ前の足なら確定しています。
なので、ポジションを持つタイミングはこの4つでかつ、基本的に1つ前の足を確認して持つのがいいでしょう。
1つ前の足の4つの一のどれかで確認をしたうえでポジションを持つようにしたEAであれば、ほぼ確実に再現できます。
スタート位置のみで作動する
さらに言えば、足の開始時のみ作動するEAを作れば、バックテストデータとフォワードテストの結果は、ほぼ一致します。
スタート位置は過去チャートでもリアルタイムデータでも確実に一致しますから、ずれることはありません。
ずれるとしたらスプレッド幅が大きくなっているタイミングがあるかもしれないというところで、それについては幅が広い場合はポジションを持たないとするしかありません。
しかし、毎回広がるわけではないですので、完全一致とまではいかなくてもほぼ一致した動きをするEAを作れます。
ただし、バックテストをする際に、開始時点でしか作動しないからといって、開始時のみというバックテストで行うとSLやTPの一に差し掛かってもそのタイミングが開始時点ではない場合は次の開始時点まで決済しない動きになるので要注意です。
本当に足の始まりのみでしか作動しないEAを作るのなら、始まりのみ作動して、あとはいったん止まるようなEAづくりをすればバックテストも一瞬で終わります。
ケルベロスの改善
上記に記載したような点を踏まえて、バックテストをまず行いました。
スタート時のみ作動するバックテストを行った場合、100万円スタートで15年で3億くらいまで膨らむEAがあったとします。
しかし、それを、全ティック運用にしただけで100万スタートが1億くらいまで減ってしまいます。
これは訳が分からないなということがわかりました。
最適化を行い、細かい係数を調整しそれを全ティック運用でバックテストを行うと破綻するケースもしばしば。
何か根本的に違うのだろうというのがわかります。
足の始まりでのみ作動するように調整
もともと、自然に足の始まりでしか作動しないよいうなEAだったのですが、なぜかこれだけの差が出るので、明示的に足の始まりでしか作動しないようにプログラムコードを書き加えました。
void OnTick(){
の直下に、
if(Volume[0]>1)return;
こう書くだけで、このEAは足が始まった瞬間でのみ作用します。
Volume[0]というのは現在の足の累積ボリューム量を数値で表す変数で、要は足が始まった瞬間は1もない要は0なんですが、0という数字が出ないらしく、1未満とすることで、ボリュームがカウントされるまでの間=足が始まった瞬間だけ動くようにできるプログラムコードです。
これを入れることで、SLやTPの作用以外はほとんどがスタート時のみのバックテストと同じになります。
逆に言えばこれを入れないとスタート時と違うということは微妙に足のスタート以外でもポジションか決済のタイミングでスタート以外にもやることがあるということですね。
足の始まりだけでは大きな問題が残る
バックテストを行っているうえでは、問題は何も起きません。
これは実際に運用を始めて初めて分かることなのですが、ケルベロスは、3通貨ペア同時に運用してこそシナジー効果が表れて大きなドローダウンを発生させずに運用できると想定して作ったEAなのです。
ということは、3つ同時に運用したらどう動くのかが大事なんです。
足の始まりだけ動くというのは、0秒001くらいのタイミングしか動かないということで、要は3つ同時にポジションが持てないのです。
実際見ていると5秒くらいの間でやっと3通貨ペア持てる感じです。
なので、上記のコードではまともに運用できないということになります。
さてどうするか...
returnというコードでEAを一旦止めるので、returnをかければいいのはわかっているのですが。。。
そこで思いついたのは、0分0秒のときだけ作動するようにすればいいんだということに気づきました。
if(Minute()>0 || Seconds()>0)return;
これで0分以外と、0秒以外はEAの作動が止まります。
そして、これでは先ほど言ったように同時に運用していると最大で4秒くらい遅れることがあるのはわかっているので、Secondsに関しては少し余裕を持たせて>6としました。
これで、5秒以内に作用するようになりました。
さらに、現在価格とオープン価格の差が3pips以内ならポジションを持つように設定することで、その1~5秒の間に値が大きく動いてしまった場合はあきらめましょうというようにしました。