OnTickの処理が終わらない内に次のティックが発生するとどうなるか
OnTickにもりもりと処理を書いている時などに、ふと出てくるこの疑問。
果たしてOnTick処理は走り切るのか、その間に発生したティックはどうなるのか。
答えとしては、走り切る。その間に発生したティックでは処理できない。
EAが処理中に無限ループした場合に固まる事を考えれば、まあそうかと思えるかもしれない。
もし計算や状態管理のプログラムが割り込み処理を受けて、そこまでの処理が破棄されるようなことがあるなら、EAのコーディングは非常に難しいものになる。
プログラムを書いて確認してみる。
まず下記のEAを実行する。
#property copyright ""
#property link ""
#property version "1.00"
#property strict
long volume=0;
int OnInit(){
return(INIT_SUCCEEDED);
}
void OnTick(){
if(volume!=0){
Print("Next OnTick, ",iVolume(Symbol(),Period(),0));
ExpertRemove();
}else{
volume=iVolume(Symbol(),Period(),0);
Print("OnTick start, ",volume);
Print("OnTick end");
}
}
EA適用後、1度目のティックで現在バーのティック数を変数volumeに保持し、変数volumeに値があればEAを削除する。
実行すると次のようなログが出力される。

1度目のOnTickで”6”が表示され、2度目のOnTickで”7”が表示されている。
OnTickの処理は瞬時に走り切って、約170ミリ秒後に2度目のOnTickの処理が実行されており、ティックの取りこぼしは無いように見て取れる。
次に、下記のEAを実行する。
#property copyright ""
#property link ""
#property version "1.00"
#property strict
long volume=0;
int OnInit(){
return(INIT_SUCCEEDED);
}
void OnTick(){
if(volume!=0){
Print("Next OnTick, ",iVolume(Symbol(),Period(),0));
ExpertRemove();
}else{
volume=iVolume(Symbol(),Period(),0);
Print("OnTick start, ",volume);
int number=0;
while(true){
number++;
if(number==INT_MAX){
break;
}
}
Print("OnTick end");
}
}
1度目のOnTick処理の中で、少し時間のかかる処理を記述した。
実行すると次のようなログが出力される。

1度目のOnTickで、”OnTick start”から”OnTick end”まで3秒ほど時間がかかっている。
2度目のOnTickで確認できた現在バーのティック数は、1度目のOnTickで確認したものより8多い。
つまり、1度目のOnTickの処理中に7回のティックが発生していて、EAはこれを取りこぼしていることになる。
上記の通り、OnTickの処理はちゃんと走り切る事が確認できる。
そのため、OnTick内の処理が多く複雑であるほど、ティックの取りこぼしが起きていると考えられる。
書こうとしているロジックの中で、次の処理が不要であることが明らかになるタイミングは様々だと思うが、その判断は早ければ早いほど良い。
処理が必要だと判断する条件式は出来るだけ前に置き、不要であればすぐにreturnしてあげることで、取りこぼしを無くすよう心がけたい。