15 KiB
15 KiB
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直接封装xtquantSDK(XtQuantTrader+xtdata),不是 HTTP 桥。 - 目标: 让 sfgrid 可以改走 qmt_bridge(或桥为其提供等价能力)。
- 一句话结论: 桥的查询类接口已满足 sfgrid 的持仓/资金/委托/成交/行情/涨跌停价/全量tick需求;交易闭环(下单、撤单、异步回报推送)尚未实现,是 sfgrid 迁移的主要缺口。
一、当前桥已实现接口(✅ 12 个)
1.1 通用
GET /health —— 健康检查
- 功能: 检查桥是否存活,返回运行模式、端口、当前资金账号、桥版本。
- 返回:
{ "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或600519period str 1dtick/1m/5m/15m/30m/60m/1h/1d/1w/1monstart str ""起始 YYYYMMDDend str ""结束 YYYYMMDDcount 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):
{ "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)。 - 返回:
{"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增量推送)。 - 请求体:
{"type": "whole", "codes": ["SH", "SZ"]} - 返回:
{"ok": true, "sub_id": 7322507885117440}(snowflake 类唯一 ID) - 推送: 订阅成功后,WS 连接
ws://host:8610/ws收到增量推送:{"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本就以全部持仓为缓存)。 - 返回:
{"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 网格逻辑对桥的关键要求:
- 下单必须透传
remark(如BUY_3)和strategy_name—— 用于关联网格档位、恢复挂单。 - 挂单查询必须支持按 strategy_name 过滤(
queryPendingOrder(code, tag)等价)。 - 撤单依赖 order_id(订单系统号),不是 remark。
- 回报必须异步推送(下单成功/成交/失败),驱动网格状态机。
三、对照结论:已满足 / 未满足
✅ 已满足(桥可直接支撑)
| 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。
六、桥的已知限制(文档留痕)
- 线程约束:
get_trade_detail_data/passorder/cancel只能在策略线程调用,HTTP worker 线程禁止直调(查询已用缓存/队列方案解决;下单/撤单将来必须走 adjust 队列)。download_history_data、get_full_tick、subscribe_whole_quote在 HTTP 线程调用已验证可行。 - 字段名: 桥返回 QMT 原生
m_*字段,sfgrid 消费时需自行映射(如m_strInstrumentID→stock_code)。 - WS 推送: 当前已实现
whole(全量tick增量);账号交易通知(trade_result/order_update/position_update/asset_update)预留命名未实现。 - 周期:
/kline周期白名单tick/1m/5m/15m/30m/60m/1h/1d/1w/1mon,合成周期自动先下载基础周期。 - 单账号: 桥是单账号(QMT 一个策略实例=一个账号),HTTP 接口无 account 参数;多账号=多桥实例(不同端口)。
- 端口: 桥监听 8610(HTTP + WS 共端口)。