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

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

根据文档,下单的时候有个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,所以针对这个问题又得额外增加判断逻辑。

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

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

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

` 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秒了,有没有出现这种可能呢?
这是不是有问题呢?

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

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

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

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

我想在策略close的时候创建一个窗口,输出我需要的信息,
我尝试在策略的on_close里加入:

widget = QWidget()
...
widget.show()

发现回测的时候会直接卡死。

但是用

widget = QDialog()
...
widget.exec_()

却可以,但是这个时候是个模态对话框,我如何创建非模态的窗口呢?

目前我这样写,不行

def on_init(self):
        if self.is_backtesting:
            self.load_bar(10)
            self.load_tick(10)
        else:
            self.load_bar(10)

我的直觉是,当回测选择tick的时候,那个load_bar就会失效,选择1m的时候,那个load_tick就会失效。
但是实际情况是:
如果选择tick回测,那个load_bar会把tick数据传到on_bar方法里面,造成错误
同理
选择1m回测,那个load_tick会把bar类型的数据传到on_tick方法里面,也造成错误

代码层面没办法判断回测输入的回测数据类型吗?
我现在只能根据测试反复注释这两句来切换,有点麻烦。

至于为什么会同时支持两种回测,
策略实际交易是根据tick数据来下单的,但是回测下载tick数据太慢,所以做了一个兼容1m k线回测的方案,但有时候也需要比较精确的tick回测。
所以就会遇到回测的时候两种周期

实际tick数据会包含9:00之前的数据,从8:55开始就有可能行情进来了,好像是开盘前的撮合竞价,大多数8:59会有开盘前的行情,这个时候貌似有的交易所能报单,有的会拒单。
我看其它的交易软件,他们都是把9:00开盘前的行情当作是9:00的开盘价,也就是说把8:59的行情合并到9:00的k线上的,包括开盘价和交易量。
虽然实际情况下这一点点影响不大,但是我的策略用到了ArrayManager,着多出来的8:59的tick会导致多一根ma出来,造成策略有问题。
同理,晚上20:59分也是一样的情况
请问一个 比较好的处理方式是什么?
直接在on_tick里判断时间,然后把开盘前的数据过滤掉不传给BarGenerator的update_tick?
或者有其它的办法?

CTA不是有一个pos变量用来存储持仓吗?
如果我通过交易软件平仓了,那pos变量会跟着改变吗?

我是用no ui的方式启动的策略,看官方的示例,到了停盘的时候会停掉对应的子进程,
到了开盘的时候,再重启策略,但ArrayManager的数据怎么办,又得重新初始化?

虽然策略在初始化的时候使用了load_tick或者load_bar,
比如1号启动了策略,到了2号凌晨2点多,策略停止,然后到了2号上午8点45策略重新启动,这个时候load_tick或者load_bar加载的是凌晨停盘前的数据吗?
我记得历史行情需要手动下载的,总不能每次停盘以后就要手动下载停盘之前的数据用于下次启动初始化吧? 所以很疑惑。

使用VeighNa Station创建了工作目录,并且在工作目录里创建了strategies文件夹,把自己的策略文件放里面
在VeighNa Station里能正常加载自己的策略,回测这些都没问题。
但是自己写了个no ui的run.py脚本放工作目录里面,就找不到这个策略类了。
难道no ui的方式不支持工作目录?
但奇怪的是,使用no ui的方式,日志却保存在工作目录里的.vntrader下的log文件夹里了,说明no ui的方式也是认工作目录的啊。

也就是说我的策略是同时基于tick和k线的,
回测的时候,tick数据和k线数据是互相保持同步的?还是各自一股脑推进来的?

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

沪公网安备 31011502017034号

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