在MQ中,创建了自定义函数,中间的计算难免会用到函数内的局部变量。而主模型调用自定义函数时,如果放在了if语句体内,就会放生悲剧。举例如下:
自定义函数:
myf() //假设就计算N根K线的最高价和最低价的合计
{
Params
Numeric N;
vars
Numeric sub;
Begin
sub=High+Low;
return sum(sub,N);
End
}
主模型调用该myf
Vars
Numeric TJ; //调用自定义函数的条件
Numeric Temp;
Begin
TJ=Barpos%5==0; //假定条件是逢五就调用
if(TJ) Temp=myf(10);
End
这时,悲剧发生了。自定义函数内的变量sub,在没有被调用的时候,其数值是系统默认随便给的,只有在被调用的时候等于 High+Low,所以,返回结果Temp是空值或者不是想得到的值。
当然,如果把调用放到IF语句体外,然后再用IF来取Temp的值,就能得到结果。
问题是,以上我只是说明机制存在的问题,事实上自定义函数可能写了很复杂的算法,我就不想在不取数的时候调用它以免浪费时间,但放到IF语句体内,自定义函数内的变量就会断数,导致结果不正确。这怎么解决?
不明白您说的,“Temp是空值或者不是想得到的值”是如何编写并比对的得到的
本地测试,使用自定义函数写法计算10周期内振幅与直接编写,输出到一个副图中查看,是完全一样
如果还有疑问可以具体说明一下,您是如何比较的
截图源码:
Vars
Numeric TJ; //调用自定义函数的条件
Numeric Temp;
Numeric Temp1;
Begin
TJ=Barpos%5==0; //假定条件是逢五就调用
if(TJ)
{
Temp=myf(10);
}
PlotNumeric("A",Temp);
if(TJ)
{
Temp1=sum(High+Low,10);
}
PlotNumeric("B",Temp1);
End
上述问题很隐蔽,我仔细写了重现问题的代码如下:
主代码:
Var
Numeric TJ; //调用自定义函数的条件
NumericArray arr[10]; //自定义函数计算完毕,通过数组返回想要的数据
Numeric Temp;
Begin
TJ=Barpos%10==0; //假定条件是逢十就调用
temp=myfuc(5,arr);
DrawNumber(tj,high*(1+0.02),temp,0,blue,Fontsize18,Align2);//查看函数返回值
DrawNumber(tj,high*(1+0.01),arr[0],0,blue,Fontsize18,Align2);//查看通过参数引用返回,该值和上一行值在自定义函数内是同一值,以便对比问题所在
//以上数据用蓝色数字显示,以示和下边黑色数字区别
if(TJ) { //用条件来调用自定义函数,并用同样的两种方式查看数值返回
temp=myfuc(5,arr);
DrawNumber(tj,high*(1+0.02),temp,0,black,Fontsize18,Align0);
DrawNumber(tj,high*(1+0.01),arr[0],0,black,Fontsize18,Align0);
//同样的位置,用黑色显示
}
End
自定义函数myfuc
Params
Numeric N;//当前位置向前N根K线
NumericArrayRef arr;
Vars
Numeric tc(0);//取值范围
Begin
tc=high+low;
arr[0]=sum(tc,n);//通过数组引用返回值
Return arr[0];//通过函数返回值
End
结果如图


帮您核实了一下3楼不是问题的,主要在于编写逻辑的处理上
写在if语句里面的myfuc仅以Barpos逢十调用,因此sum只能取得当前周期tc的值,所以所有错误的返回值是相当于返回tc*5
外面的myfuc每个周期调用,因此sum可以取5周期内的值加和,您可以结合WFC开源函数中SUM函数的源码理解一下
所以此类带有周期性质的如SUM REF等函数计算时需要在IF的外部,保证每根K线都可以计算到数值,再进入IF中进行调用就可以
源码删掉IF中对于temp的赋值语句就可以,四种写法返回值就是一样的了:
Vars
Numeric TJ; //调用自定义函数的条件
NumericArray arr[10]; //自定义函数计算完毕,通过数组返回想要的数据
Numeric Temp;
Begin
TJ=Barpos%10==0; //假定条件是逢十就调用
temp=myfuc(5,arr);
DrawNumber(tj,high*(1+0.02),temp,0,blue,Fontsize18,Align2);//查看函数返回值
DrawNumber(tj,high*(1+0.01),arr[0],0,blue,Fontsize18,Align2);//查看通过参数引用返回,该值和上一行值在自定义函数内是同一值,以便对比问题所在
//以上数据用蓝色数字显示,以示和下边黑色数字区别
DrawNumber(tj,high*(1+0.03),Sum(high+low,5),0,blue,Fontsize18,Align2);//查看函数返回值
if(TJ) { //用条件来调用自定义函数,并用同样的两种方式查看数值返回
// temp=myfuc(5,arr);
DrawNumber(tj,high*(1+0.02),temp,0,black,Fontsize18,Align0);
DrawNumber(tj,high*(1+0.01),arr[0],0,black,Fontsize18,Align0);
//同样的位置,用黑色显示
}
谢谢几位版主。我自己也测试了IF语句对变量的影响规律。这点建议在说明文件写清楚,相信很多写模型的人会遇到这个陷阱。关键还是有数据返回,但返回的数据并不是预想的结果,这就比较难被发现。
我只是因为已知道某种情况的返回结果,发现显示不是预想的那样,才特来询问
MQ适用机构使用者,他们都是有编写团队的,因此语言是类似C语言的宽语言
所以像7楼这样的编程逻辑您需要注意一下,您编写过程中有不确定的地方可以使用DrawNumber或者PlotNumeric
这样的输出语句将结果输出出来方便您比对,后续编写遇到困难也可以在论坛重新发帖提问