IndicatorCounted()とprev_calculatedは同じものだと勘違いしてました。それによってインジケーターが思ったように動かず苦労しました。
Transferring Indicators from MQL4 to MQL5http://www.mql5.com/en/articles/66一見同じように書いてあるのですが、全く違います。
そんなわけで、コードを書いて挙動の確認です。
int OnCalculate (const int rates_total, // size of input time series
const int prev_calculated, // bars handled in previous call
const datetime& time[], // Time
const double& open[], // Open
const double& high[], // High
const double& low[], // Low
const double& close[], // Close
const long& tick_volume[], // Tick Volume
const long& volume[], // Real Volume
const int& spread[]) // Spread
{
Print("rates_total = ", rates_total, " Bars = ", Bars);
Print("prev_calculated = ", prev_calculated,
" IndicatorCounted() = ", IndicatorCounted());
return(0);
}
チャートに表示させたとき(バーの数を1000とします)
rates_total = 1000
Bars = 1000
prev_calculated = 0
IndicatorCounted() = 0
↓
次の瞬間(tickが来た瞬間)
rates_total = 1000
Bars = 1000
prev_calculated = 1000
IndicatorCounted() = 999
・
・
・
新しいロウソク足が出現
rates_total = 1001
Bars = 1001
prev_calculated = 1000
IndicatorCounted() = 999
↓
次の瞬間
rates_total = 1001
Bars = 1001
prev_calculated = 1001
IndicatorCounted() = 1000
というわけで、明らかに違います。安易にIndicatorCounted()からprev_calculatedに置き換えてもうまく動作しない場合があります。
もう一度リファレンスでIndicatorCounted()を読むと、
The function returns the amount of bars not changed after the indicator had been launched last.
この関数はインジケーターを立ち上げてから変化していないバーの数を返します。
これは慣れ親しんだものなので分かります。確定していない最新のバーを除いた数を返すものです。
では、prev_calculatedとは何でしょうか?
実はコメントに書いてありました。
bars handled in previous call 前回OnCalculateが呼ばれたときに扱ったバーの数
一つ前のrates_totalの値です。対象としているものが違いますよね。これで納得しました。
それで新しいバーができたときだけ、何かしたいということがあると思います。そのときは、
if(rates_total != prev_calculated && prev_calculated > 0){...}
こう書くことになるでしょうか。