大QMThandlebar下 isnewbar和islastbar函数不起效,实时情况下为什么每个tick都会触发
is_new_bar()) #历史k线每根都是新k线 盘中 每根新k线第一个分笔返回True 其他分笔返回False
官方是这么解释的,我的理解是 一分钟的第一个tick是新k线,触发new_bar,一分钟的最后一个tick,触发last_bar,不知道这样理解对不对?
实际情况是每个tick都会触发?!
问题描述
解决方案
您好!您遇到的情况在 QMT 平台中是完全正常的。这主要是因为对 QMT 的行情驱动机制以及这两个函数的具体定义存在一些理解上的偏差。下面为您详细梳理。
1. 为什么实时情况下每个 Tick 都会触发 handlebar?
根据 QMT 的底层运行机制,handlebar(ContextInfo) 是一个行情事件驱动函数:
- 历史回测阶段:模型会从第 0 根 K 线开始,逐根 K 线运行,每根 K 线调用一次
handlebar。 - 实时行情阶段(盘中):当历史 K 线运行完毕,进入最新的一根 K 线(即最后一根 K 线)时,只要有新的 Tick 数据推送过来,
handlebar就会被调用一次。
因此,在盘中实时运行中,handlebar 确实是每个 Tick 都会触发一次,这是为了让策略能够实时监控盘口变化,而不是等到 K 线走完才反应。
2. 纠正对 is_last_bar() 的理解
- 您的理解:一分钟的最后一个 tick 触发
last_bar。 - 官方真实含义:
is_last_bar()的意思是**“当前运行的这根 K 线,是否是图表上的最新一根(最后一根)K 线”**。- 在历史回测时,只有走到最后一天的最后一根 K 线,它才返回
True。 - 在盘中实时运行时,因为当前正在走的这根 K 线就是“最后一根 K 线”,所以在这根 K 线期间到来的每一个 Tick,
is_last_bar()都会返回True。 - 它无法用来判断当前 Tick 是否是这根 K 线的最后一个 Tick(因为未来还没发生,系统不知道下一个 Tick 是属于当前 K 线还是下一根 K 线)。
- 在历史回测时,只有走到最后一天的最后一根 K 线,它才返回
3. 纠正对 is_new_bar() 的理解
- 您的理解:一分钟的第一个 tick 是新 K 线,触发
new_bar。 - 官方真实含义:这个理解基本正确。当一根新的 K 线的第一个 Tick 数据到来时,
is_new_bar()会返回True。在这根 K 线后续到来的所有 Tick 中,它都会返回False。
4. 如何在代码中正确使用它们?
通常,我们在实盘策略中,为了避免在历史 K 线上重复发单,并且控制在盘中只在特定时机(如新 K 线产生时)执行逻辑,会这样组合使用:
场景 A:只在盘中实时运行,且每根 K 线只执行一次逻辑(K线刚形成时)
def handlebar(ContextInfo):
# 1. 确保当前是盘中最新的一根 K 线(过滤掉历史 K 线的计算)
if not ContextInfo.is_last_bar():
return
# 2. 确保当前是这根新 K 线的第一个 Tick
if ContextInfo.is_new_bar():
print(f"新 K 线产生了!当前时间:{ContextInfo.get_bar_timetag(ContextInfo.barpos)}")
# 在这里编写您的交易逻辑、指标计算等
# 这样一根 K 线只会执行一次
场景 B:盘中每个 Tick 都监控,但只在满足条件时下单
def handlebar(ContextInfo):
# 过滤历史 K 线
if not ContextInfo.is_last_bar():
return
# 获取最新 Tick 数据
tick_data = ContextInfo.get_full_tick([ContextInfo.stockcode])
if ContextInfo.stockcode in tick_data:
last_price = tick_data[ContextInfo.stockcode]['lastPrice']
# 每个 Tick 都会判断价格是否突破
if last_price > 10.00:
print("价格突破,执行下单!")
# 注意:这里需要配合全局变量控制,防止同一个 Tick 或同一根 K 线内重复下单
总结
handlebar盘中逐 Tick 触发是 QMT 的底层设计,为了保证实时性。is_last_bar()判断的是**“是否处于最新的一根 K 线”**,盘中始终为True。is_new_bar()判断的是**“是否是当前 K 线的第一个 Tick”**,每根 K 线只有一次为True。- 如果想实现“K线走完时下单”,QMT 默认的
passorder机制就是:在当前 K 线最后一个 Tick 信号成立时,在下一根 K 线的第一个 Tick 发出委托。如果您想在当前 K 线未走完就下单,需要设置passorder的quickTrade=1或quickTrade=2参数。