自定义指标-OnCalculate
OnCalculate方法的工作原理
OnCalculate是指标中最容易产生理解偏差的部分(并非复杂,而是使用习惯与常规不同)。其核心逻辑可总结为四部分:
数据获取
获取K线的开高低收、时间、成交量、点差等数据。数据处理
按具体指标算法处理数据(如计算均线、RSI、MACD等公式的实现)。数据填充
将计算结果填充到指标的buffer(缓冲区),用于在图表上图形化显示。返回值
通常返回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)
)。 - 数据源(如开盘价)同样需适配此顺序。
- 将buffer设为
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;