全部 智大领峰 TBQuant功能 TBL语言 TB开户 问答专区 高手圈 其他
关于IF或者循环程序体内不能用序列变量的疑问
2023-12-24 17:41

关于IF条件判断、IF程序体内、循环程序体内均不能用序列函数的问题,之前看了这篇贴子,如下: http://auth.tb18.net/community/landlord.html?id=113

能理解贴子里说的意思,也就说如果要用序列函数,那么一定要把序列函数先在IF程序体外面或者循环体外面先赋值给简单变量,然后在IF程序体或者循环体内用这个简单变量即可。

但有两点不明白,请教各位老师。

1、把序列函数赋值给简单变量的这一句写在IF程序体外面或者循环体外面,但这个外面本身又在更大的IF程序体里面或者循环体里面,该怎么办呢?是一直要追溯代码,放在最大的那个IF程序体外面吗?还是说只要放在即将要使用到这个序列函数的小的IF程序内外面就行了呢?

举个例子,比如以下一段代码:

if (statusMap[Symbol()+\"_\"+Frequency] == 3)

{

Commentary(\"prep close buy\");

Bool isClose = false;

       Bool lossClose=residval < meanval;

if (lossClose)

{

Commentary(\"多头中轨平仓信号\");

isClose=True;

statusMap[Symbol()+\"_\"+Frequency] = 5;

}

   ---因为residval 和 meanval都是序列变量,所以两者的比较运算结果先赋值给简单变量lossClose,然后再放在接下去的判断条件里,此时Bool lossClose=residval < meanval的确是放在这个小的if程序体外面的,但是它同时又是在if (statusMap[Symbol()+\"_\"+Frequency] == 3开始的这个更大的if程序体里面的。那上述这样写行吗?还是说一定要放在if (statusMap[Symbol()+\"_\"+Frequency] == 3)这一句前面?假如说是一定要放在if (statusMap[Symbol()+\"_\"+Frequency] == 3)前面,但我的代码是这一句前面本身又在更大的IF程序体内,这就很纠结了。

 ---不知道我表达清楚没有,期待答复,谢谢


2、为什么IF条件或者循环体内不能用序列函数,之前的贴子说了问题所在以及解决的办法,但是对于为什么不能这样用没有详细解释,希望能回答一下具体原因。越详细越好,辛苦了。


     


kyover

看上去没太理解为什么序列变量为什么不能在分支循环结构中进行赋值的原因。简单来说,就是不能放在“或有”结构中。什么是“或有”结构?就是在每次执行时,不一定会执行的代码结构,有可能执行,也有可能不执行。为什么这样会导致错误?因为序列变量及含有序列变量需要向后传递值,如果有一根bar上的值没有计算,那么就可能导致后面连串的计算错误。

比如某个函数进行成交量的累计额,成交量在五根bar上依次为1,2,3,4,5。如果用序列变量来构造这个函数,那么每根bar上的成交量累计额只要当根发生额加上上一根累计额就行了。比如第四根bar上的累计额,没有必要计算1+2+3+4,只要计算上一根bar的累计额6,加上当根发生额4就能计算出正确的结果。类似这种算法在序列数据的运算当中效率非常高,经常被使用。

那么如果第三根bar上没有执行这个函数,会发生什么情况呢?由于第三根bar上没有执行函数,导致函数内部记录的累计额是由第二根bar传递来的。那么累计额就变成第二根bar的3,然后加上4,导致最后第四根bar上的累计额计算出来是7,很正确的10,差了第三根bar上的发生额。

这就是或有结构会导致的问题。

所以任何数据的计算,都要放在主结构中,也就是从事件域开始,不进入任何控制结构中。

关于你说的if嵌套的问题,不管嵌套多少层,只要是在控制结构中,都是有可能会出错的

另外,出错的原因是因为计算和赋值,如果表达式或者函数中没有计算赋值的操作,仅仅是引用某个容器进行不等式判断,不会有计算错误。

2023-12-25 09:11
wangkaiming

使用序列变量的函数,内部也有自己的序列变量,你套一个if

就导致内部的序列变量赋值可能缺少了

建议就是放在底层,onbar或者任何事件域第一层下面

要套IF,除非你能保证在if环境下,每个赋值都正确。那放在if里也没关系

2023-12-25 09:14
hyqh901097026

谢谢各位老师的答复,基本明白了。也就是说,为了保证不出错,无论IF的嵌套有多少层,还是放在最大的IF程序体外层,是吧?

那像TB的许多系统函数例如CROSSOVER,把序列变量表达式赋值给简单变量的语句并没有放在是外层的IF程序体外面,是因为已经确保了不会出错,是吗?

例如以下CROSSOVER代码中的Con1 = Price1[1] == Price2[1];并没有放在If(Price1 > Price2)前面。

Params

Series<Numeric> Price1(1); //数值型序列值一

Series<Numeric> Price2(1); //数值型序列值二

Vars

Bool Con1(False);

Bool PreCon(False);

Numeric Counter(0);

Begin

If(Price1 > Price2)

{

Counter = 1;

Con1 = Price1[1] == Price2[1];

While (Con1 And Counter < CurrentBar)

{

Counter = Counter + 1;

Con1 = Price1[Counter] == Price2[Counter];

}

PreCon = Price1[Counter] < Price2[Counter];

Return PreCon;

}Else

{

Return False;

}

End

2023-12-25 10:39
kyover
@hyqh901097026

你如果能保证算法没有问题,那就 可以放在控制结构里。

但是如果你自己都不清楚会不会出问题,保险起见,不要放在控制结构里。

2023-12-26 08:59
hyqh901097026

谢谢

2023-12-26 12:17
您未登录,请先 登录注册 后发表评论
顶部