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

vnpy在cta策略实盘时为什么不直接使用米矿的实时分钟数据,而是将交易所返回的tick数据合成分钟?

可能存在问题的代码块如下

        if self.last_dt and self.last_dt.minute != tick.datetime.minute:
            for bar in self.bars.values():
                bar.datetime = bar.datetime.replace(second=0, microsecond=0)

            self.on_bars(self.bars)
            self.bars = {}

        bar = self.bars.get(tick.vt_symbol, None)
        if not bar:
            bar = BarData(
                symbol=tick.symbol,
                exchange=tick.exchange,
                interval=Interval.MINUTE,
                datetime=tick.datetime,
                gateway_name=tick.gateway_name,
                open_price=tick.last_price,
                high_price=tick.last_price,
                low_price=tick.last_price,
                close_price=tick.last_price,
                open_interest=tick.open_interest
            )
            self.bars[bar.vt_symbol] = bar
        else:
            bar.high_price = max(bar.high_price, tick.last_price)
            bar.low_price = min(bar.low_price, tick.last_price)
            bar.close_price = tick.last_price
            bar.open_interest = tick.open_interest
            bar.datetime = tick.datetime

        last_tick = self.last_ticks.get(tick.vt_symbol, None)
        if last_tick:
            bar.volume += max(tick.volume - last_tick.volume, 0)
            bar.turnover += max(tick.turnover - last_tick.turnover, 0)

        self.last_ticks[tick.vt_symbol] = tick
        self.last_dt = tick.datetime

其中的基本逻辑为当tick的datetime标识中的minute改变时,就将已经缓存好的self.bars推出(不包含当前tick),并将self.bars清空,当前tick进入self.bars。
在这种逻辑下导致了如下问题,以下截图为实盘打印,使用品种SA209.CZCE、FG209.CZCE、MA209.CZCE

description

截图中开头为@NormTick的是在on_tick首行进行打印,开头为@minbar是在on_bars首行进行打印,可梳理出运行逻辑如下:

  1. 14:47:00的甲醇tick进入到on_tick之后被PortfolioBarGenerator.update_tick认为满足分钟已发生切换的条件(self.last_dt.minute != tick.datetime.minute,46变为47), 所以触发strategy.on_bars将缓存好所有品种的bars全部推出,所以看到了三条开头为@minbar的输出,此时PortfolioBarGenerator缓存的bars被清空并且放入了这条14:47:00的甲醇tick
  2. 下一时刻,14:46:59的纯碱tick进入到on_tick之后,update_tick再次认为满足分钟已发生切换的条件(self.last_dt.minute != tick.datetime.minute,47变为46),所以再次触发strategy.on_bars将缓存的bars(有且仅有14:47:00的甲醇tick)推出,所以看到了1条开头为@minbar的输出
  3. 下一时刻,14:47:00的玻璃tick进入on_tick,update_tick再次认为满足分钟已发生切换的条件(self.last_dt.minute != tick.datetime.minute,46变为47),所以再次触发strategy.on_bars将缓存的bars(有且仅有14:56:59的纯碱tick)推出,所以看到了1条开头为@minbar的输出

在论坛中找到解决类似问题的帖子:https://www.vnpy.com/forum/topic/7028-portfolio-strategy-zhong-on-tick-han-shu-zhong-geng-xin-bars-de-luo-ji-shi-cuo-wu-de-xiu-zheng-ban-de-luo-ji-ru-xia
基本思想为将 self.last_dt.minute != tick.datetime.minute 修改为 self.last_dt.minute < tick.datetime.minute,这样的确可以避免on_bars反复运行,但是在我的例子中会将14:46:59的纯碱tick包裹在14:47的min bar中,虽说数据仍然不准确,但好在没有很离谱(一个min bar实则只包含了一个tick)
目前正在思考更完善的解决方案

我在策略的开发过程中涉及到了不少修改vnpy官方代码的地方,但与此同时官方的代码也在不断迭代,这样的话后续我本地代码想要跟上官方升级会遇到比较多的兼容性问题,请问有什么好的管理代码方式吗

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

沪公网安备 31011502017034号

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