2016年5月26日木曜日

[MT4プログラム]バックテストでEAの呼び出し一回目はヒストリカルデータが構築されていない場合がある対策

EAのバックテストで謎現象に悩まされていました。

次の構文をOnTickの頭で記述してあります。

   // バー数が少なすぎる場合は、処理しない。
   if( iBars(Symbol(), PERIOD_D1) < 100 ) return ;
   Print("iBars(Symbol(), PERIOD_D1)=", iBars(Symbol(), PERIOD_D1));

その際の操作履歴での結果で
iBars(Symbol(), PERIOD_D1)=0
と表示される場合があります。

・・・・
・・・・・・・・・・・
・・・・・・・・・・・・・・・・・・・・・・・オイ(--#

iBars(Symbol(), PERIOD_D1)を2回呼び出しています。1回目で値が100未満であれば、処理を終了してしまうアルゴリズムです。
2回目は値を単純に操作履歴に表示するだけですが、1回目と2回目の間には何も入っていないため本来であれば、100以上の値が帰ってくるはずです。

ところが、1回目では100以上の値が帰ってきたのに、2回目では0が帰ってくるという謎現象となっています。

EAは5分足をみて動かしていましたので5分足チャートで動かしています。 そのためなのか、なぜか日足のデータが正しくとれない場合があると想定しました。起動直後に1発目から取れないのであれば、まぁ仕方がないと思うのですが、続けて2回同じ関数を呼び出したうえで、1回目と2回目で結果が違うというのは、これいかに?1回目が0で2回目が1以上というのであれば、MT4の動きとして理解できるのですが・・。

ま、最終的にはMT4のバグじゃないかなぁと思うのですが、仕方がありません何かしら対策を打ちたいと思います。

さて、原因を探るためにGetLastErrorという関数をコールしてみます。
コード的にはこんな感じです。

   //インジケータの計算
   int ratesTotal = iBars(m_symbol, m_timeframe);
   if( ratesTotal == 0 )
   {
      Print("iBars return zero GetLastError= ", GetLastError());
   }

これで、操作履歴を見ると
GetLastError=4073
というログが残っていました。

MQL4.com Runtime Errors

から4073はNO HISTORY DATAとのこと。

・・・・。じゃぁ最初から0返せ!と言いたくなりますが、とても言いたくなります(大切なので2回言いました!)が、まぁこのように動くものは仕方がありません。

まぁ仮定に仮定を重ねる形になりますが、1回目の呼び出しではキャッシュ上かなにかの履歴を見ますが、その際実際に通信してデータが取れてきていない状態になるため、2回目で0リセットされてる・・・・・・のでしょうか・・・・。でもバックテストだし(自信なし)

そうはいっても、何かしら対策を打つ必要があります。

ヒストリデータは、iClose関数など価格情報を読みむ関数をコールすると構築されます。
そこで、EAの頭で、あらかじめiClose関数で価格データを読み込みします。


//------------------------------------------------------------------
//初期化
int OnInit()
{
   // 初回価格データを読み込み、ヒストリーを構築する。
   for( int i = 0; i < 500; i++ )
   {
      iClose(Symbol(), PERIOD_D1, i);
   }

   return(INIT_SUCCEEDED);
}

上記処理を入れたところ、2回目でiBarsが0を返すような症状は発生しなくなりました。
うーん。うーん。うーーーーーーーーーーーん。

気持ち悪いですがおまじないということで。

「MT4でFXを勝ち抜く研究をするブログ」で公開している無料インジケータは、こちらの一覧から。
インジケータ一覧

Twitterもよろしくお願いします。
https://twitter.com/mt4program

ブログランキングにご協力よろしくお願いします。m(._.)m
にほんブログ村 為替ブログ MetaTraderへ
にほんブログ村

お約束ですが、本ブログは、投資に対する利益を約束する物ではありません。最終的には自己責任によるご判断よろしくお願いいたします。