在我们接触mql5的时候,可能首先接触的就是自定义指标了,因为这是我们最直观能看到的并且使用最频繁的程序。所以我们在这套MQL5系列教程中首先加入关于自定义指标的编写。
在我们编写自定义指标的时候,有一个核心的函数,叫做OnCalculate函数。是指标的核心代码都在这里。这个函数只能在自定义指标中使用,每次价格跳动的时候执行一次(Tick事件)。这个函数有两种版本,分别用于两种情况:
int OnCalculate (const int rates_total, // 价格[] 数组的大小
const int prev_calculated, // 前一次调用处理的柱
const int begin, // 有效数据起始位置
const double& price[] // 计算的数组
);
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,但所提供的参数不一样。也就是说我们在使用的时候要根据自己的需求选择使用哪个版本的函数。一般来说,我们使用第二个的比较多,因为这个比较全面有细致。他提供了每一个Bar(柱,也就是一根蜡烛图,一下都用Bar来代替)的开始时间,开盘价,收盘价,最高价,最低价和订单交易量(也就是Tick)与真实交易量(不知道准不准)和点差。这些参数足够我们去做计算了。这里我要提醒一点就是,我们常在学习mql的时候看到OHLC其实指的就是一个Bar里的开盘价,最高价,最低价与收盘价。
而第一个版本的这个函数只提供了一个Bar中可以用作计算的参数,就是Price(价格)这个价格需要在建立指标的时候,在向导中设定计算公式。默认是最高价+最低价+收盘价的和除以3.
这个函数需要着重理解的是rates_total与prev_calculated变量,通过注释我们知道了rates_total的意思是我们计算的Bar的总数,也就是历史数据的周期数。而prev_calculated则是上一次OnCalculate函数计算时的返回值。比如这次我们这个函数返回一个值为100,那么下一次执行这个函数的时候,prev_calculated的值就是100。由于这个特性,所以我们常常看到指标的最后一句话是这样的:return(rates_total);意思就是返回所有Bar的总数,那么这样就能判断出这次执行函数是否有新的Bar加入了计算。从而控制了不重复计算同一根Bar。
即这两个变量存在的意义通常是控制指标计算流程的,为了让程序的执行效率更加的高,我们常常用这两个变量去控制循环计算的次数,让及尽量的少,并能达到我们想要的计算结果。在mt5客户端的文件夹下有很多实例代码文件,都是我们常用的指标。下面就举mql5文件夹里默认有的一个ATR指标的源代码的流程控制部分:
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 &TickVolume[],
const long &Volume[],
const int &Spread[])
{
int i,limit;
if(rates_total<=ExtPeriodATR)return(0);
if(prev_calculated==0)
{
for(i=1;i<rates_total && !IsStopped();i++)
ExtTRBuffer=MathMax(High,Close[i-1])-MathMin(Low,Close[i-1]);
}
else limit=prev_calculated-1;
for(i=limit;i<rates_total && !IsStopped();i++)
{
//some code
}
return(rates_total);
}
|