LOADING
1163 字
6 分钟
vnpy学习06_常见的坑

模板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 sys
reload(sys)
sys.setdefaultencoding('utf-8')
vnpy学习06_常见的坑
/posts/quant/4cfe2aaf/
作者
思想的巨人
发布于
2019-04-02
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时