模板TargetPosTemplate的cancelAll()隐患
在阅读vnpy的样例代码可以发现,其主要逻辑都是在onbar(or ontick)中实现,这个和大部分基于股票回测的类似zipline等基本类似。但稍有差异的是onbar中首先会清空之前订单,也即是调用self.cancelAll()方法。
但是,在使用模板TargetPosTemplate时,系统提供样例MultiSignalStrategy却没做相同处理,看了下其实是在
calculateTargetPos() self.setTargetPos(targetPos) self.trade() self.cancelAll()但这么做其实有风险的,大部分时候如果仓位没变化不会调用这个方法的。但对于止损单来说,若采用随止损时却需要实时以最高价百分比下止损单,所以需要每个bar都调用cancelAll()进行旧止损订单清理。
数据初始化的几个小坑
self.am = ArrayManager(size=100)
在系统样例中,可能会忽略,采用的都是默认值100,但如果回测时间需要很长的化就需要修改这个取值。
这个值会影响那些地方呢?
在样例策略中,有这么个共同点
onbar(): if not am.inited: return这里的am.inited就是指am中填充的数据是否足够,而足够就是由size=100来定义的。在初始化的数据填充足够后inited会变为True。
另外一个需要注意的地方是:
initData = self.loadBar(self.initDays)
这里的self.initDays是天数,在bar为分钟等时,需要留意下,除240后填充到这里,避免初始化过多数据。
还有就是在BacktestingEngine
self.strategy.inited = True self.output(u'策略初始化完成') self.strategy.trading = True当am.inited被设置为True之后,如果self.strategy.trading=True会正常下单,否则虽然onbar执行逻辑正常,但是订单却不会被撮合。
理想的情况是我们需要240个分钟bar,则size=240,然后数据出事成功后,恰好am.inited=True,and ,trading = True但是实际可能不会那么凑巧。
建议回测时将initday设置偏小,比如需要360分钟bar,initday取(360/240)=1.5->1,然后初始结束后am.inited=False,回测引擎会继续执行后续的onbar填充am,直到am达到360才会执行onbar的后续业务相关逻辑。
这么做虽然会跳过一段时间,但是整体业务是顺的,不会出现应该下单的却找不到下单到哪里的诡异问题。
纠正错误
上面思路没错,但会引起另一个问题,实盘时如果按照上面的思路回导致时间段跳过的问题,比如设定需要300个bar,那么由于initday设置的是1天,1天只有240个分钟bar,导致新的一天,60个bar用来积累数据了。
所以可能还是按照超额设定initday合理一些,避免实盘错过时间段。
撮合规则
撮合普通限价单推送2条信息
self.strategy.onTrade(trade) self.strategy.onOrder(order)撮合止损单推送3条信息
self.strategy.onStopOrder(so)self.strategy.onOrder(order)self.strategy.onTrade(trade)如果需要在止损单触发时执行一段逻辑,最好在onStopOrder里面做修改,并且留意以订单的状态(所有止损单都会通知这里,包括新增订单,撤销订单和订单成交等)
停止单的orderid
并且对于停止单而言,下单成功后返回的
order_ids = self.cover(xxx,True)这里的order_ids是list,里面每个元素大概长这样“CtaStopOrder.26”,以CtaStopOrder开头的。而非常规数字id
在回调函数中onStopOrder的so入参对应onStopOrder.stopOrderID变量
行情的时间为bar开始时间(vnpy19)
比如9.00-9.01的行情时间戳为9.00的,
这个不同平台规则不同,有些会算到9.01上,在数据导入时需要留意,保持一致
如果不一致会有什么问题?
vnpy19在组合bar为am时(barCircle),会采用(分钟+1)%barCircle的整除判断,所以收到14.59(此时时间时间为9.00的第一个tick(或夜盘的第一个tick))的bar时就会凑整,推送新am,进而产生信号.
所以如果导入的数据以15.00结尾,由于尚且处于回放阶段(ontrade=false)所以,虽然触发了发单操作(有信号的化)但被trading状态阻止,所以无法发出,只有在9.30时才追触发新发单操作.
上海能源所(INE)平今问题
上海期货所一般都知道,平今和平昨需要指令区分,其实能源所INE一样的,vnpy20并未考虑到.需要手工修改,修改点并不多,
搜索Exchange.SHFE,if xx==Exchange.SHFE.
改为Exchange.SHFE,if xx in [Exchange.SHFE.Exchange.INE]
其他异常or报错
1,UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe5 in position 0: ordinal not in range(128)
import sysreload(sys)sys.setdefaultencoding('utf-8')部分信息可能已经过时