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

QMT 平台获取 Level2 逐笔数据下午 13:00 后掉包怎么办?

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

问题描述

关于level2行情问题

有朋友试过在获取 level2 的逐笔委托跟逐笔成交的时候在下午 13:00 打后出现数据掉包的现象吗?就是早上都是好的,但是下午特别明显,最近出现的频率增加

解决方案

在 QMT 平台中获取 Level2 逐笔委托和逐笔成交数据时,下午 13:00 之后出现数据掉包(丢失)是一个相对常见的现象。这通常与数据洪峰、本地处理瓶颈以及网络环境有关。以下是详细的原因分析及相应的解决方案:

一、 为什么下午 13:00 容易出现数据掉包?

  1. 下午开盘的数据洪峰:中午休盘期间,市场积累了大量的委托单。13:00 开盘瞬间,这些委托单和随之产生的成交会形成一个巨大的数据洪峰。如果本地接收端处理不过来,底层缓冲区溢出,就会导致掉包。
  2. 回调函数阻塞(最常见原因):在使用 ContextInfo.subscribe_quote 订阅 Level2 数据时,如果您的 callback 回调函数中包含了耗时操作(如复杂的指标计算、频繁的本地文件读写、同步的数据库插入或同步下单),会导致主推线程被阻塞,后续到达的 Tick 数据无法及时处理而被丢弃。
  3. 网络带宽与延迟:Level2 逐笔数据量非常大,如果您的运行环境(如本地电脑或普通云服务器)网络带宽不足或存在波动,极易在数据高峰期发生丢包。
  4. 内存与 CPU 资源耗尽:随着早盘数据的积累,如果策略中存在内存泄漏或未及时清理历史数据,下午运行时系统资源紧张,处理速度下降。

二、 解决方案与代码优化建议

1. 极速轻量化回调函数(核心优化)

确保 subscribe_quote 的回调函数尽可能轻量。绝对不要在回调函数中进行耗时的 I/O 操作或复杂计算。建议将接收到的数据推入内存队列(如 Python 的 queue.Queue),由另一个独立的后台线程专门负责处理数据。

import queue
import threading

# 初始化一个全局队列
data_queue = queue.Queue()

def process_data_thread():
    while True:
        try:
            # 从队列获取数据进行异步处理
            datas = data_queue.get(timeout=1)
            # 在这里进行复杂的计算或入库操作
            # process(datas)
        except queue.Empty:
            continue

# 启动后台处理线程
t = threading.Thread(target=process_data_thread, daemon=True)
t.start()

def on_quote(datas):
    # 回调函数只做一件事:把数据塞进队列,立即返回
    data_queue.put(datas)

def init(ContextInfo):
    # 订阅 Level2 数据
    ContextInfo.subscribe_quote('000300.SH', 'tick', 'none', on_quote)

2. 减少不必要的订阅

Level2 数据量庞大,请检查是否订阅了过多不必要的标的。尽量只订阅策略真正需要的股票池,避免全市场订阅。

3. 结合定时拉取作为容错机制

如果逐笔主推数据偶尔掉包,可以在 handlebar 中结合 ContextInfo.get_market_data_ex 定时拉取最新的快照数据进行状态校对,防止策略因为个别 Tick 丢失而产生严重逻辑错误。

4. 升级硬件与网络环境

  • 网络:尽量将策略部署在靠近券商机房的云服务器上,确保网络带宽充足且延迟低。
  • 硬件:监控下午 13:00 时的 CPU 和内存占用率,必要时升级服务器配置。

5. 联系券商排查

如果排除了本地代码和网络问题,且掉包频率近期突然增加,可能是券商服务端的 Level2 推送网关在高峰期存在压力。建议联系开户券商的 IT 支持人员,反馈该现象,确认是否为服务端限流或网关拥堵所致。