多周期-if条件判断失败,找不到原因

步骤1:在图表上加载画图公式1

//------------------------------------------------------------------------
// 简称: test_if
// 名称: 怎么c>o判断失效
// 类别: 策略应用
// 类型: 用户应用
// 输出: Void
//------------------------------------------------------------------------
Params
    //此处添加参数
    
Vars
    //此处添加变量
    plot Plt_ZT;
    
Defs
    //此处添加策略函数
    
Events
    //此处实现事件函数
    
    //初始化事件函数,策略运行期间,首先运行且只有一次
    OnInit()
    {
    
    }
    
    
    //Bar更新事件函数,参数indexs表示变化的数据源图层ID数组
    OnBar(ArrayRef<Integer> indexs)
    {
        
        range[0:DataSourceSize-1]
        {
        
            if(close > open And close[1] > open[1] And close[2] > open[2])
            {

        
                Plt_ZT.icon("support", date + time, low, "ICO72"); //画个西瓜
        
            }
        
            if(close < open And close[1] < open[1] And close[2] < open[2])
            {

                Plt_ZT.icon("resistance", date + time, high, "ICO25"); //画个哭脸
        
            }
        }
    }
    
//------------------------------------------------------------------------
// 编译版本    2025/12/3 93440
// 版权所有    quantL
// 更改声明    TradeBlazer Software保留对TradeBlazer平台
//            每一版本的TradeBlazer策略修改和重写的权利
//------------------------------------------------------------------------

单独使用这个画图,确认图表信号没有问题,在多晶硅1日线,9月15日,无标记

步骤2:图表同时加载公式2(含多周期的公式)

//------------------------------------------------------------------------
// 简称: TBDBmaTrade2
// 名称: 双均线交易
// 类别: 策略应用
// 类型: 用户应用
// 输出: Void
//------------------------------------------------------------------------
//策略规则:
//买入开仓:收盘价短期(参数Length1)均线上穿长期(参数Length1+Length2)均线,在下一个开盘价买入开仓
//卖出开仓:收盘价短期(参数Length1)均线下破长期(参数Length1+Length2)均线,在下一个开盘价卖出开仓

Params
    Numeric Length1(5,5,30,5);          //短周期        
    Numeric Length2(15,5,30,5);         //长周期        
    Numeric Amount(1);                  //交易手数,负数为交易金额
    Numeric Capital(100);               //账户资金
Vars
    Series<Numeric> Lots(0,2);
    Series<Numeric> MA1(0,2);           //短周期均价
    Series<Numeric> MA2(0,2);           //长周期均价
    Series<Numeric> indayEntry(0,2);    //日内进场次数
    Plot plt1;

Defs
    Bool TradeLots(Numeric TradeAmount)
    {
        if(TradingDate <> TradingDate[1] Or CurrentBar == 0)                                //当日第一根bar
        {
            Numeric TempUnitMoney = Open / rollover * ContractUnit * BigPointValue;         //每手市值,以开盘价计算
            Lots = Round(10000 * TradeAmount / TempUnitMoney / baseshares, 0) * baseshares;
        }
        Return True;
    }
    
Events
    OnInit()
    {
        SubscribeBar(Symbol,"15m", BeginDateTime, EndDateTime);  //原始代码这里是1d,且hide
        Data1.SetBasePeriod(Data0.Frequency);
//        Data1.Hide;
        
        Range[0:DataCount-1]
        {
            AddDataFlag(Enum_Data_RolloverBackWard());      //设置后复权
            AddDataFlag(Enum_Data_RolloverRealPrice());     //是否映射真实价格
            AddDataFlag(Enum_Data_AutoSwapPosition());      //设置自动换仓
            AddDataFlag(Enum_Data_IgnoreSwapSignalCalc());  //设置忽略换仓信号计算
        }
        SetInitCapital(Capital*10000);
    }

    OnBar(ArrayRef<Integer> indexs)
    {
        //计算交易头寸,Amount小于0,按照金额计算手数,Amount大于0就直接作为手数
        If(Amount < 0)
            TradeLots(Abs(Amount));
        Else
            Lots = Amount;
        
        //计算均价
        Range[1:1]
        {
            //尝试输出close值确认ma应用的close是否对应
            Integer i; 
            for i=0 to Length1-1
            {
                print(DateTimeToString(data0.date + data0.time) + "--data1.close["+text(i) + "]:"  + text(close[i])); //在日线上打印按照setperiod运行时对应的data0的bar时间
                
                //print(DateTimeToString(data0.date + data0.time) + "--data1.close["+text(i) + "]:"  +text(data1.close[i])); //对比一下是不是真的取的data1的值
                Commentary("序号" + text(i) +":"+ text(data1.close[i])); //为什么在data1上commentary不出来
            }
            
            print("--均价--" + text(Average(Close, Length1)));
            print("data1.CurrentBar:"+text(data1.CurrentBar));
            data1.Commentary("data1.CurrentBar:"+text(data1.CurrentBar));
            print("--------------------");
            
            //原始代码
            MA1 = Average(Close, Length1);
            MA2 = Average(Close, Length1 + Length2);
        }
        
        //原始代码
        MA1 = Data1.MA1; 
        MA2 = Data1.MA2;
        
        
        //输出测试
        print("data0.close0:"+text(close));
        print("data0.close1:"+text(close[1]));
        print("data0.close2:"+text(close[2]));
        print("data0.close3:"+text(close[3]));
        print("data0.close4:"+text(close[4]));


        
        print("均价计算:");
        print("data0.ma1:"+text(data0.MA1));
        print("data0.ma2:"+text(data0.MA2));
        print("data1.ma1:"+text(data1.MA1));
        print("data1.ma2:"+text(data1.MA2));

        print("data0.CurrentBar:"+text(data0.CurrentBar));
        print("————————————————————————————————————");
        Commentary("data0.CurrentBar:"+text(data0.CurrentBar)); 
        Commentary("data1.CurrentBar:"+text(data1.CurrentBar)); //为什么在data0上输出data1的currentbar,在日内居然会变动
        
        
        //range[0:DataSourceSize-1]
        //{
        
            //PlotNumeric("ma1", data0.ma1);
            //PlotNumeric("ma2", data0.ma2);
        //}
        //有"MA1 = Data1.MA1;",理论上画图出来的图形状应该是一样的
        PlotNumeric("data1计算的值放到data0图层ma1", data1.ma1);
        PlotNumeric("data1计算的值放到data0图层ma2", data1.ma2);
        data1.PlotNumeric("data1计算的值自己画ma1", data1.ma1);
        data1.PlotNumeric("data1计算的值自己画ma2", data1.ma2);
                
        
        //后面没有测试代码了
        
        //控制日内进场次数
        If(TradingDate<>TradingDate[1])       //新交易日
        {
            indayEntry = 0;
        }

        //交易
        If(MA1[1] > MA2[1] And MarketPosition<>1 And indayEntry==0) 
        {   
            Buy(lots, Open);
            indayEntry = 1;
        }
        If(MA1[1] < MA2[1] And MarketPosition<> -1 And indayEntry==0) 
        {
            SellShort(lots, Open);
            indayEntry = 1;
        }

        //以下画指标
        plt1.line("MA1", MA1);
        plt1.line("MA2", MA2);
    }

//------------------------------------------------------------------------
// 编译版本    2024/10/31 205152
// 版权所有    tbsh
// 更改声明    TradeBlazer Software保留对TradeBlazer平台
//            每一版本的TradeBlazer策略修改和重写的权利
//------------------------------------------------------------------------

加载这个公式后,在多晶硅1日线,9月15日,标记"ICO72",就是这个西瓜

根据画图的判断,这里不该画




这是什么原理?


公式2换过几个含多周期公式,有的标记无误,有的标记不对,找不到规律

用于展示这个异常的公式2是资源里面的(subscribe改成了15m,取消hide)

信号闪烁找不到原因
多图层期权合约平仓失败
TBQ有没判断周期内是否存在条件成立的函数
用A函数写的买卖委托失败,CTP:找不到合约
买卖前, if 两个判断条件,顺序改变,回测结果差别比较大,到底什么原因?
调用buy失败的原因怎么看
建立【数据库】初始化失败是什么原因?
提示信号闪烁但找不到原因
数据请求出错:tick补数据失败 的原因
关于多周期画线

因为跨周期以后,日线一根bar的执行次数不再是一次了,对应的小周期有几根bar,那么执行几次,而且驱动执行的对应bar数据也不是大周期收盘的数据,而是小周期bar收盘时,对应大周期bar当时的数据执行。而plot是一种不擦除的作图工具,也就是一根bar上如果执行过作图,那么后面tick如果没执行,也不会擦除这个作图结果。

总结来说,这是一种信号闪烁

我想 如果只是运行次数

那么同样订阅了多周期的其他公式,因为大周期运行次数一样,结果也应该是一样的


但试了另外一个公式,不会出现判断跟预期不一致的问题

多周期公式: (就是在系统的DualMA公式里面加了个订阅小周期)

//------------------------------------------------------------------------
// 简称: subscribe
// 名称: 订阅
// 类别: 策略应用
// 类型: 用户应用
// 输出: Void
//------------------------------------------------------------------------
//------------------------------------------------------------------------
// 简称: DualMA
// 名称: 双均线交易系统
// 类别: 策略应用
// 类型: 内建应用
//------------------------------------------------------------------------
Params
    Numeric FastLength(5);// 短期指数平均线参数
    Numeric SlowLength(20);// 长期指数平均线参数
Vars
    Series<Numeric> AvgValue1; 
    Series<Numeric> AvgValue2;
Events
    
    
    OnInit()
    {
                SubscribeBar(Symbol,"15m",BeginDateTime);
        
    }
    
    OnReady()
    {

        
        
        //Range[0:DataSourceSize() - 1]
        //{
            //SetBackBarMaxCount(1+Max(FastLength,SlowLength));
            //setPlotOption("MA1", "begin-bar", FastLength);
            //setPlotOption("MA2", "begin-bar", SlowLength);
        //}
    }
    OnBar(ArrayRef<Integer> indexs)
    {
        
        Range[0:DataSourceSize-1]
        {
            AvgValue1 = AverageFC(Close, FastLength);
            AvgValue2 = AverageFC(Close, SlowLength);
            PlotNumeric("MA1", AvgValue1);
            PlotNumeric("MA2", AvgValue2);
        
        
        
            If(MarketPosition <>1 && AvgValue1[1] > AvgValue2[1])
            {
                Buy(0, Open);
            }
        
            If(MarketPosition <> -1 && AvgValue1[1] < AvgValue2[1])
            {
                SellShort(0, Open);
            }
        
        }  
    }
//------------------------------------------------------------------------
// 编译版本    GS2010.12.08
// 版权所有    TradeBlazer Software 2003-2025
// 更改声明    TradeBlazer Software保留对TradeBlazer平
//            台每一版本的TradeBlazer公式修改和重写的权利
//------------------------------------------------------------------------


//------------------------------------------------------------------------
// 编译版本    2025/12/3 100100
// 版权所有    quantL
// 更改声明    TradeBlazer Software保留对TradeBlazer平台
//            每一版本的TradeBlazer策略修改和重写的权利
//------------------------------------------------------------------------


或者整个公式只有一句订阅,也没有异常

 SubscribeBar(Symbol,"15m",BeginDateTime);


我自己写的公式,有的有,有的没有,

排查不出来到底是哪个语句或者用法的问题

有一个机制我忘了我说过没有。

就是quant3,对于单元内的所有图层,如果保证图层标识一致,样本空间一致,周期数可整除的同一个标的,会自动启用setbaseperiod

启用的效果就是上面讲过的,大周期多次执行的时候,以bar内的数据状态进行驱动。

如果图层标识不一致,那么没有setbaseperiod效果,大周期执行几次,都是以收盘数据状态计算。

你上面的demo2,做了后复权对齐处理,所以d0d1其实自动生效了setbase机制

而demo3,没有做复权的一致性处理,没有生效setbaseperiod效果,所以大周期一直按收盘状态计算,那就出不了西瓜。


咦 还真是

demo3加上一句 SetBasePeriod("15m");

效果就变了


那这个机制还得小心,我得想想怎么按照预期的实现画图

还没有成熟的满意的策略,还比较依赖图表的写写画画来启发灵感的


之前没注意,以为Q3里面,SetBasePeriod已经可有可无了,即使不写,系统也是自动按最小周期执行的

还去看了文档,文档写的我也是按照我以为的方式理解

https://tbq.tbquant.net/helper?product_id=999&keyword=440&content_id=2595&selectedkey=3824&type=article#2.1-%E6%95%B0%E6%8D%AE%E7%9A%84%E5%AF%B9%E9%BD%90%E6%9C%BA%E5%88%B6

加了擦除语句 ,暂时目测符合预期了,再观察观察

       range[ 0:DataSourceSize - 1]
        {
    
            if(close > open And close[1] > open[1] And close[2] > open[2]  )
            {
    

                Plt_ZT.icon("support", date + time, low, "ICO72"); //画个西瓜
    
            }
            else
            {
                Plt_ZT.clear("support", date + time , date + time );
            }
    
            if(close < open And close[1] < open[1] And close[2] < open[2])
            {
    

                Plt_ZT.icon("resistance", date + time, high, "ICO25"); //画个哭脸
    
            }
            else
            {
                Plt_ZT.clear("resistance", date + time , date + time );
            }
        }
    }