Files
qmt_bridge/README.md
T

151 lines
8.5 KiB
Markdown

# QMT Bridge — 大 QMT 薄桥(HTTP + WebSocket)
将大 QMT(国金 GJQMT_BIG)内置 Python 的行情/交易能力,通过 HTTP RESTful + WebSocket 推送暴露为开放数据服务。接口规范由本地维护的 OpenAPI 文档驱动,可同步 Apifox 管理。
> ## ⚠️ 新会话启动 · 首要参考
> 1. **本文件(README.md)** — 项目概览、结构、接口、部署、约束速查
> 2. **`docs/项目规范.md`** — 详细规范(设计约束/部署/接口文档/迭代规范),项目的"宪法"
> 3. **`docs/设计/整体设计方案_v3.md`** — 唯一设计依据(架构决策/环境调研/性能实测)
> 4. **`docs/迭代记录/index.md`** — 迭代索引(每次迭代的记录)
## 架构一句话
**薄桥**:跑在 QMT 策略进程内(Python 3.6.8,纯标准库),HTTP 做请求,WS 做推送,所有业务逻辑由 QMT 统一处理,桥只做协议转换。
```
外部客户端 ── HTTP(8610): 查询/订阅 ──► 大QMT策略进程
◄── WS(8610): 行情推送 ── bridge_main.py
```
- 端口: **8610**(HTTP + WS 共端口)
- 账号: 单账号(桥绑定),从 `bridge_local_config.py` 读 ACCOUNT_ID
## 目录结构
```
qmt_bridge/
├── README.md ← 本文件(会话启动参考)
├── docs/
│ ├── 项目规范.md ← 项目规范(宪法,详细约束)
│ ├── api_spec/openapi.yaml ← 接口规范(唯一事实来源,中文,主动维护)
│ ├── 设计/整体设计方案_v3.md ← 主设计文档(唯一设计依据)
│ ├── 研究/ ← 调研类文档(xtquant_big_convert调研、官方接口核实)
│ ├── 迭代记录/index.md ← 迭代索引(每次迭代登记)
│ ├── 桥接口清单与sfgrid满足度对照.md
│ └── ...
├── src/ ← 桥源码(部署时复制到 QMT python 目录)
│ ├── bridge_main.py ← QMT 生命周期入口
│ ├── bridge_http_server.py ← HTTP server + 路由(含 /mcp 路由)
│ ├── bridge_ws_server.py ← WebSocket(心跳 + broadcast_all 推送)
│ ├── bridge_data_adapter.py ← QMT API 透传适配层
│ ├── bridge_subscription.py ← 订阅管理(snowflake sub_id + QMT 回调→WS 推送)
│ ├── bridge_mcp_server.py ← MCP 端点(JSON-RPC tools,POST /mcp)
│ ├── bridge_util.py ← 共享状态 + 工具
│ └── qmt_strategy_entry.py ← QMT 策略入口(粘贴进 QMT 编辑器,含热重载)
├── tools/
│ ├── push_apifox.py ← 生成 openapi.json + Apifox 手动导入指引
│ ├── fetch_apifox_doc.ps1 ← 沙箱外抓取 Apifox 文档(UAC 提权)
│ └── fetch_qmt_docs.ps1 ← 沙箱外抓取 QMT 官方文档(UAC 提权)
├── tests/
│ ├── test_trade.py ← 交易接口 mock 测试
│ ├── test_subscription.py ← 订阅/退订/tick mock 测试
│ ├── test_ws_push.py ← WS 推送链路 mock 测试
│ ├── test_ws_real.py ← 真实 QMT WS 推送验证
│ └── test_sub_no_ws.py ← 无 WS 连接时订阅行为测试
├── reference/ ← 参考材料(xtquant_big_convert 等,只读)
└── deploy_elevated.bat ← 部署脚本(自动提权)
```
## 模块职责与依赖
```
bridge_main.py ──import──► bridge_http_server.py, bridge_ws_server.py, bridge_data_adapter.py, bridge_subscription.py
bridge_http_server.py ──import──► bridge_data_adapter.py, bridge_util.py, bridge_ws_server.py, bridge_subscription.py
bridge_ws_server.py ──import──► bridge_util.py
bridge_data_adapter.py ──import──► bridge_util.py
bridge_subscription.py ──import──► bridge_util.py, bridge_ws_server.py
```
| 模块 | 职责 |
|------|------|
| bridge_main.py | QMT 生命周期,启动/停止服务器,绑定 QMT API,刷新交易缓存,清理订阅 |
| bridge_http_server.py | HTTP 服务,路由(含订阅/退订/tick/MCP),WS Upgrade 分流,openapi 端点 |
| bridge_ws_server.py | WS 握手/帧编解码/心跳,broadcast_all 推送 |
| bridge_data_adapter.py | 调 QMT API(get_market_data_ex/get_full_tick/get_instrument_detail/get_trading_dates/get_trade_data) |
| bridge_subscription.py | 订阅管理: snowflake sub_id、订阅表、QMT 订阅回调→WS 推送 |
| bridge_mcp_server.py | MCP 端点: JSON-RPC 2.0(initialize/ping/tools/list/tools/call),9 个工具 |
| bridge_util.py | 日志、工具、共享状态(CTX/QMT_API/交易缓存) |
| qmt_strategy_entry.py | QMT 策略入口(热重载: 重跑时清模块缓存+释放端口) |
## 当前接口(12 个,详见 docs/api_spec/openapi.yaml)
- GET `/health` — 健康检查
- GET `/data/kline` — K线(先下载后查询,fields 可筛选,默认完整 OHLCV)
- GET `/data/quote` — 实时快照(单票 full tick,含五档)
- GET `/data/tick` — 全推 tick 快照(批量,透传 get_full_tick)【订阅体系】
- GET `/data/instrument` — 合约详情(涨跌停价/名称)
- GET `/data/calendar/trading_dates` — 交易日历
- POST `/data/subscribe` — 订阅数据(当前支持 whole 全量tick)【订阅体系】
- POST `/data/unsubscribe` — 退订数据【订阅体系】
- GET `/trade/positions` — 持仓(全部持仓,语义化字段 + m_* 超集 + summary)
- GET `/trade/asset` — 资金资产
- GET `/trade/orders` — 委托(code/status/strategy_name 过滤)
- GET `/trade/trades` — 成交
- WS `/ws` — 单通道推送(接收 `{"type":"whole","data":{code:tick_dict}}` 增量)
- POST `/mcp`**MCP 端点**(JSON-RPC 2.0): `initialize` / `ping` / `tools/list` / `tools/call`,9 个工具与 HTTP 接口 1:1(`qmt_kline`/`qmt_quote`/`qmt_tick`/`qmt_instrument`/`qmt_trading_dates`/`qmt_positions`/`qmt_asset`/`qmt_orders`/`qmt_trades`),详见 `docs/迭代记录/MCP服务.md`
**待实现**: `/trade/order`(下单)、`/trade/cancel`(撤单)、`/trade/order/status`、WS 账号交易通知(trade_result 等)、MCP `qmt_order`/`qmt_cancel`/SSE 流式。
## 部署到 QMT
1. 双击 `deploy_elevated.bat`(自动提权,复制 src 下 7 个 .py 到 `C:\Programs\GJQMT_BIG\python\`)
2. QMT 策略编辑器新建策略,粘贴 `qmt_strategy_entry.py` 内容(含热重载)
3. 配置 `C:\Programs\GJQMT_BIG\python\bridge_local_config.py``ACCOUNT_ID`
4. 运行 → 日志 `[qmt_bridge] HTTP+WS server started on 0.0.0.0:8610`
**热重载**: 改代码后 QMT 里 停止→运行 即可(入口自动清模块缓存+释放端口)。
> ⚠️ 若端口被残留占用(监听但不响应),需**重启 QMT 进程**彻底释放。
**验证**: `http://127.0.0.1:8610/health` 返回 ok 即正常。
## 接口规范同步(Apifox)
- 桥提供 `GET /openapi.yaml` / `GET /openapi.json`(从 QMT 目录读取,Apifox URL 同步用)
- 手动导入: Apifox → 导入数据 → OpenAPI/Swagger → 文件导入 `docs/api_spec/openapi.yaml`
- 辅助: `python tools/push_apifox.py`(生成 json + 打印步骤)
- 开放 API 自动推送未打通(沙箱代理伪造 201 / PowerShell 422)
## 本地测试
```bash
python tests/test_trade.py # 交易接口 mock 测试
python tests/test_subscription.py # 订阅/退订/tick mock 测试
python tests/test_ws_push.py # WS 推送链路 mock 测试
python tests/test_mcp.py # MCP 端点 mock 测试(纯标准库,无需 pandas)
```
## 关键约束(硬性,详见 docs/项目规范.md)
1. **源码编码**: 文件头 `# coding:gbk`,内容必须**纯 ASCII**(UTF-8 中文会 SyntaxError)
2. **QMT 函数线程约束**: `get_trade_detail_data`/`passorder`/`cancel` 只能在**策略线程**调(缓存/队列方案);
`get_full_tick`/`subscribe_whole_quote`/`download_history_data` 可在 HTTP 线程调(实测)
3. **单账号**: 桥天然单账号(QMT 一个策略=一个账号),HTTP 接口无 account 参数
4. **字段差异**: 大 QMT 订单行无 `m_strStrategyName`;`m_strInstrumentID` 不带后缀
5. **K线**: 查询前必须先下载;fields 传完整列表;DataFrame 用 iat 取值
6. **错误格式**: `{"detail":"..."}` + 4xx/5xx
## 迭代规范
每次迭代在 `docs/迭代记录/` 定义设计文档,在 `index.md` 登记索引,记录完成情况。详见 `docs/项目规范.md` 第九节。
## 文档导航
| 文档 | 用途 |
|------|------|
| `docs/项目规范.md` | 项目宪法: 结构/约束/部署/接口文档/迭代规范 |
| `docs/设计/整体设计方案_v3.md` | 唯一设计依据(架构/环境调研/性能实测/变更记录) |
| `docs/api_spec/openapi.yaml` | 接口规范唯一事实来源 |
| `docs/桥接口清单与sfgrid满足度对照.md` | sfgrid 需求 vs 桥能力 |
| `docs/迭代记录/index.md` | 迭代索引 |
| `docs/研究/` | 调研文档 |