在现实交易中,策略复杂多样。在backtrader中进行回测时,除了自定义Strategy子类以外,还可以通过各种order来辅助实现交易策略。
在backtrader中,Cerebro是系统的控制核心,Strategy是用户的可操控点,还需要一个将Strategy与系统其它部分相连接的角色,有了这个角色就可以将用户自定义的Strategy的信息传递给系统的其它部分,让系统按用户的需要运转起来,这个角色的扮演者就是order。
也就是说:order是连接用户自定义Strategy与backtrader系统其它部分的桥梁,让backtrader可以按照用户的想法运行(回测或者交易)。
这种桥梁作用是通过下面的方式来实现:
1. order将策略Strategy逻辑所做出的决定,翻译为代理Broker所能理解的信息,Broker最终来执行具体的交易操作。 具体的操作包括:
订单创建
通过调用Strategy的buy()、sell()、close()方法来返回订单实例。
订单取消
通过调用Strategy的cancel(order)方法来取消订单。
2. order将Broker执行交易的信息反馈给用户。 具体方式为:
上面提到,可以通过buy()、sell()、close()方法来创建订单,这里介绍一下这些方法可能使用到的参数。参数的不同选择,会使订单的交易行为截然不同。因此为了全面了解order的作用,有必要过一遍这些参数:
data(默认值:None)
order所要操作的数据。如果为None,则系统中的第一组数据(第一只股票/品种)将被使用,也就是self.datas[0]、self.data0、self.data,上面3种形式均可以表示系统中的第一组数据。
size(默认值:None)
交易单位,size是一个正数。对于买单,如果size=100,就是买100个单位数量的仓位;对于卖单,如果size=100,就是卖100个单位数量的仓位。
如果size=None,sizer实例就会通过getsizer方法来获取size的值。也就是说,除了使用buy、sell方法来设置单个订单的交易单位大小,还有方法设置全局交易单位的大小(通过Cerebro.addsizer方法来设置),这样就避免了每个order都要设置交易单位。
price(默认值:None)
交易价格。
默认值None适用于Market、Close订单(后面的exectype参数会介绍各类型订单的意义),由市场决定具体的交易价格。
对于Limit、Stop、StopLimit订单,必须显式给price赋值,price值决定了交易的触发点(trigger point)。
对于StopTrail、StopTrailLimit订单,是否显示设置price,将决定不同的交易触发点。(后续文章将详细介绍)
plimit(默认值:None)
只适用于StopLimit订单。在StopLimit订单中,plimit值被设置为隐含的Limit订单price值,而price值被用于触发当前StopLimit订单的Stop条件。(后续文章将详细介绍)
exectype(默认值:None)
可能的取值:
valid(默认值:None)
可能的取值:
tradeid(默认值:0)
这是backtrader应用的一个内部值,用于跟踪相同资产上的重叠交易。当通知订单状态的变化时,此tradeid被发送回策略。
∗ ∗ ** ∗∗kwargs
其他代理的实现可能支持额外的参数。backtrader将kwarg向下传递到创建的order对象。
close方法将首先检查当前的持仓情况,然后根据持仓情况对应地使用buy或者sell方法来清空仓位。如果用户不指定具体的size值,size会被自动计算。如果指定了size值,那么将实现部分close或者reversal订单。
为了收到订单通知,需要在用户自定义的Strategy子类中,重写notify_order方法,该方法默认为空。notify_order方法将会被以如下方式使用:
在实盘交易中,对于订单状态同为Order.Partial的通知可能会出现多次,因为实盘中订单可能会被拆分为多笔交易被执行完成。而在回测中,由于不考虑成交量的匹配,所以不会出现这种情况。
被执行的订单数据被记录在属性order.executed中,它是一个类型为OrderData的实例,包含size和price字段。
订单创建时的数据被记录在order.created中,这些数据在order的整个生命周期中保持不变。
翻看backtrader源代码,在order.py中可以看到ExecTypes列表共有8种不同类型的订单,即按照执行类型,可以分为以下8种:
ExecTypes = ['Market', 'Close', 'Limit', 'Stop', 'StopLimit', 'StopTrail',
'StopTrailLimit', 'Historical']
各种执行类型的简单说明可以参见上文中exectype参数描述部分,后续文章将进行详细描述。
在backtrader中,代理(broker)使用以下2个原则来进行订单交易:
1. 当前数据已经产生,不能被用于执行交易。
例如,Strategy的逻辑如下:
if self.data.close > self.sma: # sma表示简单移动平均线
self.buy()
在这个逻辑中,将收盘价close与移动平均线做比较,如果满足条件,就下买单。但是买单是无法用close进行交易的,因为close是已经产生的数据。只能用下一根K线的某个价位成交,成交价格取决于order类型。
订单的首个可交易的时间在下一根K线上。
2. 成交量在交易中不发挥作用
在实际交易中,成交量是会影响交易的。如果交易员是在进行非流动资产的买卖,或者是在K线的极端点(最高点或者最低点)进行的交易,成交量将影响实盘交易。
但是触及最高点/最低点是很少发生的(A股例外,有涨跌停。。。),所选资产将有足够的流动性来吸收任何常规交易的指令。因此backtrader假设成交量在交易中不发挥作用。
PS:原计划用1篇文章记录backtrader的order,写着写着发现需要5篇左右文章才能进行完整的描述。只有慢慢来了,力争把所有的知识点掰开了、揉碎了再呈现出来:)
为了便于相互交流学习,新建了微信群,感兴趣的读者请加微信。