backtrader策略排坑:策略编制要特别关注停牌日的坑

《扫地僧Backtrader给力教程系列一》

前面发过几篇策略编制时考虑停牌问题的文章,本文汇总补充后,再发一次。本文内容亦发布于微信公众号:optMaster,公众号文章有分类,便于按需检索导航。

1 引子
有同学回测时发现一个奇怪的现象,如下图,在2010年3月11日,600000浦发银行的买单执行了三次,还有很多因现金不足作废。

这是因为600000在2010年2月26到3月10日停牌,因此2月25到3月10日发出的订单只能在3月11日执行。所以3月11日三个执行了,其他现金不足作废了。

程序中可以控制这种情况,比如不在停牌日发单,教程中有这样的案例如下,其中data0是指数,当日停牌股票的date不会等于指数的date(原因请参考教程里的策略迭代表),所以不进入可能发订单的列表,从而保证不在停牌日发单。

以上只是停牌造成的奇怪后果之一。在策略回测中,创建订单和执行订单都要考虑停牌日的特殊情况。要自问你的策略:

(1) 在停牌日允许下单吗?

(2)下单的次日是停牌日,不会执行订单,这对策略有影响吗?

(3)下单后,若明日开始股票长期停牌,你的订单可能一直无法执行,对策略有影响吗?

(4)若某日开始,股票长期停牌甚至摘牌,你的现有仓位该如何处理?

(5)多股操作时,有些股票一开始就无交易(未上市或早期停牌),这些股票迭代时最小期对其他股票的影响。

2 基本原则:数据进策略前要删除停牌日记录

由于backtrader是按bar迭代的,理论上停牌日不应该有bar,否则很容易导致在停牌日成交。因此,停牌日的记录都要在注入引擎前预先删除,这样,在策略中就不会出现停牌日的bar。

有些数据源停牌日也有股票bar的记录,只是加一个表示停牌的标志。这个是很多人容易忽略的地方。不删除停牌记录,会导致一系列莫名其妙的问题。

因此,在已假设删除停牌日记录的前提下,我们来澄清若干问题。

3 一些场景

3.1 单股策略场景

如果你的策略只需要一支股票的数据,即只有一个行情数据,那么问题比较简单。由于没有停牌日的bar,策略当然不会迭代到停牌日的bar,也就无法在停牌日下单,也无法在停牌日执行订单,因为这两个动作都必须在迭代到某个bar上才能做。也就是,系统会自动确保你只能在交易日下单,该单也只能在下一个交易日成交(如果是市价单的话)。

3.2 多股策略场景

这种场景比较复杂,涉及到多股构成的复合策略迭代表的理解,这种策略迭代表一根bar横跨多个股票的bar,如果对应的股票当天停牌,会以一根虚拟bar占位。那就是说,策略有可能迭代到这个虚拟bar,因此,也就有可能在停牌日下单,但是,这个单不会在后面的虚拟bar上成交,只可能在实际交易bar上成交,这个是backtrader自己保证的。

如果你不想在停牌日下单,那就要自己写点代码控制一下,要处理好这种情况,必须理解跨多数据的策略迭代表的构造和使用方式,建议仔细查阅我们的技术教程《扫地僧Backtrader给力教程系列一》中关于策略迭代表的内容。

有时候,我们对某股下单后,次日股票就停牌比如10天,那么第11天,可能会冒出一个很多天前的买单或卖单参杂在正常订单中,有些人的订单是有预订顺序的,但这个参杂的订单会使得订单顺序似乎错乱了。有好几位用户碰到这个问题,一开始都入坑了,找不到订单顺序错乱的原因,其实就是忘记这个梗了。

3.3 长期停牌的处理

有些股票在你发出订单后,次日开始就长期停牌,甚至退市,这些情况在回测时都要仔细考虑如何处理。

对于长期停牌的情况,比如几个月的停牌,可以通过使用带有效期的限价单来解决,使得订单到期失效。但是市价单目前不支持有效期,可能要改一下backtrader的代码,使得市价单也支持有效期。

对可能要几年的停牌甚至退市,一般都会有公告,那么迭代到公告日,就应该立即清空已有仓位,并在其后禁止发单。应该在原始数据中,有一列标注即将长期停牌,通常在公告日那个bar,设置该标志为1,然后迭代时发现该标志为1时,就要进行额外处理。

猜你喜欢

转载自blog.csdn.net/qtbgo/article/details/111468614