Files
qmt_bridge/reference/xtquant_big_convert/docs/ZMQ_BACKTEST_BRIDGE.md
T

5.1 KiB
Raw Blame History

QMT 原生 ZMQ 回测桥接

1. 目标和边界

正式模式是在 QMT 回测进程内部运行一个 ZMQ 服务,把 QMT 当前回测 Bar、 账户、持仓、委托和成交桥接给外部策略。QMT 是唯一的行情推进器、回测引擎、 账户系统和撮合器。

BIGQMT_ZMQ_BACKTEST.py 与现有实盘 RPC 入口完全分离:

  • 不导入或修改 bigqmt_signal_trader
  • 使用独立端口 tcp://127.0.0.1:16662
  • 只允许 ContextInfo.do_back_test=true 的 QMT 回测上下文;
  • 协议固定返回 live_ready=false
  • ZMQ 后台线程只接收请求和排队,不直接调用 QMT API;
  • passorder、撤单和账户查询只在 QMT handlebar 回调线程执行。

项目仍保留端口 16661 的 CSV 独立回测工具,用于脱离 QMT 的协议测试。该工具 使用本地 BacktestEngine/SimulatedBroker,不是 QMT 原生回测服务,二者不能混用。

2. 运行时序

  1. QMT 加载 BIGQMT_ZMQ_BACKTEST.py 并调用 init(ContextInfo)
  2. 入口确认当前是 QMT 回测模式,绑定 QMT 注入的 passordercancelget_trade_detail_data,然后启动 ZMQ 服务。
  3. QMT 调用 handlebar 时,服务发布当前 Bar,并等待外部策略完成这一 Bar 的决策。
  4. 外部策略调用 submit_ordercancel_order;ZMQ 线程只把命令放入当前 Bar 队列。
  5. 外部策略调用 next_bar 后,QMT 回调线程排空命令并调用 QMT API,然后把控制权 交还 QMT。QMT 自己撮合并推进下一根 Bar。
  6. QMT 的 order_callbackdeal_callback 以及账户查询结果会进入 ZMQ 状态; QMT 调用 stop/after_backtest 后,下一次 next_bar 返回 done=true

外部策略超时不释放当前 Bar 时,桥接会抛出超时错误并停止继续下单,避免 QMT 静默跑完整段历史而外部策略没有参与。

3. QMT 端安装与配置

同步以下内容到正在运行的 QMT python 目录:

src/bigqmt_backtest/
src/BIGQMT_ZMQ_BACKTEST.py

编辑 BIGQMT_ZMQ_BACKTEST.py 顶部配置:

BACKTEST_ZMQ_CONFIG = {
    "bind_endpoint": "tcp://127.0.0.1:16662",
    "run_id": "",                    # 空值会按启动时间生成
    "account_id": "你的QMT回测账号",
    "account_type": "STOCK",
    "strategy_name": "ZMQ_BACKTEST",
    "combo_type": 1101,
    "quick_trade": 2,
    "market_price_type": 5,
    "limit_price_type": 11,
    "bar_wait_timeout_seconds": 60,
    "require_qmt_backtest": True,
}

入口是 GBK/ASCIIbigqmt_backtest 包使用 UTF-8。在 QMT 中创建回测任务并且只加载 BIGQMT_ZMQ_BACKTEST.py,不要使用“启动本地 Python”。启动日志会打印实际 run_id、端口和账号。

account_id 必须填写,服务会调用 ContextInfo.set_account(account_id),外部订单最终 通过以下 QMT 原生接口提交:

passorder(23/24, 1101, account_id, symbol, price_type, price, quantity,
          strategy_name, quick_trade, client_order_id, ContextInfo)

撮合价格、成交时间、手续费、资金和持仓均以 QMT 回测结果为准,桥接不再计算第二套 结果。

4. 外部策略启动

安装客户端包:

python -m pip install -e .

启动 QMT 回测后,在外部 Python 运行:

python examples/zmq_backtest_strategy.py `
  --endpoint tcp://127.0.0.1:16662 `
  --symbol 600000.SH `
  --fast 5 `
  --slow 20

没有传 --run-id 时,客户端先调用 describe 发现 QMT 本次运行的 run_id。同一运行 只允许首个调用 startclient_id 控制。

5. 协议

ZMQ 使用 REQ/REP,请求包含:

{
  "schema_version": 1,
  "request_id": "唯一幂等键",
  "run_id": "qmt-native-20260719-120000",
  "client_id": "strategy-a",
  "method": "start",
  "params": {}
}
方法 QMT 原生模式含义
ping / describe 探活、发现 run_id 和确认 engine_owner=QMT
start 外部策略挂接并等待 QMT 第一根 Bar;不启动第二个引擎
submit_order 把订单意图排入当前 Bar,返回 QUEUED
cancel_order 把撤单意图排入当前 Bar
next_bar 释放当前 Bar;QMT 线程执行命令并等待 QMT 下一根 Bar
state 返回 QMT 缓存的资金、持仓和当前 Bar
history 返回 QMT 已经发布给外部策略的历史 Bar,不泄露未来数据
orders / fills 返回 QMT 委托/成交查询及回调归一化结果
finish 外部策略解除挂接;QMT 回测报告仍由 QMT 生成

响应包含 execution_backend=QMT_NATIVEexecution_mode=QMT_BACKTESTlive_ready=false。相同 request_id 的重试返回缓存响应。

6. CSV 独立模式

仅当不启动 QMT、需要验证协议或外部策略逻辑时使用:

python -m bigqmt_backtest.server `
  --data examples/backtest_bars.example.csv `
  --config examples/backtest_config.example.json `
  --run-id demo-001 `
  --bind tcp://127.0.0.1:16661

该模式响应 execution_backend=LOCAL_SIM,本地产出 result.json、委托、成交、资金 曲线等证据。它不会调用 QMT,也不能代表 QMT 原生撮合结果。