新版的 MT4 指标计算在 OnCalculate 函数中,每次 tick 数据变动,相当于刷新最后一根 bar 的 Close。这时只需要重新计算最后一根的 bar 上的数据。显然不希望在最后一根 bar 上不断更新收盘价时,均线缺不变化。
但是如果在 EA 中用 iCustom 来引用这根均线时,可以采用上一根已收盘的 bar 的来计算。
采用 Bars - IndicatorCounted() - 1 的方式
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[]) {
// 每次响应 tick 数据时都会回调
// 未计算的 bars
int limit = Bars - IndicatorCounted() - 1; // 这种方式如果计算过, limit = 0
LOG_INFO(StringFormat("limit: %d", limit));
// 从前往后算
for (int i = limit; i >= 0; i--) {
log_info(log_handle, StringFormat(
"Open: %f\tHigh: %f\tLow: %f\tClose: %f", Open[i], High[i], Low[i], Close[i]
));
BufUP[i] = iBands(NULL, 0, BB_Period, 3, 0, PRICE_CLOSE, 1, i);
BufCenter[i] = iBands(NULL, 0, BB_Period, 3, 0, PRICE_CLOSE, 0, i);
BufDOWN[i] = iBands(NULL, 0, BB_Period, 3, 0, PRICE_CLOSE, 2, i);
BufDOWN_Arrow[i] = EMPTY_VALUE;
BufUP_Arrow[i] = EMPTY_VALUE;
if(BufUP[i] < High[i]) {
BufDOWN_Arrow[i] = High[i] + 30 * Point;
}
if(BufDOWN[i] > Low[i]) {
BufUP_Arrow[i] = Low[i] - 30 * Point;
}
}
return(rates_total);
}
采用 rates_total - prev_calculated - 1 的方式
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[]) {
// 每次响应 tick 数据时都会回调
// 未计算的 bars
int limit = rates_total - prev_calculated - 1; // 这种方式必须 -1, 不然第一次计算引用第一根 bar 会出现错误,limit = -1
if (limit < 0)
limit = 0;
LOG_INFO(StringFormat("limit: %d", limit));
// 从前往后算
for (int i = limit; i >= 0; i--) {
log_info(log_handle, StringFormat(
"Open: %f\tHigh: %f\tLow: %f\tClose: %f", Open[i], High[i], Low[i], Close[i]
));
BufUP[i] = iBands(NULL, 0, BB_Period, 3, 0, PRICE_CLOSE, 1, i);
BufCenter[i] = iBands(NULL, 0, BB_Period, 3, 0, PRICE_CLOSE, 0, i);
BufDOWN[i] = iBands(NULL, 0, BB_Period, 3, 0, PRICE_CLOSE, 2, i);
BufDOWN_Arrow[i] = EMPTY_VALUE;
BufUP_Arrow[i] = EMPTY_VALUE;
if(BufUP[i] < High[i]) {
BufDOWN_Arrow[i] = High[i] + 30 * Point;
}
if(BufDOWN[i] > Low[i]) {
BufUP_Arrow[i] = Low[i] - 30 * Point;
}
}
return(rates_total);
}
另外一种写法
int limit;
if (prev_calculated == 0)
limit = rates_total - 1;
else
limit = rates_total - prev_calculated;
总结
- 不管用何种方式,都要使
limit = 0
,这样在正向循环计算时始终计算最后一根。 - 有也从后往前计算的方式,但是像 supertrend 这样的指标需要前一根 bar 的数据,不能倒着计算。均线可以倒着计算。