# QMT Bridge 接口清单 & sfgrid 满足度对照 > 更新日期: 2026-08-26 > 适用范围: `qmt_bridge`(大 QMT 内策略桥,端口 8610) > 对照对象: `C:\Users\Docker\Development\sfgrid`(网格策略客户端,当前走 miniQMT xtquant SDK 直连) > 接口规范权威来源: `docs/api_spec/openapi.yaml`(主动维护,可同步 Apifox) --- ## 〇、背景与结论速览 - **sfgrid 当前接入方式**: `core/qmt_real.py` 直接封装 `xtquant` SDK(`XtQuantTrader` + `xtdata`),**不是** HTTP 桥。 - **目标**: 让 sfgrid 可以改走 qmt_bridge(或桥为其提供等价能力)。 - **一句话结论**: 桥的**查询类接口已满足** sfgrid 的持仓/资金/委托/成交/行情/涨跌停价/全量tick需求;**交易闭环(下单、撤单、异步回报推送)尚未实现**,是 sfgrid 迁移的主要缺口。 --- ## 一、当前桥已实现接口(✅ 12 个) ### 1.1 通用 #### GET /health —— 健康检查 - **功能**: 检查桥是否存活,返回运行模式、端口、当前资金账号、桥版本。 - **返回**: ```json { "status": "ok", "connect_info": {"mode": "big_qmt", "http_port": 8610, "ws_port": 8610, "account": "8882874667"}, "last_error": null, "bridge_version": "2", "hot_reload": true } ``` ### 1.2 data 命名空间(行情/数据) #### GET /data/kline —— K线查询 - **功能**: 查询历史/实时 K 线,支持周期合成,按字段筛选。**查询前自动先下载基础周期数据**。 - **参数** (Query): | 参数 | 类型 | 默认 | 说明 | |------|------|------|------| | code | str | 必填 | 股票代码,`600519.SH` 或 `600519` | | period | str | `1d` | `tick/1m/5m/15m/30m/60m/1h/1d/1w/1mon` | | start | str | `""` | 起始 `YYYYMMDD` | | end | str | `""` | 结束 `YYYYMMDD` | | count | int | `-1` | 条数,`-1`=全部;与 start/end 互斥 | | fields | str | `open,high,low,close,volume,amount` | 逗号分隔,**不传=返回完整 OHLCV**;传了则只返回指定字段(白名单: `open,high,low,close,volume,amount,settle,openInterest`) | - **返回**(实测 2026-08-21, 600900.SH): ```json { "code": "600900.SH", "period": "1d", "count": 14, "data": [{"time": "20260803", "open": 28.99, "high": 29.2, "low": 28.75, "close": 29.05, "volume": 1018010.0, "amount": 2949045835.0}, ...] } ``` - **底层**: 先 `download_history_data`(合成周期自动下载基础周期: 3m←1m, 15m/30m/60m←5m, 1w/1mon←1d),再 `ContextInfo.get_market_data_ex`。 - **fields 行为**(实测): 不传→完整 OHLCV;`fields=close`→只 close;`fields=open,high`→只 open/high。 #### GET /data/quote —— 实时行情快照(单票) - **功能**: 查询指定股票的**完整实时快照**(最新价、开高低收、昨收、成交量额、五档盘口等)。 - **参数** (Query): `code`(必填)。 - **底层**: `ContextInfo.get_full_tick([code])`。sfgrid 的 `getLastPrice()` 就是从 `get_full_tick` 里取 `lastPrice` 字段。 #### GET /data/tick —— 全推 tick 快照(批量)【2026-08-26 新增】 - **功能**: 透传 `get_full_tick(codes)`,返回多个代码的最新分笔快照。客户端按需主动拉取(WS 只推增量,不做 prime 推送)。 - **参数** (Query): `codes`(必填,逗号分隔,如 `600000.SH,000001.SZ`)。 - **返回**: ```json {"ok": true, "data": {"600000.SH": {"timetag": "20260826 09:25:02", "lastPrice": 9.13, ...}}} ``` - **底层**: `ContextInfo.get_full_tick(codes)`。 #### GET /data/instrument —— 合约详细信息(含涨跌停价) - **功能**: 查询合约详细信息,**含涨跌停价**(sfgrid `dailyUpStop`/`dailyDownStop` 所需)。 - **参数** (Query): `code`(必填)。 - **返回**(实测 600519.SH): `ExchangeID/InstrumentID/InstrumentName/OpenDate/PreClose/UpStopPrice/DownStopPrice/PriceTick/...` - **底层**: `ContextInfo.get_instrument_detail(code)`。 #### GET /data/calendar/trading_dates —— 交易日历 - **功能**: 返回 [start, end] 区间交易日列表。可用于市场活跃判断。 - **参数** (Query): `start`、`end`(YYYYMMDD,可空)。 - **返回**: `{"market":"SH","count":N,"dates":["20260803",...]}` - **底层**: `ContextInfo.get_trading_dates`(大 QMT 签名 `(stockcode,start,end,count)`)。 #### 旧路径兼容(别名) - `/kline` → `/data/kline`、`/quote` → `/data/quote`(保留,旧脚本零改动)。 ### 1.3 订阅与推送(WS 单通道)【2026-08-26 新增】 > 设计详见 `docs/迭代记录/WS单通道推送设计.md`(已完成)。单通道 `/ws`,消息按 `type` 区分。 #### POST /data/subscribe —— 订阅数据(全量tick) - **功能**: 订阅数据推送类型。当前支持 `whole`(全量tick增量推送)。 - **请求体**: ```json {"type": "whole", "codes": ["SH", "SZ"]} ``` - **返回**: `{"ok": true, "sub_id": 7322507885117440}`(snowflake 类唯一 ID) - **推送**: 订阅成功后,WS 连接 `ws://host:8610/ws` 收到增量推送: ```json {"type": "whole", "data": {"600000.SH": {"lastPrice": 9.13, ...}}} ``` - **底层**: `ContextInfo.subscribe_whole_quote(codes, callback)`。 #### POST /data/unsubscribe —— 退订数据 - **功能**: 按 sub_id 退订某类型订阅。 - **请求体**: `{"sub_id": 7322507885117440}` - **返回**: `{"ok": true}` #### WS 端点 /ws —— 单通道推送 - **功能**: 客户端建立 WS 连接接收推送(心跳 30s ping/pong)。 - **推送消息**: `{"type":"whole","data":{code:tick_dict}}`(增量,只含变化品种)。 - **账号交易通知**(trade_result/order_update/position_update/asset_update): 预留命名,**尚未实现**。 ### 1.4 trade 命名空间(交易查询) > 数据来自 QMT `get_trade_detail_data`,**由策略线程(adjust/handlebar)定时刷新缓存**(当前 300ms),HTTP 线程只读缓存。账号为桥绑定账号(单账号策略),**无需 account/account_type 参数**。 #### GET /trade/positions —— 持仓查询【2026-08-26 增强】 - **功能**: 当前账号**全部持仓**,每行 = 语义化字段(xt 风格,sfgrid 可直接消费)+ 原始 `m_*` 字段超集 + 汇总 summary。 - **不做过滤**: 不提供 code/status 等过滤参数,客户端从全量中自取(sfgrid `getStockPosition` 本就以全部持仓为缓存)。 - **返回**: ```json {"ok": true, "data": {"positions": [{"stock_code": "600519.SH", "stock_name": "贵州茅台", "volume": 100, "available": 100, "frozen_volume": 0, "on_road_volume": 0, "yesterday_volume": 0, "avg_price": 1500.0, "price": 1510.0, "market_value": 151000.0, "open_price": 1500.0, "profit": 1000.0, "profit_pct": 0.67, "direction": 48, "m_strInstrumentID": "600519", ...}], "summary": {"count": 1, "total_market_value": 151000.0, "total_profit": 1000.0}}} ``` - **字段映射**: `m_strInstrumentID` → `stock_code`(补全后缀)、`m_nVolume` → `volume`、`m_nCanUseVolume` → `available`、`m_dOpenPrice` → `avg_price`/`open_price`、`m_dFloatProfit` → `profit`、市值/盈亏缺失时计算兜底。 - **底层**: 策略线程缓存(`get_trade_detail_data('POSITION')`,300ms 刷新),HTTP 线程只读。 #### GET /trade/asset —— 资金/资产查询 - **返回**: `{"ok":true,"data":[{m_dBalance, m_dAvailable, m_dAssetBalance, m_dFrozenCash, ...}]}` #### GET /trade/orders —— 委托查询(支持过滤) - **功能**: 当日委托,支持三类过滤。 - **参数** (Query): | 参数 | 说明 | |------|------| | code | 客户端按代码过滤(600519 或 600519.SH)| | status | `active`(排除已撤54/废单57)或数字状态码 | | strategy_name | **服务端**按 passorder 策略名过滤(get_trade_detail_data 第4参数)| - **返回**: `{"ok":true,"data":[{m_strOrderSysID, m_strInstrumentID, m_nOrderStatus, m_nVolumeTraded, m_dLimitPrice, ...}]}` #### GET /trade/trades —— 成交查询 - **返回**: `{"ok":true,"data":[{m_strTradeID, m_strOrderSysID, m_strInstrumentID, m_dPrice, m_nVolume, m_strTradeTime, ...}]}` --- ## 二、sfgrid 实际需要的能力(代码调用点) sfgrid 通过 `core/qmt_real.py` 的 `qmtv` 单例调用以下方法: | # | qmtv 方法 | sfgrid 用途 | 调用位置 | |---|-----------|------------|---------| | 1 | `init_qmtv()` + `connect()` | 初始化并连接 QMT | `core/ui/tinker/app.py`、`core/ui/flet/app_v2.py` | | 2 | `getAllPositions()` | 全部持仓展示/计算 | `core/ui/*/data_store.py`、`app_v2.py` | | 3 | `getStockPosition(code)` | 单票持仓查询 | 同上 | | 4 | `queryTodayOrders()` | 当日委托列表 | 同上 | | 5 | `queryTodayTrades()` | 当日成交列表 | 同上 | | 6 | `queryPendingOrder(code, tag)` | **按 strategy_name 过滤未成交挂单**(网格恢复核心) | `core/sfgrid/sfgrid_strategy.py` | | 7 | `orderAsync(code, vol, type, price, priceType, remark, strategy_name)` | 下单(带 remark + strategy_name) | 同上 | | 8 | `xt_trader.cancel_order_stock_async(account, order_id)` | 撤单(用 order_id) | 同上 | | 9 | `dailyUpStop(code)` / `dailyDownStop(code)` | 涨跌停价(网格边界校验) | 同上 | | 10 | `getLastPrice(code)` | 最新价兜底 | `data_store.py`、`app_v2.py` | | 11 | `getInstrumentName(code)` | 股票名称 | 同上 | | 12 | `isMarketActive`(属性) | 市场是否活跃(交易门禁) | `sfgrid_strategy.py` | | 13 | `subscribe_whole_quote(['SH','SZ'], cb)` + `_on_market_data` | 全市场 tick 推送 | `core/qmt_real.py` | | 14 | 回调 `on_order_stock_async_response` / `on_stock_trade` / `on_order_error` | 下单回报/成交/失败**异步推送** | `sfgrid_strategy.py` 事件订阅 | **sfgrid 网格逻辑对桥的关键要求**: 1. 下单必须透传 **`remark`**(如 `BUY_3`)和 **`strategy_name`** —— 用于关联网格档位、恢复挂单。 2. 挂单查询必须支持**按 strategy_name 过滤**(`queryPendingOrder(code, tag)` 等价)。 3. 撤单依赖 **order_id**(订单系统号),不是 remark。 4. 回报必须**异步推送**(下单成功/成交/失败),驱动网格状态机。 --- ## 三、对照结论:已满足 / 未满足 ### ✅ 已满足(桥可直接支撑) | sfgrid 需求 | 桥接口 | 备注 | |-------------|--------|------| | 全部持仓 | `GET /trade/positions` | **已增强(2026-08-26)**:语义化字段(stock_code/volume/available/avg_price/market_value/profit...)+ summary,sfgrid 无需再映射 | | 资金资产 | `GET /trade/asset` | 同上 | | 当日委托 | `GET /trade/orders` | 同上 | | 当日成交 | `GET /trade/trades` | 同上 | | 最新价 | `GET /data/quote` 或 `GET /data/tick`(取 `lastPrice`) | 返回完整快照(含五档)| | K线 | `GET /data/kline` | 桥已可用 | | 涨跌停价 | `GET /data/instrument`(`UpStopPrice`/`DownStopPrice`)| 已实现(实测 600519 → 1438.67/1177.09)| | 股票名称 | `GET /data/instrument`(`InstrumentName`)| 已实现 | | 全市场 tick 订阅 | `POST /data/subscribe` + WS `/ws`(`type=whole`)| **2026-08-26 已实现**,增量推送 | ### ⚠️ 部分满足(可用但缺细节) | sfgrid 需求 | 现状 | 缺口 | |-------------|------|------| | 市场活跃 `isMarketActive` | 无对应概念 | 桥没有暴露(可用 trading_dates + 时间判断)| ### ❌ 未满足(sfgrid 迁移必须补) | sfgrid 需求 | 缺失的桥能力 | 建议实现 | |-------------|-------------|---------| | 下单 `orderAsync` | **`POST /trade/order`** | passorder 走 **adjust() 队列**(策略线程),透传 remark/strategy_name/价格类型 | | 撤单 `cancel_order_stock_async` | **`POST /trade/cancel`** | cancel(队列→adjust),按 order_id 撤单 | | 异步回报推送 | WS 只有 `whole`(行情)| WS 推送 `trade_result`(submitted/order_update/dealt/order_error),账号交易通知预留未实现 | | 下单状态查询(轮询兜底) | 无 | `GET /trade/order/status?rid=...` | --- ## 四、建议的 sfgrid → 桥 接口映射(未来实现) | sfgrid 调用 | 桥端点(建议) | 说明 | |-------------|---------------|------| | `getAllPositions()` | `GET /trade/positions` | ✅ 已实现(语义化字段 + summary,直接可用)| | `getStockPosition(code)` | `GET /trade/positions` 后客户端按 code 取 | ✅ 已实现(桥返回全部持仓,客户端过滤即可;已确认不做服务端过滤)| | `queryTodayOrders()` | `GET /trade/orders` | ✅ 已实现 | | `queryTodayTrades()` | `GET /trade/trades` | ✅ 已实现 | | `queryPendingOrder(code, tag)` | `GET /trade/orders?strategy_name=xxx&status=active` | ✅ 已实现(服务端 strategy_name 过滤)| | `orderAsync(...)` | `POST /trade/order` | **需新增**,body 含 code/volume/opType/price/prType/remark/strategyName | | `cancel(...)` | `POST /trade/cancel` | **需新增**,body 含 orderId | | `dailyUpStop/DownStop` | `GET /data/instrument?code=` | ✅ 已实现 | | `getLastPrice(code)` | `GET /data/quote?code=` 或 `GET /data/tick?codes=` | ✅ 已实现 | | `getInstrumentName(code)` | `GET /data/instrument?code=` | ✅ 已实现 | | `subscribe_whole_quote` | `POST /data/subscribe` + WS `/ws` | ✅ 已实现(type=whole 增量推送)| | 回报推送 | WS `trade_result`(账号通知)| **需实现**(预留命名)| | `isMarketActive` | `GET /data/calendar/trading_dates` + 时间判断 | 建议扩展 | --- ## 五、官方接口依据(涨跌停价数据来源) **涨跌停价不在行情快照里,而在合约详细信息里。** - 官方接口: `ContextInfo.get_instrument_detail(code)`(根据代码获取合约详细信息) - 涨跌停字段: `UpStopPrice`(涨停)/ `DownStopPrice`(跌停) - 其他常用字段: `InstrumentName`、`OpenDate` 等 **对桥的启示**: `GET /data/instrument` 已实现,透传 `UpStopPrice`/`DownStopPrice`,同时满足 sfgrid 的 `dailyUpStop`/`dailyDownStop` 和 `getInstrumentName`。 --- ## 六、桥的已知限制(文档留痕) 1. **线程约束**: `get_trade_detail_data`/`passorder`/`cancel` 只能在**策略线程**调用,HTTP worker 线程禁止直调(查询已用缓存/队列方案解决;下单/撤单将来必须走 adjust 队列)。`download_history_data`、`get_full_tick`、`subscribe_whole_quote` 在 HTTP 线程调用已验证可行。 2. **字段名**: 桥返回 QMT 原生 `m_*` 字段,sfgrid 消费时需自行映射(如 `m_strInstrumentID` → `stock_code`)。 3. **WS 推送**: 当前已实现 `whole`(全量tick增量);**账号交易通知**(trade_result/order_update/position_update/asset_update)预留命名未实现。 4. **周期**: `/kline` 周期白名单 `tick/1m/5m/15m/30m/60m/1h/1d/1w/1mon`,合成周期自动先下载基础周期。 5. **单账号**: 桥是单账号(QMT 一个策略实例=一个账号),HTTP 接口无 account 参数;多账号=多桥实例(不同端口)。 6. **端口**: 桥监听 **8610**(HTTP + WS 共端口)。