Skip to content

自定义指标-OnCalculate

OnCalculate方法的工作原理

OnCalculate是指标中最容易产生理解偏差的部分(并非复杂,而是使用习惯与常规不同)。其核心逻辑可总结为四部分:

  1. 数据获取
    获取K线的开高低收、时间、成交量、点差等数据。

  2. 数据处理
    按具体指标算法处理数据(如计算均线、RSI、MACD等公式的实现)。

  3. 数据填充
    将计算结果填充到指标的buffer(缓冲区),用于在图表上图形化显示。

  4. 返回值
    通常返回rates_total,表示当前时间下经OnCalculate处理过的K线数量。该值会作为下次调用时的prev_calculated参数,用于计算未处理的K线数量。

K线下标顺序:核心难点

MT5的K线下标逻辑与常规认知(如EA中当前K线下标为0)不同:

  • MT5默认顺序:最左边(最早)的K线下标为0,当前K线下标为rates_total - 1(总K线数减1)。
    示例:显示最近3根K线的收盘价(以柱状体为例):
cpp
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[]) {
  buffer[rates_total-1] = close[rates_total-1];
  buffer[rates_total-2] = close[rates_total-2];
  buffer[rates_total-3] = close[rates_total-3];
return rates_total;
}

编译加载后,最新3根K线的值正常显示

  • 倒置顺序(可选):将最新K线下标设为0,最早K线下标为iRetraceTotal - 1(更符合常规理解,但使用频率较低)。
    实现方式
    • 将buffer设为SERIES模式(SetIndexBuffer(buffer, 0, MODE_SERIES))。
    • 数据源(如开盘价)同样需适配此顺序。
cpp
 // 最右边为0
   ArraySetAsSeries(buffer,true);
   ArraySetAsSeries(close,true);
   buffer[0] = close[0];
   buffer[1] = close[1];
   buffer[2] = close[2];

指标绘制优化:避免重复计算

  • 首次运行(prev_calculated = 0:需计算所有K线的指标值,从下标0开始绘制。
  • 非首次运行(prev_calculated ≠ 0:仅计算未处理的K线(通常是当前新增的1根),提升效率。
    代码逻辑
cpp
   int start = 0;
   if(prev_calculated !=0 ) {
      start = prev_calculated;
   }
   for(int i=start;i<rates_total;i++) {
      buffer[i] = close[i];
   }
   return rates_total;