多品种时存在重复执行K线的情况,疑似BUG

前两天我发了关于 MarketPosition() 获取到的状态不对 的帖子

https://bbs.tbquant.net/thread/20250613174746908464

https://bbs.tbquant.net/thread/20250616152306846672


经过测试我将问题定位了出来 ,一个小DEMO就可以确定复现, 多品种的情况下会有重复执行同一根K线的情况


Vars
    Natural CodeProperty codePro;
    Global Array<Numeric> lastTradeBars; // 记录每个品种的最后交易Bar索引
    Global Numeric j; // 自增计数
Events
    OnReady()
    {
        
        SetArraySize(lastTradeBars, DataSourceSize(), -1); // 初始化数组,大小为品种数量,初始值为-1
        Range[0:DataSourceSize()-1]
        {
            GetProperty(codePro);
        }
        print("OnReady结束");
    }
    
    OnBar(ArrayRef<Integer> indexs)
    {
        Numeric i;
        Range[i=0:DataSourceSize()-1]
        {
            j=j+1;
            Print("时间=" + Text(Date)+"当前Bar=" + Text(CurrentBar()) + ", 合约=" + codePro.symbol + "数组="+TextArray(lastTradeBars)+"  i="+Text(i)+" 自增j="+Text(j));   
            // 如果当前Bar索引等于该品种上次交易Bar索引,跳过
            If(CurrentBar() == lastTradeBars[i] &&lastTradeBars[i]>0)
            {
                Print("时间=" + Text(Date)+"当前Bar=" + Text(CurrentBar()) + ", 合约=" + codePro.symbol + "数组="+TextArray(lastTradeBars)+"  i="+Text(i)+" 自增j="+Text(j)+" 重复执行");  

            }
            // 记录当前Bar索引
            lastTradeBars[i] = CurrentBar();
        }
    }

11997行和12003行 就可以看出来了, 随便选6个品种  回测起始时间2000年就行

可以排除是全局变量没有更新 因为 打印的时间是一样的

麻烦老师花点时间看下 ,我已经将问题定位的很明确了,复制代码即可复现



除权换仓在实盘是否存在重复执行的问题?
两个tbq3的疑似bug和一个小建议
区域统计是否存在Bug?
TBQUANT策略的执行是必须要下根K线才能执行吗,不能当前K线执行?
K线订阅的bug
请教:ONBARCLOSE函数,在当天收盘的最后一根K线时不会执行,而要等到明日或晚盘开盘的那根K线才执行的问题
发现多图层的Bug
PlayWavSound函数触发单一条件开仓时,单根K线多次重复语音播报问题
【BUG反馈】多品种交易开盘时间问题,请刘风及凯明老师进来看下
遍历期权图层时,偶然发生不执行的交易代码的情况,请TB老师分析

看了两眼代码,其实问题就是不理解机制,上面这个图表明了对应的执行逻辑

993下面这根什么重复执行,因为上面周期对应都是下面同一根

这是第一根问题,其实还有别的问题,你全局变量赋值,实时按tick执行,逻辑上可能更混乱

首先,多图层下重复执行代码是可能的,因为多品种的交易时间并不对齐。

比如,一个有夜盘的品种a,和没有夜盘的品种b,如果现在是晚上十点,那么读a品种的交易数据,读到的其实a品种下午收盘前的数据,而不是晚上十点的数据。

我们如果更是深入的举例,比如多品种下,我要比较每个品种的某个指标甲的数值,较大的发出交易信号。

那么如果下午14点时,a品种的指标值较大,所以a品种开了仓。但是等夜盘晚上22点,b品种的指标值和a品种的14点指标值比,b品种又比较大了,那是不是a品种的信号就没了呢?导致marketposition出错?

我只测试了回测,在日线级别里面,上市早的品种会先加载bar,然后到了上市晚的品种的时间才会加载晚的品种的bar。      marketposition出错   是因为重复读取了同一个bar意思就是在这个bar上多了好几个TICK 同一个bar内序列变量的值不变,所以导致了marketposition出错


你这个代码我也看下,但是扫一眼内容,你之前描述为marketposition有问题,然后这个代码主要是全局变量,说明问题还是全局变量

然后说在前面的话就是,range加你这个全局,我很难相信不出问题

然后具体是什么问题,需要分析代码

我说一下我的困惑。

你之前提到的说法是,marketposition状态不对,取到的错了。

但是,你提交的这个复现demo,通篇我都没看到marketposition。

先不说其他的,一个没有marketposition的代码,如何说明marketposition取值出错了呢?我不理解

假设 第一根bar 读取到了marketposition 为0 此时满足了策略开仓 开仓函数返回true ,此时再读取marketposition会为1。重复读取bar之后  此时marketposition 还是为0 包括时间也是一样的状态。导致了marketposition 获取到的状态不对。

onbar(...)

{

integer i;

for i = 0 to datacount - 1

{

if(ArrayFind(indexs, i))

{

data[i].xxxxx;

}

}


}


你这样写了试试

你的编码方式本来就会导致问题

其一

数据源先搞两个

更容易观察


其二

把交易设置为双向

自己读取多/空各自头寸,根据多/空头寸开平

不要用marketpostion


其三

静态回溯 逐Bar 和 实际 逐Tick

运行是有差异的

bar内

序列变量值不会变

Range[i=0:DataSourceSize()-1]

这个就是个for循环

少用

对于其一 3个品种发生问题的概率很低,代码在单品种上跑是没问题的

其二

这个能不能给个DEMO或者伪代码  我看软件内所有的策略都是基于单品种的也是根据marketpostion来判断要不要开仓的

其三 BAR内,序列变量值不会变 是这样,你说的没错。

这个没问题啊  i 一直是循环的,不存在重复的情况

老哥能给个Q么,我好跟你沟通下

你按照我上面的代码先改一下

改完就没问题了

其二

把交易设置为双向

自己读取多/空各自头寸,根据多/空头寸开平

不要用marketpostion  不用marketpostion 怎么读头寸呢

我反正是不指望老师了,如果愿意的话可以加个Q聊一下,我本身是程序员,我之前是用文华的 已经实盘了5年了,就是因为文华的多品种回测局限性很大,所以才想试试开拓者。

不用这么想

我至今还有很多问题要请教老师


longCurrentContracts

shortCurrentContracts

我不知道怎么解释

你才能明白

😢

回测级别选择日线级别