3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在QMT平台中,行情驱动是其核心运行机制。当策略在盘中实时运行时,当前K线(最后一根Bar)每变动一次(即每一个新的Tick数据到来),handlebar(ContextInfo) 函数就会被调用一次。这会导致一个经典痛点:盘中临时成立的信号(虚假信号/闪烁信号)频繁触发,而只有K线结束时的最后一个Tick才是最终的有效信号。
本文将为您深度拆解QMT的信号触发机制,并提供切实可行的代码解决方案,帮助您在实盘中完美过滤虚假信号。
在盘中,最后一根K线尚未走完时,价格会随着Tick不断波动:
如果直接在每个Tick触发时立即下单,就会产生大量的虚假信号交易(俗称“信号闪烁”)。只有当这根K线的最后一个Tick到来、K线完全确定时,产生的信号才是唯一有效的信号。
QMT默认的交易函数运行机制是:在当前K线的最后一个Tick判定信号是否成立,若成立,则在下一根K线的第一个Tick发出下单信号。
如果您希望严格在K线走完后交易,可以结合 ContextInfo.is_new_bar() 来控制逻辑,确保只在新K线生成的第一时间处理上一根K线的信号。
#coding:gbk
def init(ContextInfo):
ContextInfo.set_universe(['600000.SH'])
def handlebar(ContextInfo):
# 仅在新K线的第一个Tick到来时执行核心逻辑
if not ContextInfo.is_new_bar():
return
# 此时上一根K线已经完全确定,获取的数据是绝对真实的,无闪烁风险
# 获取历史收盘价(不包含当前未走完的Bar)
close_data = ContextInfo.get_history_data(2, '1d', 'close')
# 执行您的策略信号判定与下单逻辑...
在 handlebar 中,我们可以通过 ContextInfo.is_last_bar() 限制只在最新的实时Bar上进行Tick级别的判定,同时配合时间戳或 is_new_bar 锁定交易时机。
#coding:gbk
def init(ContextInfo):
ContextInfo.set_universe(['600000.SH'])
def handlebar(ContextInfo):
# 过滤历史Bar,加快计算速度,只在最后一根K线(最新Bar)处理逻辑
if not ContextInfo.is_last_bar():
return
# 结合您的选价与下单逻辑
# 注意:若未开启 quickTrade=1,默认passorder会在下一根K线首个Tick发送委托
如果您不想等到下一根K线,而是希望在当前K线判定成立时立即下单,可以使用 passorder 中的 quickTrade 参数:
quickTrade=1:立即下单。当最后一根K线没有走完时,一旦信号成立立刻发出下单信号。(注意:此模式下需要自行在代码中做变量控制,防止同一个Bar内重复下单)。# 示例:使用 quickTrade=1 立即触发,但通过自定义变量限制每个Bar只投单一次
def init(ContextInfo):
ContextInfo.last_order_bar = -1
def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
return
current_bar = ContextInfo.barpos
# 确保每个Bar只交易一次,防止Tick级别重复下单
if current_bar > ContextInfo.last_order_bar:
# 策略买入信号判定成立
signal_buy = True
if signal_buy:
# quickTrade=1 立即下单,不等待下一根K线
passorder(23, 1101, '您的资金账号', '600000.SH', 5, -1, 100, 'MyStrategy', 1, ContextInfo)
ContextInfo.last_order_bar = current_bar
is_new_bar():这是过滤盘中Tick噪点、锁定K线交替时机的最强利器。quickTrade=1 或 do_order(),必须在 ContextInfo 中记录当前 barpos,防止同一个K线周期内因Tick波动被反复触发下单,导致超单或资金透支。