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

BarGenerator通过tick时时行情在合成数据时发现一个问题,如下图:
description

就是在跨交易时间段,比如上午11:30跟下午13:30衔接时段会出现上午11:30的k到下午才推出来,但是仔细看这跟k,其实只有1根tick数据,而上午11:59:59.500000时间推送出去的11:59的bar其实就差1根tick,深究代码:

def update_tick(self, tick: TickData) -> None:
        """
        Update new tick data into generator.
        """
        new_minute = False

        # Filter tick data with 0 last price
        if not tick.last_price:
            return

        # Filter tick data with older timestamp
        if self.last_tick and tick.datetime < self.last_tick.datetime:
            return

        if not self.bar:
            new_minute = True
        elif (
            (self.bar.datetime.minute != tick.datetime.minute)
            or (self.bar.datetime.hour != tick.datetime.hour)
        ):
            self.bar.datetime = self.bar.datetime.replace(
                second=0, microsecond=0
            )
            self.on_bar(self.bar)

            new_minute = True

        if new_minute:
            self.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
            )
        else:
            self.bar.high_price = max(self.bar.high_price, tick.last_price)
            if tick.high_price > self.last_tick.high_price:
                self.bar.high_price = max(self.bar.high_price, tick.high_price)

            self.bar.low_price = min(self.bar.low_price, tick.last_price)
            if tick.low_price < self.last_tick.low_price:
                self.bar.low_price = min(self.bar.low_price, tick.low_price)

            self.bar.close_price = tick.last_price
            self.bar.open_interest = tick.open_interest
            self.bar.datetime = tick.datetime

        if self.last_tick:
            volume_change = tick.volume - self.last_tick.volume
            self.bar.volume += max(volume_change, 0)

            turnover_change = tick.turnover - self.last_tick.turnover
            self.bar.turnover += max(turnover_change, 0)

        self.last_tick = tick

发现在运行 self.on_bar(self.bar) 时并没有把从59秒变成00秒的那根tick数据加进去,实际只推送出去59.500000秒的数据,在常规时段因为不会出现如11:30:00至14:30:00这种秒级别的0跟0的衔接,所以数据不会有异常,当跨时段时就出现该问题,此时会导致衔接时段收到的如1分钟k线只有1根tick的数据,从而影响如均线的计算的准确性。

解决方案:

def update_tick(self, tick: TickData) -> None:
        """
        Update new tick data into generator.
        """
        # Filter tick data with 0 last price
        if not tick.last_price:
            return

        # Filter tick data with older timestamp
        if self.last_tick and tick.datetime < self.last_tick.datetime:
            return

        if self.bar:
            self.bar.high_price = max(self.bar.high_price, tick.last_price)
            if tick.high_price > self.last_tick.high_price:
                self.bar.high_price = max(self.bar.high_price, tick.high_price)

            self.bar.low_price = min(self.bar.low_price, tick.last_price)
            if tick.low_price < self.last_tick.low_price:
                self.bar.low_price = min(self.bar.low_price, tick.low_price)

            self.bar.close_price = tick.last_price
            self.bar.open_interest = tick.open_interest
            self.bar.datetime = tick.datetime

        else:
            self.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
            )

        if self.last_tick:
            volume_change = tick.volume - self.last_tick.volume
            self.bar.volume += max(volume_change, 0)

            turnover_change = tick.turnover - self.last_tick.turnover
            self.bar.turnover += max(turnover_change, 0)

        if self.last_tick and not (tick.datetime.replace(microsecond=0).second == 0 and self.last_tick.datetime.replace(microsecond=0).second == 0):
            if self.last_tick and (
                (self.last_tick.datetime.minute != tick.datetime.minute)
                or (self.last_tick.datetime.hour != tick.datetime.hour)
            ):
                self.bar.datetime = self.bar.datetime.replace(
                    second=0, microsecond=0
                )
                self.on_bar(self.bar)
                self.bar = None
       self.last_tick = tick

结果如下:
description

Administrator
avatar
加入于:
帖子: 4500
声望: 320

感谢分享!精华送上

这里主要是因为vn.py自带的BarGenerator更多为了通用性设计(兼容国内外所有市场),所以确实对于时间段结束的瞬时TICK没有特别好的处理,大家需要的话可以自己在策略代码中继承实现自己的BarGenerator。

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

沪公网安备 31011502017034号

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