基于其他指标的值的自定义指标
在编写使用 函数调用的简短形式的指标时,您可能会忽略这样一个事实,即指标的计算不仅可以通过价格数据完成,还可以通过其他指标(无论是内置指标还是自定义指标)的数据实现。
让我们做一个简单的尝试:将内置 RSI 指标及标准设置附于图表,并将 自定义指标拖至 RSI 指标窗口中。在显示窗口的 Parameters(参数)选项卡中,指定指标应应用至 Previous Indicator's Data(上一指标数据)(RSI(14))。赫兹量化软件
结果与我们的预期将大相庭径。TSI 指标的附加线未在 RSI 指标窗口中出现,且在“数据窗口”中您会发现其值也同样不清楚。
尽管事实如此,RSI 的值的定义几乎贯穿整个历史数据,但 TSI 的值(应用至 RSI 数据)要么完全缺失(在开始时)要么始终为 -100:
此现象由 begin 参数的值未在 True_Strength_Index_ver2.mq5 的 中到处使用的事实导致。begin 参数指定 price[] 输入参数中空值的数量。这些空值无法用于指标值的计算。让我们回忆一下 函数调用第一种形式的定义。赫兹量化软件
int OnCalculate (const int rates_total, // price[]数组大小; const int prev_calculated, // 上次调用计算后的价格柱的数量 const int begin, // price[]数组开始计算的索引 const double& price[] // 指标计算的依据数组 );
在将指标应用至指定之一的价格数据时,begin 参数等于 0,因为各个柱均有指定的价格类型。因此,price[] 输入数组始终从其第一个元素 price[0] 起具有正确的数据。但是,如果我们指定其他指标的数据作为计算源,这一点将不再得到保证。赫兹量化软件
OnCalculate() 的 begin 参数
如果计算是使用其他指标的数据执行,让我们检查一下 price[] 数组包含的值。为此,我们将在 OnCalculate() 函数中添加一些代码,以便输出我们希望检查的值。现在 OnCalculate() 函数的起始部分如下所示:
//+------------------------------------------------------------------+ //| 自定义指标迭代函数 | //+------------------------------------------------------------------+ int OnCalculate (const int rates_total, // price[]数组大小; const int prev_calculated,// 上次调用计算后的价格柱的数量; const int begin, // price[]数组开始计算的索引 const double &price[]) // 指标计算的依据数组; { //--- 确定price[]数组数值仅输出一次的标志 static bool printed=false; //--- 如果begin变量不为0,有些数值不应该被计算在内 if(begin>0 && !printed) { //--- 让我们输出这个数值 Print("用于计算的数据索引begin等于 ",begin, " price[] 数组长度 =",rates_total); //--- 让我们显示不应该计算的数值 for(int i=0;i<=begin;i++) { Print("i =",i," value =",price[i]); } //--- 设置标志确定我们已经记录了这些数值 printed=true; }
让我们再次将修改后的指标拖至 RSI(14) 窗口,然后指定将上一指标的数据用于计算。随后我们将会看到未被绘制且不应用于计算的值,此时使用 RSI(14) 指标的值。
指标缓冲区中的空值和 DBL_MAX
price[] 数组的前 14 个元素(索引从 0 至 13,含 0 和 13)具有相同的值 1.797693134862316e+308。该值是内置常量的数字值,出现极为频繁,用于指出指标缓冲区中的空值。赫兹量化软件
在空值中填入零并不是通用的解决方案,因为该值可能是其他指标的计算结果。由于上述原因,客户端的所有内置指标均返回该数值为空值。之所以选择值 1.797693134862316e+308 是因为它是可能的最大型值,另一个原因是它可以作为常量方便地在 MQL5 中呈现。
要检查某个双精度型数值是否为空,可将其与 或 常量进行比较。两个变量的值相等,但为了使代码一目了然,最好是使用 常量。赫兹量化软件
//+------------------------------------------------------------------+ //| 针对空值返回 true | //+------------------------------------------------------------------+ bool isEmptyValue(double value_to_check) { //--- 如果数值等于 DBL_MAX, 表明是个空值 if(value_to_check==EMPTY_VALUE) return(true); //--- 不等于 DBL_MAX return(false); }