# xtquant_big_convert 实现原理调研(基于协议线索 + 官方API还原) 调研日期:2026-08-19 仓库:https://github.com/litaolemo/xtquant_big_convert ⚠️ 注意:本机出网受限(GitHub/镜像/Bing/Baidu 全部不通),无法抓取真实源码。 本文基于方案文档中的协议线索 + 迅投官方API文档(已核实)还原实现原理。 协议线索:请求 RPUSH bigqmt:rpc:queue:{账号} / 响应 BLPOP bigqmt:rpc:respq:{账号}:{reqId} --- ## 一、它解决什么问题 **目标**:让外部 Python 程序(没有 MiniQMT/XtQuantServer 权限)直接调用"大QMT"的交易和行情能力。 **背景约束**(官方文档核实): - xtquant 外部库的 XtQuantTrader / xtdata **本质是和 MiniQMT 建立连接**(官方原文) - 大QMT(完整交易端)不提供 MiniQMT 的 userdata_mini 连接通道 → 外部 xtquant 直连大QMT 失败 - 但大QMT 的策略编辑器(内置 Python 3.6)能跑策略,能调 passorder / get_trade_detail_data **解法**:把"桥"跑在大QMT 进程内(策略里),外部程序通过 Redis 发 RPC 请求,桥在 QMT 策略线程里执行并回写结果。 --- ## 二、核心架构 ``` ┌─ 外部Python进程(无QMT权限) ─┐ ┌─ Redis ─┐ ┌─ 大QMT进程内(策略) ─┐ │ 你的量化脚本 / sfgrid(TS) │ │ │ │ qmt_big_convert.py │ │ │ ①RPUSH │ │ ②BLPOP │ │ │ redis_client.rpush( ├───────►│ queue ├───────►│ bridge_loop(): │ │ 'bigqmt:rpc:queue:{acct}',│ │ {acct} │ │ 解析请求 │ │ json.dumps(req)) │ │ │ │ passorder(...) │ │ │ │ │ │ get_trade_detail │ │ ⑤BLPOP(respq) ←─────────────┼────────┤ respq │◄───────┤ ④RPUSH 结果 │ │ reqId → 结果 │ │ {acct}: │ │ │ └──────────────────────────────┘ │ {reqId} │ └──────────────────────┘ └─────────┘ ``` **关键**:Redis 是"队列桥接"的中枢,不是 HTTP server。这正好绕开官方"QMT 内置 Python 不能多线程"的约束——QMT 侧不需要开监听线程,用一个循环/定时器消费队列即可。 --- ## 三、Redis 协议设计(从 key 命名还原) ### 3.1 请求通道 ``` Key: bigqmt:rpc:queue:{accountID} Type: LIST 操作: 外部进程 RPUSH, QMT桥 BLPOP Value: JSON 请求体 ``` ### 3.2 响应通道 ``` Key: bigqmt:rpc:respq:{accountID}:{reqId} Type: LIST 操作: QMT桥 RPUSH, 外部进程 BLPOP(带超时) Value: JSON 响应体 ``` ### 3.3 推断的请求/响应结构(基于常见 RPC 桥设计 + 协议命名) ```jsonc // 请求(外部 → QMT) { "reqId": "uuid或自增id", // 用于关联响应队列 "method": "order | cancel | query_position | query_asset | kline | ...", "params": { // order: {"code":"000001.SZ","opType":23,"volume":100,"priceType":5,"price":-1,...} // kline: {"code":"600000.SH","period":"1d","count":100} } } // 响应(QMT → 外部) { "reqId": "同上", "code": 0, // 0成功, 非0错误 "data": {...} | [...], // 查询结果 / 下单结果 "msg": "error message" } ``` --- ## 四、QMT 侧桥程序的关键实现 ### 4.1 入口:策略生命周期 ```python #coding:gbk import json, redis # 或自实现极简RESP客户端 def init(ContextInfo): ContextInfo.run_time("bridge", "200nMilliSecond", "2019-01-01 00:00:00") # 或: # 起一个 while 循环线程(若实测线程可用) def bridge(ContextInfo): # 定时/循环:BLPOP 队列 req = redis_client.blpop('bigqmt:rpc:queue:%s' % ACCOUNT, timeout=0.1) if req: result = dispatch(req) # 在策略上下文执行 redis_client.rpush('bigqmt:rpc:respq:%s:%s' % (ACCOUNT, req['reqId']), json.dumps(result)) def dispatch(req): method = req['method'] if method == 'order': return passorder(req['params']) # 必须传 ContextInfo elif method == 'cancel': return cancel(...) elif method == 'query': return get_trade_detail_data(...) elif method == 'kline': return ContextInfo.get_market_data_ex(...) ``` ### 4.2 必须处理的点(官方文档核实) 1. **passorder 无返回** → 下单结果要 order_callback/deal_callback 或轮询委托回写 2. **回调仅实盘模式 + 需 set_account** → init 里 `ContextInfo.set_account(account)` 3. **状态不能挂 ContextInfo**(会回滚) → 用模块级全局 class 4. **行情函数**:内置 Python 用 `ContextInfo.get_market_data_ex`(不能直接在 init 跑) 5. **定时器用 run_time**(官方无 adjust) --- ## 五、为什么它和你的 HTTP 桥方案是"同构"的 | 维度 | xtquant_big_convert | 你的 qmt_http_bridge 方案 | |------|--------------------|--------------------------| | 桥的位置 | 大QMT 策略内 | 大QMT 策略内 | | 外部入口 | Redis LIST(RPUSH/BLPOP) | HTTP server | | 队列桥接 | Redis 队列 | 内存 ORDER_QUEUE | | 结果回写 | Redis respq + reqId | ORDER_RESULTS[rid] | | QMT 侧执行 | 策略线程(定时消费) | adjust() 定时消费 | | 解决的问题 | 外部无 xtquant 权限 | 外部脚本零改动复用8610 | **本质相同**:都是"大QMT 进程内桥 + 队列 + 策略线程执行 + 结果回写"。 --- ## 六、Redis vs HTTP 的取舍(你的方案该参考什么) ### xtquant_big_convert 用 Redis 的动机(推断) - 官方"不能多线程"→ 无法开 HTTP server 线程 - Redis BLPOP 天然适配单线程轮询:一个 run_time 定时器就能消费 - 外部 redis-py 客户端成熟,不碰 QMT ### 但它引入的问题 1. **需要 Redis 服务** → 多一个运维组件(虽然轻量) 2. **QMT 内置 Python 3.6 是否有 redis 库?** → 大概率没有,要自己实现极简 RESP 客户端(纯 socket,~100行) 3. **BLPOP 阻塞语义** → 若桥循环里阻塞,会卡住策略主线程,需要 timeout 参数 ### 对你 HTTP 桥方案的启示 - 如果实测 QMT 里**线程可用** → HTTP 方案可行,但必须加请求超时保护(慢客户端卡死策略) - 如果**线程不可用** → 你的 HTTP 方案需要改成"单线程事件循环",或者借鉴 Redis 思路:QMT 侧只做定时轮询,HTTP 监听放外部进程(方向B) --- ## 七、待验证项(拿到真实源码后核对) - [ ] 桥是否用 redis-py 还是自写 RESP 客户端 - [ ] 请求/响应 JSON 的确切字段名 - [ ] 下单结果如何回写(回调 or 轮询) - [ ] 是否处理了 order_callback / deal_callback - [ ] 定时器用的 run_time 还是线程 - [ ] 是否支持行情(kline)还是只做交易 - [ ] 是否内置了 token/鉴权