🚀 AI 一键生成 qmt 策略代码

为什么 QMT 订阅 1 分钟 K 线数据,回调函数会每秒执行一次?

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

问题描述

contextinfo.subscribe_quote()的1分钟k线数据回调函数,调用时怎么会是间隔1秒调用

#encoding:gbk
def call_back(data):
# 打印回调数据,验证是否执行
print("收到K线数据:")
print(data)
print("+++++++")

def init(ContextInfo):
# 显式指定参数名,确保回调函数正确绑定(国信API必须)
sub_id = ContextInfo.subscribe_quote("SM601.ZF","1m",callback=call_back)
# 打印订阅ID,验证是否订阅成功(-1表示失败)
print(f"订阅ID:{sub_id},若为-1请检查品种代码或权限")

# 国信平台主循环函数应为handle_data,而非handlebar(名称错误会影响监控)
def handle_data(ContextInfo):
print("============================")

解决方案

在 QMT 平台中,使用 ContextInfo.subscribe_quote() 订阅 1 分钟 K 线数据时,回调函数之所以会每隔 1 秒(甚至更短时间)被调用一次,是因为 QMT 的底层行情驱动机制是基于 Tick(分笔)数据的

为什么会频繁回调?

  1. Tick 驱动 K 线更新:即使你订阅的是 1m(1分钟)周期的 K 线,这根 1 分钟的 K 线在盘中是动态生成的。每当交易所推送一个新的 Tick 数据(期货通常是每秒 2 笔,即 500ms 一笔),当前这根 1 分钟 K 线的最新价、最高价、最低价、成交量等字段就会发生更新。
  2. 数据更新即触发回调subscribe_quote 的设计初衷是“在某只代码行情更新后立即执行”。因此,只要底层有新的 Tick 到来导致这根 1 分钟 K 线的数据发生了变化,回调函数 call_back 就会被触发。这就是为什么你会看到它每秒都在打印数据,而不是每 1 分钟打印一次。

解决方案:如何只在 1 分钟 K 线走完时执行逻辑?

如果你希望只在 1 分钟 K 线真正结束(或新 K 线产生)时才执行特定的交易逻辑,可以通过以下几种方式处理:

方法一:在回调函数中记录并判断时间戳

你可以记录上一次处理的 K 线时间戳,只有当时间戳发生变化(即进入了下一根 K 线)时,才执行你的核心逻辑。

#encoding:gbk
last_bar_time = ""

def call_back(data):
    global last_bar_time
    # data 是一个字典,格式如 {'SM601.ZF': DataFrame}
    for code, df in data.items():
        if df.empty:
            continue
        # 获取最新一根 K 线的时间戳(通常是 DataFrame 的 index 的最后一个)
        current_time = df.index[-1]
        
        # 如果时间戳与上次记录的不同,说明产生了一根新的 K 线
        if current_time != last_bar_time:
            print(f"【新K线产生】时间:{current_time},收盘价:{df['close'].iloc[-1]}")
            last_bar_time = current_time
            # 在这里执行你的 1 分钟级别逻辑

def init(ContextInfo):
    sub_id = ContextInfo.subscribe_quote("SM601.ZF", "1m", callback=call_back)
    print(f"订阅ID:{sub_id}")

def handlebar(ContextInfo):
    pass

方法二:使用主图驱动和 is_new_bar()

如果你不需要监控大量不在主图上的股票,最标准的 QMT 做法是将主图周期设置为 1 分钟,然后在 handlebar 中使用 ContextInfo.is_new_bar() 或判断 ContextInfo.is_last_bar()

#encoding:gbk
def init(ContextInfo):
    pass

def handlebar(ContextInfo):
    # 确保在实盘/模拟的最新一根 K 线上运行
    if not ContextInfo.is_last_bar():
        return
        
    # 当这根 1 分钟 K 线的第一个 tick 到来时,判定为新的 K 线
    if ContextInfo.is_new_bar():
        print("1分钟K线走完,新K线开始,执行逻辑")
        # 获取上一根走完的 K 线数据
        # df = ContextInfo.get_market_data_ex(...)

代码修正提示

在你提供的代码中,主循环函数被命名为 handle_data在 QMT 平台中,Python 策略的核心执行函数必须命名为 handlebar,否则策略将无法随行情驱动正常运行(handle_data 是其他量化平台如聚宽的命名习惯)。

正确的结构必须包含:

def init(ContextInfo):
    pass

def handlebar(ContextInfo):
    pass