🚀 AI 一键生成 qmt 策略代码
立即体验

QMT 盘中避坑:如何过滤 handlebar 虚假信号并锁定最后一个 Tick?

qmt | 发布时间: 2026/8/5
以下内容由 EasyQuant 生成。

问题描述

QMT 盘中避坑:如何过滤 handlebar 虚假信号并锁定最后一个 Tick?
QMT 在盘中每个 Tick 都会触发 handlebar 产生虚假信号,如何写代码进行信号过滤?

解决方案

QMT 盘中避坑:如何过滤 handlebar 虚假信号并锁定最后一个 Tick?

在 QMT 平台中,默认的运行机制是行情驱动、逐 K 线运行。在盘中实时交易时,当前最新的一根 K 线(Bar)尚未走完,每一个 Tick 数据的推送都会触发一次 handlebar(ContextInfo) 函数。这会导致在 K 线形成过程中频繁出现“信号闪烁”或“虚假信号”。

本文将为您深度剖析 QMT 的盘中运行机制,并提供实用的代码过滤方案。


一、 为什么会产生虚假信号?

  1. Tick 驱动机制:盘中最后一根 K 线每变动一次,handlebar 就会被执行一次。如果您的策略逻辑直接在 handlebar 中判断价格并下单,那么在 K 线没走完时,价格上下波动就会反复触发下单信号。
  2. 有效信号的定义:只有当这根 K 线的最后一个 Tick 到来且 K 线确定(Close)时,产生的信号才是有效信号。QMT 默认会在下一根 K 线的第一个 Tick 发出下单任务。
  3. 临时更改不保存:在非最后一个 Tick 调用 handlebar 时,策略所做的变量更改不会被平台保存,也不会发送真实的交易信号。但如果您开启了 quickTrade=1(立即下单),虚假信号就会被立刻推送至柜台,造成误交易。

二、 核心过滤方案与代码实现

方案 1:利用 ContextInfo.is_last_bar() 与默认下单机制(最安全)

QMT 默认的 passorder 机制会自动在当前 K 线确定后(最后一个 Tick 判定通过),在下一根 K 线的第一个 Tick 发出信号。如果您不需要盘中抢跑,只需保持默认设置,并使用 is_last_bar() 限制计算范围:

#coding:gbk

def init(ContextInfo):
    ContextInfo.set_universe(['600000.SH'])

def handlebar(ContextInfo):
    # 仅在最后一根 K 线上进行盘中实时判断
    if not ContextInfo.is_last_bar():
        return
        
    # 获取最新行情
    close_prices = ContextInfo.get_history_data(1, '1d', 'close')
    stock = ContextInfo.get_universe()[0]
    
    # 策略逻辑判断
    if close_prices[stock][-1] > 10.0:
        # quickTrade 默认为 0,代表等待当前 Bar 走完(最后一个 Tick 确定)后,在下一根 Bar 的第一个 Tick 下单
        passorder(23, 1101, '您的资金账号', stock, 5, -1, 100, 'MyStrategy', 0, ContextInfo)

方案 2:使用 ContextInfo.is_new_bar() 锁定新 K 线开始(防止单根 Bar 重复触发)

如果您希望在**新一根 K 线刚生成(第一个 Tick 到来)**时只执行一次逻辑,可以使用 is_new_bar() 进行过滤:

#coding:gbk

def init(ContextInfo):
    ContextInfo.set_universe(['600000.SH'])

def handlebar(ContextInfo):
    # 判定是否为新 K 线的第一个 Tick
    if ContextInfo.is_new_bar():
        stock = ContextInfo.get_universe()[0]
        print(f"新 K 线生成,当前 Bar 索引: {ContextInfo.barpos},开始执行信号判定。")
        # 在此处编写只执行一次的逻辑

方案 3:盘中即时触发与 do_order() 配合

如果您运行在日 K 线周期,由于下一个 K 线要等到第二天,默认机制会导致当日无法下单。此时可以使用 do_order(ContextInfo) 函数,在盘中指定时间点,把上一根 K 线确定的有效信号立刻发送出去,避免 Tick 波动干扰:

#coding:gbk
import time

def init(ContextInfo):
    ContextInfo.set_account('您的资金账号')

def handlebar(ContextInfo):
    # 编写您的基础下单逻辑
    order_lots('600000.SH', 1, ContextInfo, '您的资金账号')
    
    # 获取当前最新 Tick 时间
    tick_timetag = ContextInfo.get_tick_timetag()
    int_time = int(timetag_to_datetime(tick_timetag, '%H%M%S'))
    
    # 在每天上午 10:00:00 到 10:00:05 之间,将上一根 K 线确定的信号立刻发出,且只发一次
    if 100000 <= int_time < 100005:
        do_order(ContextInfo)

三、 QMT 盘中避坑金律

  1. 慎用 quickTrade=1:该参数会使最后一根 K 线没有走完时也立即下单。除非您有极高频的盘中突破抢跑需求,否则请保持默认值 0
  2. 区分“运行”与“回测”:回测时是以 K 线收盘价撮合,不存在 Tick 抖动;而实盘/模拟运行是 Tick 驱动。在实盘上线前,务必在模拟盘中观察 handlebar 的触发频率。
  3. 合理设置“刷新间隔”:在新建模型的基本信息中,可以通过设置“刷新间隔”来限制策略运行频率,降低系统开销并减少虚假信号的判定次数。