问题描述:
在多品种策略回测时,部分品种没有夜盘,导致与有夜盘的品种开盘时间不一致。在回测时,没有夜盘的品种会再次驱动onbar执行,导致历史回溯时出现图表信号闪烁,且Global全局变量、全局数组等都出现问题,且该问题反复尝试了多种方法都无法避免(包括使用return中断onbar的执行)。
在实时行情时,可以通过currenttime、全局状态变量等办法过滤多次执行的问题,历史回溯却无法实现。该问题在所有数据时间线上都存在,包括所有无夜盘品种:苹果、硅铁、红枣、花生、尿素等。只要加载此类品种,就会出现问题。目前只能屏蔽这些品种。
希望官方能提供解决办法,例如增加新函数进行判断,或者从底层解决这个问题。
相关代码和图片证明在之前的帖子中:
之前的发帖(有图和代码):关于onbar执行次数的问题
http://www.tbquant.net/forum/9165.html
社区其他用户的相关发帖:商品期货多品种截面交易,onbaropen{}重复调用的问题
http://www.tbquant.net/forum/1207.html
回忆探讨了一天,基本上搞清楚你的问题了。
你的问题就是a,b两个品种,a没有夜盘,b有夜盘
日线上,两个品种的bar是一一对应的,按照onbar驱动的解释,有50根一一对应的历史bar,那么对应的公式应该跑50次。
但是实际上并不是,公式跑了100次,因为一根bar驱动了两次。你不理解的就是这个结果,对吧?
实际上,这是对于历史上,开盘时间不一致的品种,就算历史bar上按时间分布是一一对应的,但是还是按照开盘前后顺序分配来运行。因为有一些逻辑是必须区分先后的,比如如果b的夜盘数据得到了一些结果,影响了第二天a开盘的判断,如果按照图表顺序,先执行a再执行b,这个时间上的先后顺序就无法体现了
如果要区别这个驱动,可以通过检查驱动的indexs参数来决定是否要执行相关代码
比如一下例子
Events
OnBar(ArrayRef<Integer> indexs)
{
print(DateToString(date));
Numeric i;
for i = 0 to GetArraySize(indexs)-1
{
print(text(indexs[i]));
}
}
indexs也用了,另外我用TradingOpenDateTime函数也能识别开盘时间,并区别运行代码,但实际执行还是出现闪烁,还是找不到问题根源,感觉还是有问题,我再多排查下
用indexs不是就已经能解决了么?还要排查什么?
1、indexs图层返回是当前更新的图层编号,但我无法仅通过编号得知哪个品种是无夜盘的
2、通过indexs区别进行驱动,但全局变量和数组仍然是一套,可能还会有影响。我再试试看吧,现在多少有个新的方向可以尝试。
行不行,先试试看再说
不需要吧,你只要知道哪个图层驱动,就执行哪个图层的数值计算和信号执行不就行了吗
怎么说呢,这个有点复杂,策略需要对所有图层的数据进行比对,然后综合评估选出最适合的品种进行交易。也就是说,即使知道了哪个图层被驱动了,也不一定就在这个图层执行计算和信号。我这边是统一在data[0]进行综合计算,如果驱动不一致,就会出问题。
但我现在有一些思路了,可以尝试!
居然还点名了
不能通过truedate返回图层的真实交易日期么?比如今天1月1日,收盘以后,a品种停留在下午15:00,然后晚上九点b品种继续开盘,a品种停留在下午最后一根bar,那么这两个品种的truedate返回时不一致的,a品种就算驱动了,返回的时1月1日,b品种驱动返回的时1月2日,这不就区分开了吗?通过这个来决定是否要影响交易信号试试
简单来说就是循环检索所有图层的真实交易日期,找到最新的那个,然后信号条件就是判断,如果bar日期和最新的真实交易日期不符,那就不修改信号
尝试过了,按照常理只要判断不一致就可以不执行后续的代码,但图表信号仍然是提示闪烁,
比如:第一次onbar执行了开仓操作,第二次虽然区分了,采取不执行代码,但图表一次有信号,一次无信号仍然是闪烁。