VeighNa量化社区
你的开源社区量化交易平台
havenonetosay's Avatar
Member
离线
36 帖子
声望: 0

MTF wrote:

这个设计早期是为了避免用户误删策略后找不回来缓存数据,现在看可能加个点击【删除】按钮后的确认对话框更加合适?请在Github开个issue吧
好的

我看了一下CtaEngine类的源码,删除策略以后,因为strategy_data里的对应key没有被删除,CtaEngine类里面压根就没有删除strategy_data里key的相关逻辑,也就是说,strategy_data里会一直保存已经删掉的策略的变量数据。

这应该算是纰漏吧?

strategy_engine.remove_strategy("xxxxx")
调用remove_strategy以后,只有cta_strategy_setting.json里的相应的数据被清理了,但是保存变量的cta_strategy_data.json里的数据没被清理。
这会导致下次如果新建一样名字的策略,会加载之前的数据。这是故意这么设计的吗?为什么呢
从语义来说,既然是删除了策略,就应该把保存的变量也清理干净,就像删除了文件,总不能创建新的同名文件还会残留之前老文件的内容吧?

MTF wrote:

havenonetosay wrote:

我的策略是每天早上8点50分自动启动,目标合约是pg液化石油气。
8:50还没到竞价阶段,但是启动后on_tick收到的第一个tick的时间居然是当天晚上10点59分的,
比如1月1日早上8:50启动,结果收到的第一条tick的datetime居然是1月1日晚上10:59的,
结果导致BarGenerator无法生成分钟bar了(因为BarGenerator只会接收比上一条tick时间更晚的tick)。

初步估计是vnpy_ctp对大商所的ActionDay的处理问题,所以应该不只是pg合约,大商所的合约都可能有这个问题。(这下不得不吐槽国内的交易所对 TradingDay/ActionDay 的处理问题了,几个交易所几个不同标准,FXXK.)
我看到论坛上有过滤无效tick的解决办法:https://www.vnpy.com/forum/topic/30601-che-di-jie-jue-tickshu-ju-de-guo-lu-wen-ti
但是修改的地方太多了,不利于vnpy后续更新(除非官方把修改合并进去)

主要是这个异常tick如果不考虑本地系统时间,单纯从tick的datetime还无法判断是否无效,因为它也确实是正常的交易时间内。
目前一个不太优雅的解决办法是,直接取系统时间,如果是9点前收取的tick一律无视。
但这种过滤方法又会影响回测和载入历史tick,所以针对这个问题又得额外增加判断逻辑。

看vnpy_ctp的仓库已经开了Issue,大家有什么思路在这里一起讨论下吧。

确实对于大商所的日期特殊处理,就是导致上述问题的原因。

因为大商所的ActionDay和TradingDay是相同的(没有遵循上期对ActionDay的规范),
所以对于大商所夜盘品种来说,针对早上开盘前的tick快照(也就是这个品种的最新一个tick,对于pg来说也就是前一天晚上10点59分的tick),不论是取ActionDay还是TradingDay,还是取本地实际实际日期,都不对。
问题是没有接口能查询上一个交易日的日期,毕竟有周末或者节假日,所以又不能单纯把日期减1。

我目前想到的一个简单的判断逻辑是,直接把这个datetime和本地时间做对比,误差超过5分钟(设置一个阈值),就视作无效tick。

MTF wrote:

havenonetosay wrote:

根据文档,下单的时候有个net参数可以设置净仓下单模式,多数情况下是正常的,但是偶尔(概率并不小)仍然会出现锁仓的情况。
比如当前的pos是1,
调用self.sell(order_price, 2, net=True)
大概率是会先平1手多仓,然后再开1手空仓。
但是有一定概率会直接开2手空仓,造成有1手锁仓的问题。

反之当前pos是-1的时候,
调用self.buy(order_price, 2, net=True)
大概率是会先平1手空仓,然后再开1手多仓。
但是有一定概率会直接开2手多仓,造成有1手锁仓的问题。

出问题的概率只是相对低,实际并不低,
我对接simnow,写了个run.py,同时开启所有主力合约。
过1天,就有一大堆锁仓的。

每次下单之前我都会调用self.cancel_all(),所以实际伪代码类似下面这种:

self.cancel_all()
self.buy(order_price, self.target_pos-self.pos, net=True)

因为有可能上次报单价格没有成交,所以会先撤单,再重新下单。
我猜可能是由于撤单和成交回报不同步导致的vnpy对仓位的判断错误而导致的净仓转换的问题。

请问这种要怎么解决呢?

出现这种情况的原因,大概率是还有活动委托的撤单回报尚未收到。

底层OffsetConverter组件对于开平的转换,是基于仓位的【可用】数量进行的,所以如果之前已经挂出的委托撤单后,回报尚未收到的情况下(即冻结部分没有解锁),此时反向委托就会造成开仓。

TargetPosTemplate内部实现了一个简单的交易状态机,必须没有在途委托时才允许重下,所以不会有这个问题。

我刚开始对于TargetPosTemplate里面反手的时候“先平后不开”的操作不理解,现在明白了为什么要等下次再开仓了,就是为了确保报单成交或者确认撤回以后再开。

原来CTA还有个TargetPosTemplate模板,文档里都没提到这个。先试试用这个模板会不会锁仓
果然文档只是参考,要弄明白还得看框架的源码啊。

根据文档,下单的时候有个net参数可以设置净仓下单模式,多数情况下是正常的,但是偶尔(概率并不小)仍然会出现锁仓的情况。
比如当前的pos是1,
调用self.sell(order_price, 2, net=True)
大概率是会先平1手多仓,然后再开1手空仓。
但是有一定概率会直接开2手空仓,造成有1手锁仓的问题。

反之当前pos是-1的时候,
调用self.buy(order_price, 2, net=True)
大概率是会先平1手空仓,然后再开1手多仓。
但是有一定概率会直接开2手多仓,造成有1手锁仓的问题。

出问题的概率只是相对低,实际并不低,
我对接simnow,写了个run.py,同时开启所有主力合约。
过1天,就有一大堆锁仓的。

每次下单之前我都会调用self.cancel_all(),所以实际伪代码类似下面这种:

self.cancel_all()
self.buy(order_price, self.target_pos-self.pos, net=True)

因为有可能上次报单价格没有成交,所以会先撤单,再重新下单。
我猜可能是由于撤单和成交回报不同步导致的vnpy对仓位的判断错误而导致的净仓转换的问题。

请问这种要怎么解决呢?

我的策略是每天早上8点50分自动启动,目标合约是pg液化石油气。
8:50还没到竞价阶段,但是启动后on_tick收到的第一个tick的时间居然是当天晚上10点59分的,
比如1月1日早上8:50启动,结果收到的第一条tick的datetime居然是1月1日晚上10:59的,
结果导致BarGenerator无法生成分钟bar了(因为BarGenerator只会接收比上一条tick时间更晚的tick)。

初步估计是vnpy_ctp对大商所的ActionDay的处理问题,所以应该不只是pg合约,大商所的合约都可能有这个问题。(这下不得不吐槽国内的交易所对 TradingDay/ActionDay 的处理问题了,几个交易所几个不同标准,FXXK.)
我看到论坛上有过滤无效tick的解决办法:https://www.vnpy.com/forum/topic/30601-che-di-jie-jue-tickshu-ju-de-guo-lu-wen-ti
但是修改的地方太多了,不利于vnpy后续更新(除非官方把修改合并进去)

主要是这个异常tick如果不考虑本地系统时间,单纯从tick的datetime还无法判断是否无效,因为它也确实是正常的交易时间内。
目前一个不太优雅的解决办法是,直接取系统时间,如果是9点前收取的tick一律无视。
但这种过滤方法又会影响回测和载入历史tick,所以针对这个问题又得额外增加判断逻辑。

MTF wrote:

为了简化投组策略开发的难度吧,很多用户还是不太会写这块多合约的执行
谢谢回复,我的意思不是set_target的初衷,我是说rebalance_portfolio里的具体实现,它下单的时候是根据目标持仓和 已有持仓的差值来计算买卖开平的数量,但是有个net净仓下单的参数,直接可以做到这一点,为什么要rebalance_portfolio函数里又要单独写逻辑算一次呢

我看了一下rebalance_portfolio的源码,
它是自己计算的 平开数量,为什么不直接用send_order的net净仓模式下单呢?这样做有什么区别吗?

有的策略跑着跑着pos就和实际持仓不一致了,导致有仓位“泄露”,最终结果就是该平的没平,一直漏在那,
主要又是小概率事件,不一定能重现,所以不好找原因。
所以能不能定期同步pos呢

MTF wrote:

  1. 策略可以自行记录委托号信息,并写入在缓存变量中(重启后自动加载)
  2. 或者可以重启后,手动一键全撤之前的委托,然后策略中就无需记录(重启后自动根据逻辑再下新的)

感谢解答

如果通过CTA策略挂出去的单没有成交,然后策略意外退出了,重新启动以后那些单是不是就“泄露托管”了?
因为我看介绍说,不论是撤单还是计算持仓都是基于vnpy自己维护的状态,换句话说其它客户端的持仓和下单,vnpy是“视而不见的”,那么像我说的这种情况,vnpy挂单以后崩溃退出,重新运行以后,之前挂的单是不是就在策略里控制不了了?因为我看vnpy保存的变量除了策略自定义的之外就只有pos,没看到它保存挂出去的单号啊?

https://github.com/vnpy/vnpy_ctp/issues/34
我在github上也发了这个疑问,担心github没人看,所以发在论坛希望有人能解惑,

` def onRtnDepthMarketData(self, data: dict) -> None:
"""行情数据推送"""

    # 过滤没有时间戳的异常行情数据
    if not data["UpdateTime"]:
        return

    # 过滤还没有收到合约数据前的行情推送
    symbol: str = data["InstrumentID"]
    contract: ContractData = symbol_contract_map.get(symbol, None)
    if not contract:
        return

    # 对大商所的交易日字段取本地日期
    if not data["ActionDay"] or contract.exchange == Exchange.DCE:
        date_str: str = self.current_date
    else:
        date_str: str = data["ActionDay"]`

几大交易所的TradingDay和ActionDay定义都不一样,
看了一下,因为大商所的ActionDay比较特殊,它实际上应该是TradingDay,所以vnpy的CTP模块的源码里,如果是大商所的行情,日期就取本地日期。
但是这样做是否会有隐患?
虽然联网的电脑或者服务器都有网络时间校准,但是也有极端情况
比如行情是 1号 晚上23点59分59秒:500毫秒 的,但是到达本地的时候,因为网络延迟或者本地时间误差,本地时间已经是2号0点了,如果替换成本地日期,那就变成 2号 23点59分59秒了,有没有出现这种可能呢?
这是不是有问题呢?

MTF wrote:

可以用净仓交易模式来执行(委托函数中的net字段传True),然后自己基于on_trade维护一个持仓数据

xiaohe wrote:

那可以使用净仓交易模式https://www.vnpy.com/docs/cn/cta_strategy.html#cta-ctatemplate

谢谢你们,原来净仓模式是这个意思

目前想的是完全取消对self.pos的依赖,自己根据on_trade来维护 开多 和 开空的数量。

国内分了4种情况,感觉反而容易乱套,我本身没有锁仓的需求,我甚至觉得锁仓就是一个无意义的行为,网上说锁仓各种好处,什么留下思维空隙,静下心来慢慢分析啥的,我感觉锁仓理由各种离谱,没找到锁仓的意义,从结果看跟平仓没区别,既然要冷静思考,干嘛不直接平了,而锁仓白白占用双倍保证金?

现在buy sell short cover,对于我的策略而言,反而搞复杂了。我完全不需要锁仓的情况,
能否有简单的办法实现只用sell和buy来做到自动开平仓做多做空呢?
因为我的策略经常会反手操作,目前的流程就是根据self.pos的正负,先平仓,再反向开仓,但是这个过程中可能出现各种意外情况,比如部分交易,挂单未交易等等,导致后续还是莫名其妙出现锁仓而额外占用保证金。

懂了,要用edit_strategy……

我在noui的脚本里面更新策略参数,发现启动以后还是旧参数,必须关掉,下次再启动才是新的参数。
我是先update_strategy_setting
然后init_all_strategies
然后start_all_strategies

按道理我更新参数是在启动之前,为什么要等下次启动才生效呢?
我看了一下update_strategy_setting的源码,貌似它更新了cta_engine里保存的对应策略的参数,然后保存了json。

© 2015-2022 微信 18391752892
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

【用户协议】
【隐私政策】
【免责条款】