VeighNa量化社区
你的开源社区量化交易平台 | vn.py | vnpy
Member
avatar
加入于:
帖子: 15
声望: 0

在BarGenerator利用tick数据合成1分钟bar的uptick函数中,当tick如下时,9:30的bar无法取到第1个tick内产生的最低值4516.8,原因是第一次初始化self.bar的时候, “ low_price=tick.last_price,”( if new_minute:的源码中)。请确认下是否有这种情况,以及是否会有补丁
第1个tick:时间=2025-09-01 09:30:00.5, last_price=4518.8, low_price=4516.8
第2个tick:时间=2025-09-01 09:30:01, last价格=4519.0, low_price=4516.8
...
相关源码:
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
)

Member
avatar
加入于:
帖子: 5913
声望: 363

都是更新last_price,tick.low_price是一天的最低价,不影响的

Member
avatar
加入于:
帖子: 15
声望: 0

xiaohe wrote:

都是更新last_price,tick.low_price是一天的最低价,不影响的
假设第3个tick里的last_price=4518.4,是9:30这根bar里的最小last_price,
那么按目前程序会出现9:30 的self.bar.low_price=4518.4,但实际上self.bar.low_price=4516.8(出现在第一个tick的low_price里,但不反映在last_price里,当然也是一天的最低价)

Member
avatar
加入于:
帖子: 5913
声望: 363

下面self.bar.low_price = min(self.bar.low_price, tick.low_price)会更新的

Member
avatar
加入于:
帖子: 15
声望: 0

xiaohe wrote:

下面self.bar.low_price = min(self.bar.low_price, tick.low_price)会更新的

第1个tick:时间=2025-09-01 09:30:00.5, last_price=4518.8, low_price=4516.8
第2个tick:时间=2025-09-01 09:30:01, last_price=4519.0, low_price=4516.8
第3个tick:时间=2025-09-01 09:30:01.5, last_price=4518.4, low_price=4516.8
...
第120个tick: 时间=2025-09-01 09:30:59.5, last_price=4519.0, low_price=4516.8

当收到第1个tick后,self.bar.low_price=4518.8,
当收到第3个tick后,self.bar.low_price=4518.4,
因为只有 if self.last_tick and tick.low_price < self.last_tick.low_price:
才能 self.bar.low_price = min(self.bar.low_price, tick.low_price),
但这个条件是没法实现的,因为后续的 tick.low_price = self.last_tick.low_price,没能出现比前一个更低价的tick.low_price,所以第一个tick的 low_price没法采集到了。我在想是否可以改成这样:
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
)
if (self.last_tick and tick.high_price > self.last_tick.high_price) or (self.last_tick==None) :
self.bar.high_price = max(self.bar.high_price, tick.high_price)
if (self.last_tick and tick.low_price < self.last_tick.low_price) or (self.last_tick==None) :
self.bar.low_price = min(self.bar.low_price, tick.low_price)
elif self.bar:

Member
avatar
加入于:
帖子: 5913
声望: 363

bar.low_price记录的是一根K线里的low_price,当收到第一个tick的时候,K线里只有一个tick,不存在high和low,收到第二个tick的时候才能有比较。所以bg的写法是对的

Member
avatar
加入于:
帖子: 15
声望: 0

“bar.low_price记录的是一根K线里的low_price,当收到第一个tick的时候,K线里只有一个tick,不存在high和low”
当9:40的第一个tick,
第1个tick:时间=2025-09-01 09:40:00.5, last_price=4518.8, low_price=4516.8(同时也是本日最低值)
第2个tick:时间=2025-09-01 09:40:01, last_price=4519.0, low_price=4516.8
第3个tick:时间=2025-09-01 09:40:01.5, last_price=4518.4, low_price=4516.8

在第一个tick时,因为是新的分钟,会创建一个新的bar,其中low_price被设置为4518.8(tick.last_price),而不是4516.8(tick.low_price)。
然后在第二个tick时,会更新bar:
self.bar.low_price = min(self.bar.low_price, tick.last_price)
if self.last_tick and tick.low_price < self.last_tick.low_price:
self.bar.low_price = min(self.bar.low_price, tick.low_price)
这里会比较当前bar的low_price(4518.8)和tick.last_price(4519.0),取最小值4518.8。 然后检查self.last_tick(即第一个tick)和当前tick的low_price,第一个tick的low_price是4516.8,当前tick的low_price也是4516.8,所以不会更新。
最终9:40的bar的low_price是4518.8,而不是应该的4516.8。
建议修改方法:当新的一分钟开始时,
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
)
if (self.last_tick and tick.high_price > self.last_tick.high_price) or (self.last_tick==None) :
self.bar.high_price = max(self.bar.high_price, tick.high_price)
if (self.last_tick and tick.low_price < self.last_tick.low_price) or (self.last_tick==None) :
self.bar.low_price = min(self.bar.low_price, tick.low_price)
elif self.bar:

Member
avatar
加入于:
帖子: 15
声望: 0

if (self.last_tick and tick.low_price < self.last_tick.low_price)对应9:40:0.5 这种跨分钟的新的一分钟;
(self.last_tick==None) 对应9:30:0.2 这种全天的第一分钟(全天的第一个tick也可能last_price与low_price不一致),同时全天第一根tick的交易量没有初始化,因为不满足下述“if self.last_tick ”的条件
if self.last_tick and self.bar:
volume_change: float = tick.volume - self.last_tick.volume
self.bar.volume += max(volume_change, 0)

Member
avatar
加入于:
帖子: 5913
声望: 363

bar.low_price记录的是一根K线里的low_price不是当日的low_price
tick.low_price是当日的low_price,有更低的价格API会自行更新tick.low_price

Member
avatar
加入于:
帖子: 15
声望: 0

xiaohe wrote:

bar.low_price记录的是一根K线里的low_price不是当日的low_price
tick.low_price是当日的low_price,有更低的价格API会自行更新tick.low_price

你说的完全正确,问题就出在当一根bar线的第一个tick里出现了当天的最低tick.low_price,这根bar线取不到这个tick.low_price,因为初始化self.bar的时候取的是last_price,后续第二个tick因为不满足self.last_tick and tick.low_price < self.last_tick.low_price,也无法更新self.bar.low_price
如图所示IF2509.CFFEX 2025-08-04 9:30分的bar线 代码运行后,最低价是4018.6,实际上应该是4017.4

description

Member
avatar
加入于:
帖子: 15
声望: 0

更新部分代码:

        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
            )
            '''
            修正新的bar线当第一个tick出现当日最高价、最低价时,原有算法取不到该值的问题,同步更新初始成交量
            '''
            if (self.last_tick and tick.high_price > self.last_tick.high_price) or (self.last_tick == None):
                self.bar.high_price = max(self.bar.high_price, tick.high_price)
            if (self.last_tick and tick.low_price < self.last_tick.low_price) or (self.last_tick == None):
                self.bar.low_price = min(self.bar.low_price, tick.low_price)

            if (self.last_tick == None):
                self.bar.volume = max(tick.volume, 0)
                self.bar.turnover = max(tick.volume, 0)
Member
avatar
加入于:
帖子: 5913
声望: 363

收到,感谢反馈。我们下个版本会更新,方便的话也可以去github发个PR

Member
avatar
加入于:
帖子: 15
声望: 0

xiaohe wrote:

收到,感谢反馈。我们下个版本会更新,方便的话也可以去github发个PR
好哒

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

沪公网安备 31011502017034号

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