VeighNa量化社区
你的开源社区量化交易平台
Member
avatar
加入于:
帖子: 26
声望: 1

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

        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)
目前正在思考更完善的解决方案

Member
avatar
加入于:
帖子: 716
声望: 55

感觉是14:47:00这根甲醇出了问题,14:46:59.035498和14:47:00的时间不对,上一根甲醇也出了这个问题,秒数不对。

Member
avatar
加入于:
帖子: 26
声望: 1

郭易燔 wrote:

感觉是14:47:00这根甲醇出了问题,14:46:59.035498和14:47:00的时间不对,上一根甲醇也出了这个问题,秒数不对。

针对Normtick的那个甲醇信息,14:46:59.035498是我这条日志的打印时间,14:47:00+08:00是这条tick数据所携带的datetime,那请问为何会导致这种情况呢,如果是因为我的服务器时间和交易所未校准,也算是正常吧?

根本问题不是多品种下tick的datetime在两分钟之间会反复横跳吗?单品种肯定不存在该问题,因为是严格时间序列的

© 2015-2022 上海韦纳软件科技有限公司
备案服务号:沪ICP备18006526号

沪公网安备 31011502017034号

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