MT4/MT5 的指标计算都带缓存,不用每次都从头到尾的在每一根 bar 上计算。指标提供了 OnCalculate 回调函数。也就是在初次加载指标时,OnCalculate 回调函数会计算一下历史 bar,然后就等待 tick 更新最后一根 bar,tick 每更新一次就刷新一次 OnCalculate,这时可能还会出现断网再重连补数据的情况,那么就需要不光要绘制最后一根 bar, 要多绘制最后几根 bar。
那么在 OnCalculate 中就可以正向循环计算和反向循环计算两种方法。
从后往前计算
//+------------------------------------------------------------------+
//| Bill Williams' Alligator |
//+------------------------------------------------------------------+
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[]) {
int limit = rates_total - prev_calculated;
//---- main loop
for(int i = 0; i < limit; i++) {
double Range = 0;
double AvgRange = 0;
for(int counter = 0; counter <= 0 + 9; counter++) {
AvgRange = AvgRange + MathAbs(High[counter] - Low[counter]);
}
Range = AvgRange / 10;
//---- ma_shift set to 0 because SetIndexShift called abowe
ExtBlueBuffer[i] = iMA(NULL, 0, InpJawsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i);
ExtRedBuffer[i] = iMA(NULL, 0, InpTeethPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i);
ExtLimeBuffer[i] = iMA(NULL, 0, InpLipsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i);
double rosokuValueCloseP = iClose(NULL, 0, i);
double JAW_ATAI_1 = ExtBlueBuffer[i];
double JAW_ATAI_2 = iMA(NULL, 0, InpJawsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i + 1);
double TEETH_ATAI_1 = ExtRedBuffer[i];
double TEETH_ATAI_2 = iMA(NULL, 0, InpTeethPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i + 1);
double LIPS_ATAI_1 = ExtLimeBuffer[i];
double LIPS_ATAI_2 = iMA(NULL, 0, InpLipsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i + 1);
if(LIPS_ATAI_1 > TEETH_ATAI_1 && LIPS_ATAI_1 > JAW_ATAI_1 && JAW_ATAI_2 < JAW_ATAI_1 && rosokuValueCloseP > LIPS_ATAI_1) {
CrossUp[i] = Low[i] - Range * 0.5;
}
else if(LIPS_ATAI_1 < TEETH_ATAI_1 && LIPS_ATAI_1 < JAW_ATAI_1 && JAW_ATAI_2 > JAW_ATAI_1 && rosokuValueCloseP < LIPS_ATAI_1) {
CrossDown[i] = High[i] + Range * 0.5;
} else {
}
}
return(rates_total);
}
从前往后计算
//+------------------------------------------------------------------+
//| Bill Williams' Alligator |
//+------------------------------------------------------------------+
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[]) {
int limit = rates_total - prev_calculated - 1;
//---- main loop
for(int i = limit; i >= 0; i--) {
double Range = 0;
double AvgRange = 0;
for(int counter = 0; counter <= 0 + 9; counter++) {
AvgRange = AvgRange + MathAbs(High[counter] - Low[counter]);
}
Range = AvgRange / 10;
//---- ma_shift set to 0 because SetIndexShift called abowe
ExtBlueBuffer[i] = iMA(NULL, 0, InpJawsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i);
ExtRedBuffer[i] = iMA(NULL, 0, InpTeethPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i);
ExtLimeBuffer[i] = iMA(NULL, 0, InpLipsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i);
double rosokuValueCloseP = iClose(NULL, 0, i);
double JAW_ATAI_1 = ExtBlueBuffer[i];
double JAW_ATAI_2 = iMA(NULL, 0, InpJawsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i + 1);
double TEETH_ATAI_1 = ExtRedBuffer[i];
double TEETH_ATAI_2 = iMA(NULL, 0, InpTeethPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i + 1);
double LIPS_ATAI_1 = ExtLimeBuffer[i];
double LIPS_ATAI_2 = iMA(NULL, 0, InpLipsPeriod, 0, MODE_SMMA, PRICE_MEDIAN, i + 1);
if(LIPS_ATAI_1 > TEETH_ATAI_1 && LIPS_ATAI_1 > JAW_ATAI_1 && JAW_ATAI_2 < JAW_ATAI_1 && rosokuValueCloseP > LIPS_ATAI_1) {
CrossUp[i] = Low[i] - Range * 0.5;
}
else if(LIPS_ATAI_1 < TEETH_ATAI_1 && LIPS_ATAI_1 < JAW_ATAI_1 && JAW_ATAI_2 > JAW_ATAI_1 && rosokuValueCloseP < LIPS_ATAI_1) {
CrossDown[i] = High[i] + Range * 0.5;
} else {
}
}
return(rates_total);
}