[MQL4] カスタムインジケーターを最新値で更新する方法2種
MQL のカスタムインジケーターは便利ですが、 作り方を間違えると不思議な動作をするので注意が必要です。
今回は最新(右端)のインジケーターの値が更新されない問題について書いてみたいと思います。
NG な例
まず問題点を説明するために、単純に終値を結ぶだけのカスタムインジケーターを作ってみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | #property strict #property indicator_chart_window #property indicator_buffers 1 #property indicator_plots 1 //--- plot Close #property indicator_label1 "Close" #property indicator_type1 DRAW_LINE #property indicator_color1 clrRed #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //--- indicator buffers double Buffer[]; int OnInit() { SetIndexBuffer (0,Buffer); return INIT_SUCCEEDED; } int OnCalculate( const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { if (rates_total == 0) { return 0; } int num_uncalculated = rates_total - prev_calculated; for ( int i = num_uncalculated - 1; i >= 0; i--) { Buffer[i] = close[i]; } // return value of prev_calculated for next call return rates_total; } |
これをチャートに適用すると以下のように描画されました。
一見、正しく動作しているように見えますが、黄色の丸の中をよく見ると、値が終値からずれてしまっています。
これは、描画した瞬間の終値で値が確定し、その後更新されないことに起因します。
このインジケーターをリアルタイムチャートに適用させ続けると以下のようになります。
よく見てください。終値に追従しなければならないのに、始値に張り付いています。
描画した瞬間、つまり足が出来た瞬間は「始値=終値」なので、このような動作になってしまうわけです。
解決方法1 - 戻り値を変更する
OnCalculate()
の戻り値は次の計算時に prev_calculated
として与えられます。
つまり、この値を rates_total - 1
にすることで、常に num_uncalculated
が 1 以上になり、再計算が行われます。
40 41 42 | // return value of prev_calculated for next call return rates_total - 1; } |
解決方法2 - 最新値を常に計算する
以下のように num_uncalculated
が 0 の場合も Buffer[0]
が更新されるようにします。
35 36 37 38 39 40 41 42 | int num_uncalculated = 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; } |
なお、Buffer[0]
だけを強制的に更新すると、タイミングによっては値が最新にならない可能性があります。
参考
どちらを使ったら良いか?
どちらも、最終的に行われる計算は同じですし、 どちらを使っている例も見かけるので、どちらでも良いかと思います。
ただ、更新すべき足が複数本になる場合1は、方法2の方が良いかもしれません。 更新すべき足の本数を直前で決められるからです。
[MQL4] マルチタイムフレーム対応インジケーターの作り方 を書きました。 この中で複数本を常に更新するサンプルを公開しています。