2016年7月25日月曜日

[MT4プログラム]EA内でマルチタイムフレームを見る場合、常時取得しないと値がずれる

Gewinn8のコミュニティで、おかしな動き(SELLしかしない)をするという報告がありました。

直接的には、その現象とは関係ないのですが、調査している途中に、不思議な現象を確認しました。

たとえば、5分足でEAを動かしている際、足の期間の違う3つの最新足のClose値を見るとします。

double closeM5 = iClose(NULL, PERIOD_M5, 0);
double closeH1 = iClose(NULL, PERIOD_H1, 0);
double closeD1 = iClose(NULL, PERIOD_D1, 0);

時間足が異なろうが、最新足のクローズ値は基本変わりません。
現在価格が、見る足によって変わったら困りますよね?

・・・・・。この困る現象が発生します(滝汗)

例えば、このプログラムは5分に一回だけ動くEAだとします。M5に新しい足が追加された時だけ動くような形になっている感じです。

その時1時間足、1日足をとると、古い値が帰ってくるのです。

具体的には、次のコードで、if文の中に入ってきてしまいます。
   double closeM5 = iClose(NULL, PERIOD_M5, 0 );
   double closeH1 = iClose(NULL, PERIOD_H1, 0 );
   double closeD1 = iClose(NULL, PERIOD_D1, 0 );
   if( closeM5 != closeH1 || closeM5 != closeD1 )
   {
      PrintFormat("miss match %f %f %f", closeM5, closeH1, closeD1);
   }

ここからは、動作から見た推測になります。
MT4は、価格情報をサーバーから取得しますが、表示していないチャート時間足毎の情報までは構築していません。

iCloseなどの問い合わせがあって、初めて構築します。その際、MT4はいったん古い情報を返した後、改めて内部で構築、サーバーから再取得を行っているようです。

いったん、iCloseがその時間足で呼ばれると、しばらくは取得していますが、ある程度呼び出しがないと再び取得を停止するようです。

そのため、この症状を解消するには、とにかくTickの発生の度にすべての価格情報をいったん読み取る必要がありそうです。

■症状が発生するコード
//------------------------------------------------------------------
// 気配値表示処理   
void OnTick()
{
   //5分に一回だけ動作する
   static datetime lastUpdate = 0 ;
   datetime current = iTime(Symbol(), PERIOD_M5, 0);
   if( lastUpdate == current ) return ;
   lastUpdate = current;

   //ヒストリカルデータは取得する。
   double closeM5 = iClose(NULL, PERIOD_M5, 0 );
   double closeH1 = iClose(NULL, PERIOD_H1, 0 );
   double closeD1 = iClose(NULL, PERIOD_D1, 0 );
   if( closeM5 != closeH1 || closeM5 != closeD1 )
   {
      PrintFormat("miss match %f %f %f", closeM5, closeH1, closeD1);
   }

■症状が発生しないコード
//------------------------------------------------------------------
// 気配値表示処理   
void OnTick()
{
   //ヒストリカルデータは取得する。
   double closeM5 = iClose(NULL, PERIOD_M5, 0 );
   double closeH1 = iClose(NULL, PERIOD_H1, 0 );
   double closeD1 = iClose(NULL, PERIOD_D1, 0 );
   if( closeM5 != closeH1 || closeM5 != closeD1 )
   {
      PrintFormat("miss match %f %f %f", closeM5, closeH1, closeD1);
   }

   //5分に一回だけ動作する
   static datetime lastUpdate = 0 ;
   datetime current = iTime(Symbol(), PERIOD_M5, 0);
   if( lastUpdate == current ) return ;
   lastUpdate = current;



この現象は、マルチタイムフレームだけではなく、多通貨を同時に監視するようなEAにも同じことが言えます。
まとめると下記の通りです。

1.最新値が読めるのは、EAが挿入されているチャートの値のみ。

2.他の通貨や時間は最新値ではない。

3.一回iCloseなどで価格を取りに行くと、そのタイミングで最新値を構築する。
 ただし、その際、iCloseはいったん古いデータを返却する。

4.一度最新値を構築すると、しばらく(1分ぐらい?)は構築し続ける。

ということで、対策は、処理の頭で、使う時間軸と通貨のiCloseを読み込み続けるということになるかと思います。

Gewinn8のように、5分一回しか動作しないし、数秒ずれたところで・・・というEAでは特に問題ないかもしれませんが、スキャル系に1秒を争う場合はちょっと許容しがたい処理遅れになるかしれませんね。このあたりは、処理内容で、価格チェックをする場合と、発注処理をする場合とで切り分けるなど、工夫が必要そうです。

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

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

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

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