第一次用量化,改写了一下MACD,就出现奇葩问题,TB的编译器有问题吗?希望大神指点迷津,感谢!!!

就写了简单的MACD,用来显示追日的MACD值:

Params
    Numeric FastLength(12);
    Numeric SlowLength(26);
    Numeric MACDLength(9);
Vars
Defs

    Numeric MACDDiff(Integer daysAgo)
    {
        return XAverage( CloseD(daysAgo), FastLength ) - XAverage( CloseD(daysAgo), SlowLength ) ;
    }

    Numeric MACDAvg(Integer daysAgo)
    {
        return XAverage(MACDDiff(daysAgo),MACDLength);
    }
    
    Numeric MACDValue(Integer daysAgo)
    {
        return 2 * (MACDDiff(daysAgo) - MACDAvg(daysAgo));
    }
        
    
Events
    
    OnBar(ArrayRef<Integer> indexs)
    {
        Range[0:DataSourceSize() - 1]
        {

            PlotAuto("MACD",MACDValue(1),0,Color9(),Enum_Bar); 
                        
            //加上这句代码后,会改变前面的运行结果,不知何解?
            if( MACDValue(0) > MACDValue(1)){ }
            
        }
    }

就一个简单的求昨日MACD值的代码,如果加上 if( MACDValue(0) > MACDValue(1)){ } 这句代码,显示的结果就是错的,如果注释这段代码,显示的结果就正确,我就不明白了,后面的代码还能改变前面的值?

这个问题困扰我好几天,寝食难安,请高手指点!

你好,第一次使用tb,有问题咨询
信号闪烁,信号闪烁出现第一次就固定信号
关于一用策略单元设置就出现问题
TB有砖形图吗?或者自己用TB写,用什么方式
请教一下,收盘后,TICK就不会跳动了,有些函数就测试不了,收盘后TB有模拟tick跳动的功能吗?
求大神赐教 万般感谢
找大神量化代写
文华8的指标可以用吗?
关于建仓数量总是大于可开仓数量的问题,困扰很久,迫切向大神求教
请教:TB自带的海归系统出现信号闪烁的问题

又是一个【序列变量】与【用户函数】嵌套调用的【天坑】问题。【MACDValue】这个函数是你自定义的函数虽然没有直接使用【序列类型变量】,但是里面嵌套调用了【MACDDiff】和【MACDAvg】这2个函数,虽然这2个函数也没有使用【序列类型变量】,但是它们都调用了系统内置的用户函数【XAverage】,你可以进一步打开【XAverage】(TB是开放这个函数的源代码的),这里就可以看到其实【XAverage】是定义了一个【序列类型的变量】Series<Numeric> XAvgValue,这还没完,好家伙你在调用【XAverage】前,还嵌套调用了【CloseD】这个系统内置的用户函数,同样方法你打开源代码可以发现内部定义了2个【序列变量】:Series<Numeric> barCnt; Series<Numeric> dayClose; 代码我就不再贴第2份了。

//------------------------------------------------------------------------
// 简称: XAverage
// 名称: 求指数平均
// 类别: 用户函数
// 类型: 内建函数
// 输出: 数值型
// 说明: 函数中使用了序列变量请不限制条件调用
//------------------------------------------------------------------------
Params
    Numeric Price(10);                //数值型序列值
    Integer Length(10);             //周期数
Vars
    Numeric sFcactor;
    Series<Numeric> XAvgValue;
Begin
    sFcactor = 2 / ( Length + 1 );
    if (CurrentBar == 0 )
    {
        XAvgValue = Price;
    }else
    {
        XAvgValue = XAvgValue[1] + sFcactor * ( Price - XAvgValue[1] ) ;
    }    
    Return XAvgValue;
End

至于为什么【用户函数】使用了【序列变量】后,在外部调用时,就会出现很多“天坑”问题,刚好昨天也回答过一个类似的问题: https://bbs.tbquant.net/thread/20250204220009584238

所以,如果你弄明白问题的原因后,接下就是怎么解决问题了,解决办法也很简单,只要确保MACDValue函数每次都一定会在【OnBar】主体被执行,不会被编译器优化,不会因为分支路径不满足而不被执行,以下就是在你的代码基础上稍微修改一下就可以解决问题了:

Params
    Numeric FastLength(12);
    Numeric SlowLength(26);
    Numeric MACDLength(9);

Defs
    Numeric MACDDiff(Integer daysAgo){
        return XAverage( CloseD(daysAgo), FastLength ) - XAverage( CloseD(daysAgo), SlowLength ) ;
    }

    Numeric MACDAvg(Integer daysAgo){
        return XAverage(MACDDiff(daysAgo),MACDLength);
    }
    
    Numeric MACDValue(Integer daysAgo){
        return 2 * (MACDDiff(daysAgo) - MACDAvg(daysAgo));
    }
Events
    OnBar(ArrayRef<Integer> indexs){
        Range[0: DataSourceSize - 1]{
            //【建议】:把 MACDValue(1) 函数 从 PlotAuto 传参的地方抽出来,放到OnBar主体部分,确保没有执行OnBar都一定会被执行
            //把内含序列变量的函数 抽调到【OnBar】主体部分执行,是一种好的习惯,可以减少出错的几率,特别是遇到 序列类型变量
            Numeric n = MACDValue(1);
            PlotAuto("MACD", n, 0, Color9(), Enum_Bar); 
            
            //把 MACDValue() 函数调用从 If的条件语句中抽出来,放到OnBar主体部分,确保没有执行OnBar都一定会被执行
            Numeric n0 = MACDValue(0);
            Numeric n1 = MACDValue(1);
            If(n0  > n1){ }
        }
    }


CloseD的参数是一个回溯值,每一个调用,不能动态变化,要常量或不变的值,否则影响序列变量,因为CloseD里面有序列变量。

已经在关注了