2019年6月6日木曜日

[MQL4] カスタムインジケーターを更新する際、最新値だけでは足りない

以前、カスタムインジケーターを最新値で更新する方法2種 を書きました。 その中で、「Buffer[0] を常に更新すれば良い」と書いたのですが、この方法には問題があることがわかりました1

1本前が更新されないことがある

以下が掲載していたコードです。

34
35
36
37
38
39
40
41
42
// NG な例
int num_uncalculated = rates_total - prev_calculated;
for (int i = num_uncalculated - 1; i > 0; i--) {
    Buffer[i] = close[i];
}
Buffer[0] = close[0];
 
// return value of prev_calculated for next call
return rates_total;

上記を実行すると、一見正しく動作するように見えます。 しかし、新しい足が作成された瞬間、つまり Buffer[0]Buffer[1] に切り替わった瞬間、Buffer[1] の値が更新されないことがあるようです。

最新足の1本前(黄色の矢印)が更新されないということです2

修正方法

以下のようにすると良いかと思います。

35
36
37
38
39
40
41
int num_uncalculated = (prev_calculated == 0) ? rates_total - 1 : rates_total - prev_calculated;
for (int i = num_uncalculated; i >= 0; i--) {
    Buffer[i] = close[i];
}
 
// return value of prev_calculated for next call
return rates_total;

num_uncalculated が 0 でも、Buffer[0] は更新されます。 最新の足に切り替わった際、num_uncalculated は 1 になるので、Buffer[1] も更新されます。

iCustom() を使う時は特に注意

この問題、iCustom() を使ったEAのバックテスト時に見つけました。

リアルタイムチャートでも起こるのかと思って試してみたのですが、私の手元では再現させることが出来ませんでした。 タイミングの問題のため、再現させるのは難しいのかもしれません。

インジケーターにもよりますが、ずれても誤差程度なので目視ではほとんど問題にならないかもしれません。 しかし、EA で使用する際は誤動作の原因3になるので注意したいところです。

  1. 元記事は修正済み 
  2. そして、リアルタイムチャートに適用し続けると、ずれた値が残る 
  3. 誤差分の差異で動きが大きく変わるような EA は大抵うまく機能しないけど… 
?