chore: init qmt_bridge repo (HTTP+WS bridge, MCP endpoint, docs, references)
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
# MCP 服务(桥内嵌 /mcp 端点)
|
||||
|
||||
> 版本: 1.1 (2026-08-27)
|
||||
> 状态: ✅ 已完成
|
||||
> 关联: docs/设计/整体设计方案_v3.md(单端口 8610 统一方案)、docs/api_spec/openapi.yaml
|
||||
> 本次迭代: 在现有 qmt_bridge HTTP 服务器上新增 MCP(Model Context Protocol)端点,使 AI 助手(Claude Desktop / Cursor 等)可直接通过 MCP 调用桥的行情/交易能力
|
||||
|
||||
---
|
||||
|
||||
## 一、已确认的设计决策
|
||||
|
||||
### 1.1 结论:可行,采用"桥内嵌 /mcp 端点"方案
|
||||
|
||||
MCP 本质是 **JSON-RPC 2.0 应用协议**,官方两种传输:
|
||||
- **stdio**:子进程管道,适合"MCP 客户端拉起独立进程"
|
||||
- **Streamable HTTP**(2025-03-26 起取代旧 SSE):POST JSON-RPC,单请求-响应
|
||||
|
||||
桥已经手写 raw-socket HTTP 服务器,并已证明可在同一端口处理 WebSocket 长连接(Upgrade 分流)。因此:
|
||||
|
||||
- **选定方案 A(桥内嵌)**:新增 `bridge_mcp_server.py`,在 `POST /mcp` 上实现 JSON-RPC 2.0 分发,工具直接复用 `bridge_data_adapter` / `bridge_util`。
|
||||
- **放弃方案 B(独立 MCP 进程 + 官方 mcp SDK)**:官方 SDK 要求 **Python ≥ 3.10**,QMT 内置是 **Python 3.6.8 纯标准库**(不能装包);方案 B 需额外进程经 HTTP 8610 转发,多一跳且偏离项目"薄桥/零依赖"理念。
|
||||
- **传输选型**:Streamable HTTP 的"非流式"子集(单请求-响应 `application/json`),覆盖主流 MCP 客户端。流式(SSE)留待后续。
|
||||
|
||||
### 1.2 约束核对(逐条过项目规范)
|
||||
|
||||
| 硬约束 | 影响 | 结论 |
|
||||
|--------|------|------|
|
||||
| 源码 GBK + 纯 ASCII | 新模块同样遵守,无新问题 | ✅ |
|
||||
| QMT 函数线程约束 | MCP tools/call 跑在 HTTP worker 线程,全部复用现有 adapter 安全模式 | ✅ |
|
||||
| 单账号 | MCP 工具无 account 参数,与 HTTP 一致 | ✅ |
|
||||
| 单端口 8610 | `POST /mcp` 复用 8610,不新开端口 | ✅ |
|
||||
| 热重载 | `qmt_strategy_entry.py` 的 `_BRIDGE_MODULES` 需加 `bridge_mcp_server` | ✅ |
|
||||
| 部署 | `deploy_elevated.bat` 需加 `bridge_mcp_server.py` | ✅ |
|
||||
|
||||
### 1.3 协议实现范围(MCP 最小集)
|
||||
|
||||
| MCP 方法 | 实现 | 说明 |
|
||||
|----------|------|------|
|
||||
| `initialize` | ✅ | 返回协议版本 + `tools` capability,记录协商版本 |
|
||||
| `notifications/initialized` | ✅ | 空响应(通知类) |
|
||||
| `ping` | ✅ | 返回空 result |
|
||||
| `tools/list` | ✅ | 从内置工具注册表返回 `{tools: [...]}`(含 inputSchema) |
|
||||
| `tools/call` | ✅ | 校验参数 → 调 adapter → 返回 `{content:[{type:"text",text:json}]}` |
|
||||
|
||||
> 暂不实现: `resources/*`、`prompts/*`、`logging/*`、`completions/*`、流式(SSE)。纯工具型最小实现与主流客户端兼容。
|
||||
|
||||
### 1.4 首批工具(9 个,与 HTTP 接口 1:1)
|
||||
|
||||
| 工具名 | 对应 HTTP | 底层 |
|
||||
|--------|-----------|------|
|
||||
| `qmt_kline` | GET /data/kline | get_market_data_ex(worker 线程直调 ✅) |
|
||||
| `qmt_quote` | GET /data/quote | get_full_tick |
|
||||
| `qmt_tick` | GET /data/tick | get_full_tick(批量) |
|
||||
| `qmt_instrument` | GET /data/instrument | get_instrument_detail |
|
||||
| `qmt_trading_dates` | GET /data/calendar/trading_dates | get_trading_dates |
|
||||
| `qmt_positions` | GET /trade/positions | 读 TRADE_CACHE(策略线程刷新 ✅) |
|
||||
| `qmt_asset` | GET /trade/asset | 读 TRADE_CACHE |
|
||||
| `qmt_orders` | GET /trade/orders | 读 TRADE_CACHE(+ 可选过滤) |
|
||||
| `qmt_trades` | GET /trade/trades | 读 TRADE_CACHE |
|
||||
|
||||
后续迭代: `qmt_order`(下单,队列→adjust)、`qmt_cancel`(撤单)、`qmt_subscribe`(订阅)。
|
||||
|
||||
### 1.5 工具实现与 HTTP 共用一个内部函数层
|
||||
|
||||
为免工具逻辑与 HTTP handler 双写,`bridge_mcp_server.py` 内置"工具名 → 参数校验 → 结果 dict"的映射,直接 import `bridge_data_adapter` 的函数(get_market_data_ex / get_full_tick / get_instrument_detail / get_trading_dates / get_trade_data / get_positions),参数语义与 HTTP 完全一致(code 自动补后缀等)。
|
||||
|
||||
> 说明: 本次迭代不把 HTTP handler 重构为共用同一函数层(避免动既有稳定代码);但工具内部复用的 adapter 已是同一函数,行为一致。文档(openapi.yaml)仍是唯一事实来源,工具 schema 与之保持 1:1。
|
||||
|
||||
### 1.6 鉴权与 CORS
|
||||
|
||||
- 鉴权复用桥 TOKEN 机制: `X-Token` header 或 `?token=`(MCP 客户端如 Claude Desktop 支持自定义 header)。
|
||||
- 响应带 CORS 头(`Access-Control-Allow-Origin: *` 等),兼容浏览器类 MCP 客户端 / 调试工具。
|
||||
- `OPTIONS /mcp` 预检返回 204。
|
||||
|
||||
### 1.7 错误语义
|
||||
|
||||
- 非法 JSON / 非法 JSON-RPC: `-32700` parse error / `-32600` invalid request(HTTP 200, MCP 规范要求 JSON-RPC 错误也走 200)。
|
||||
- 未知方法: `-32601` method not found。
|
||||
- 工具参数错误: `-32602` invalid params(带 detail)。
|
||||
- 工具执行异常: `-32603` internal error(带 detail)。
|
||||
- 非 JSON-RPC body(如纯文本): 400 + `{"detail": "..."}`(桥统一错误格式)。
|
||||
|
||||
---
|
||||
|
||||
## 二、实现记录(已完成)
|
||||
|
||||
### 2.1 新增文件
|
||||
|
||||
- `src/bridge_mcp_server.py`: JSON-RPC 2.0 分发 + 9 个工具(复用 bridge_data_adapter)+ raw-socket 响应 + CORS 头
|
||||
- `tests/test_mcp.py`: mock 测试(纯标准库,FakeDF 代替 pandas,本机即可跑),覆盖 initialize / tools/list / 9 个 tools/call / 错误路径 / notification 202 / OPTIONS 204
|
||||
|
||||
### 2.2 改动文件
|
||||
|
||||
- `src/bridge_http_server.py`: `POST /mcp` 路由 + `OPTIONS /mcp` CORS 预检(204)
|
||||
- `src/qmt_strategy_entry.py`: `_BRIDGE_MODULES` 热重载列表加入 `bridge_mcp_server`
|
||||
- `deploy_elevated.bat`: 部署文件列表加入 `bridge_mcp_server.py`(7 → 8 个 .py)
|
||||
- `README.md` / `docs/项目规范.md`(新增 3.8 节)/ `docs/迭代记录/index.md`: 文档同步
|
||||
|
||||
### 2.3 实现要点
|
||||
|
||||
- **工具与 HTTP 1:1**: qmt_kline / qmt_quote / qmt_tick / qmt_instrument / qmt_trading_dates / qmt_positions / qmt_asset / qmt_orders / qmt_trades
|
||||
- **协议**: `initialize`(协商 protocolVersion,回显 2025-06-18/2025-03-26/2024-11-05)、`notifications/initialized`(202 空 body)、`ping`、`tools/list`、`tools/call`
|
||||
- **错误**: JSON-RPC 错误走 HTTP 200(parse -32700 / invalid request -32600 / method not found -32601 / invalid params -32602 / internal -32603);非法 body 走 400 `{"detail":...}`
|
||||
- **鉴权/CORS**: 复用 TOKEN(X-Token);`OPTIONS /mcp` 预检 204;响应带 `Access-Control-Allow-Origin: *`
|
||||
- **线程约束**: 全部工具经 bridge_data_adapter → 与 HTTP 端点同模式(行情 worker 直调,交易读缓存),无新 QMT 调用形态
|
||||
|
||||
### 2.4 验证结果
|
||||
|
||||
- 编译 + ASCII 检查: 全部通过(纯 ASCII,0 非 ASCII 字节)
|
||||
- `python tests/test_mcp.py`: 17 项断言全部 OK(initialize、9 工具、错误路径、202、204)
|
||||
- 回归: `test_subscription.py` / `test_sub_no_ws.py` / `test_ws_push.py` 全部通过(路由改动无影响)
|
||||
|
||||
---
|
||||
|
||||
## 三、待讨论事项
|
||||
|
||||
- 是否需要 SSE 流式(长连接占线程池 worker,参考 WS 的处理;默认不做)
|
||||
- 是否需要 `qmt_order` / `qmt_cancel`(依赖交易接口后续迭代)
|
||||
- 目标 MCP 客户端确认(Claude Desktop / Cursor / DSH 等)
|
||||
@@ -0,0 +1,146 @@
|
||||
# WS 单通道推送设计
|
||||
|
||||
> 版本: 3.1 (2026-08-25)
|
||||
> 状态: ✅ **已完成**(2026-08-26 实现并真实验证通过)
|
||||
> 关联: docs/设计/整体设计方案_v3.md 第五节(订阅与推送)
|
||||
> 本次迭代: **通用接口定义 + 全量 tick 订阅(whole)**
|
||||
>
|
||||
> 实现记录:
|
||||
> - 新增 `src/bridge_subscription.py`(订阅管理:snowflake sub_id、订阅表、QMT 回调→WS 推送)
|
||||
> - `bridge_http_server.py` 新增 `POST /data/subscribe`、`POST /data/unsubscribe`、`GET /data/tick`
|
||||
> - `bridge_ws_server.py` 新增 `broadcast_all`
|
||||
> - `bridge_main.py` stop 清理订阅;`qmt_strategy_entry.py` 热重载模块列表更新
|
||||
> - 桥端口迁移至 **8610**
|
||||
> - 真实验证通过:订阅 whole → WS 收到真实增量推送(单批最多 26673 代码)、tick 快照、退订正常
|
||||
|
||||
## 一、通道定义(已确认)
|
||||
|
||||
**只保留一个 WS 通道**,不再区分 data/trade 双通道。
|
||||
|
||||
- WS 端点:`ws://host:8610/ws`(单通道)
|
||||
- 所有推送(行情数据 + 交易事件)走同一条连接
|
||||
- 消息用 `type` 字段区分类型
|
||||
- 客户端按 `type` 解析分发到不同处理逻辑
|
||||
|
||||
> 变更记录:v1 曾设计双通道(/data/ws + /trade/ws),讨论后改为单通道。
|
||||
|
||||
## 二、订阅流程(已确认)
|
||||
|
||||
**客户端通过 HTTP 提交订阅请求,订阅成功后建立 WS 连接接收推送。**
|
||||
|
||||
```
|
||||
1. 客户端 → HTTP 提交订阅请求(含订阅类型 + 内容)
|
||||
2. 服务端订阅成功,记录:订阅ID + 订阅类型
|
||||
3. 服务端 → 客户端:返回 订阅ID
|
||||
4. 客户端 建立 WS 连接 (ws://host:8610/ws)
|
||||
5. 开始接收数据推送(按 type 分发)
|
||||
6. 以后:客户端用 订阅ID 取消某类型的订阅
|
||||
```
|
||||
|
||||
已确认要点:
|
||||
- **订阅/退订统一走 HTTP**(请求-响应,返回明确结果)
|
||||
- 服务端记录:**订阅ID + 订阅类型**(+ 订阅内容,如 codes)
|
||||
- 订阅响应返回:**订阅ID**
|
||||
- **去掉 client_id**(单客户端场景,客户端不需要自报身份)
|
||||
- **统一按单客户端处理**:不搞多客户端归属路由
|
||||
- **WS 连接:无 client_id**,推送发到唯一 WS 连接
|
||||
- **按订阅过滤推送**:用户订阅了什么类型,才推送什么类型;
|
||||
没订阅的数据类型不推送;退订某类型后该类型停止推送
|
||||
- **不做 prime 推送**:WS 只推增量(subscribe_whole_quote 回调数据);
|
||||
客户端需要当前快照时,**主动调用透传 get_full_tick 的 HTTP 接口**(另设)
|
||||
- **心跳机制:沿用现有**(服务端每 30s ping,客户端回 pong,已有实现)
|
||||
- **退订用订阅ID**(HTTP 退订接口)
|
||||
|
||||
## 三、订阅接口 URI(已确认风格 B)
|
||||
|
||||
**一个订阅接口,type 在 body 里**:
|
||||
|
||||
| 方法 | URI | body | 返回 |
|
||||
|------|-----|------|------|
|
||||
| POST | `/data/subscribe` | `{"type":"whole","codes":["SH","SZ"]}` | `{"ok":true,"sub_id":123}` |
|
||||
| POST | `/data/unsubscribe` | `{"sub_id":123}` | `{"ok":true}` |
|
||||
|
||||
- 数据订阅类型未来扩展(whole/stock/kline)只需加 type,不改 URI
|
||||
- **sub_id 生成:snowflake 类唯一 ID 算法**(时间戳 + 序列号,全局唯一、趋势递增)
|
||||
- **错误格式:沿用项目规范 3.6**——`{"detail":"..."}` + 4xx/5xx
|
||||
(如 400 unsupported type / codes required、404 sub_id not found、503 订阅失败)
|
||||
|
||||
## 四、两类推送(已确认架构)
|
||||
|
||||
| 类别 | 是否需要订阅 | 推送方式 |
|
||||
|------|-------------|---------|
|
||||
| **数据订阅**(whole 全量tick 等)| 需要订阅,按订阅过滤 | 订阅了什么才推什么 |
|
||||
| **账号交易通知**(成交/订单/持仓/资金)| **不需要订阅**,统一回传 | 账号级事件,连上 WS 即收 |
|
||||
|
||||
## 四之二、get_full_tick 透传接口(已确认新增)
|
||||
|
||||
WS 只推增量(subscribe_whole_quote 回调数据),**不做 prime 快照推送**;
|
||||
客户端需要当前 tick 快照时,主动调用本接口:
|
||||
|
||||
| 方法 | URI | 参数 | 返回 |
|
||||
|------|-----|------|------|
|
||||
| GET | `/data/tick` | `codes=600000.SH,000001.SZ`(逗号分隔)| `{"ok":true,"data":{code: tick_dict}}` |
|
||||
|
||||
- 底层:透传 `ContextInfo.get_full_tick(codes)`(现有 `bridge_data_adapter.get_full_tick`)
|
||||
- 支持批量代码;与单票 `/data/quote` 并存(/data/tick 批量,/data/quote 保留兼容)
|
||||
|
||||
## 五、本次迭代范围(聚焦)
|
||||
|
||||
**本次实现**:
|
||||
- 通用接口定义:订阅接口(HTTP)、退订接口(HTTP)、WS 单通道、心跳
|
||||
- **数据订阅:全量 tick(type=whole)**——订阅/退订/增量推送
|
||||
- **get_full_tick 透传接口**(`/data/tick`,客户端按需拉快照)
|
||||
|
||||
**本次不做(预留,保留命名,不实现)**:
|
||||
- 数据订阅其他类型:单票行情(预留)
|
||||
- 账号交易通知:成交/订单/持仓/资金回调推送
|
||||
|
||||
## 六、type 枚举(初步定义)
|
||||
|
||||
### 数据订阅类(按订阅推送)
|
||||
| type | 含义 | 本次 |
|
||||
|------|------|------|
|
||||
| `whole` | 全量 tick(增量推送,只含变化的品种)| ✅ 实现 |
|
||||
|
||||
### 账号交易通知类(统一回传,本次不实现)
|
||||
| type | 含义 | 触发 |
|
||||
|------|------|------|
|
||||
| `trade_result` | 成交回报 | deal_callback |
|
||||
| `order_update` | 订单状态 | order_callback |
|
||||
| `position_update` | 持仓变更 | position_callback |
|
||||
| `asset_update` | 资金变更 | account_callback |
|
||||
|
||||
### 通用
|
||||
| type | 含义 |
|
||||
|------|------|
|
||||
| `pong` | 心跳响应(现有)|
|
||||
|
||||
> 已确认:**不加** `subscribed`/`unsubscribed`(HTTP 响应已确认订阅结果);
|
||||
> **不加** `error`(订阅期错误由 HTTP 4xx/5xx 返回,运行期错误服务端内部消化,客户端无需感知)
|
||||
|
||||
## 七、whole 推送消息结构(已确认)
|
||||
|
||||
与 `get_full_tick` / `subscribe_whole_quote` 回调数据结构一致(官方文档确认):
|
||||
|
||||
```json
|
||||
{"type":"whole","data":{"600000.SH":{"timetag":"20231106 15:00:04","lastPrice":2.533,"open":2.528,"high":2.538,"low":2.521,"lastClose":2.513,"amount":1442588037.0,"volume":5701929,"pvolume":5701929,"stockStatus":5}}}
|
||||
```
|
||||
|
||||
- `data`:`{code: tick_dict}`,code 为完整代码(600000.SH)
|
||||
- 增量推送只含**变化的品种**
|
||||
- tick_dict 字段透传 QMT 原始字段(timetag/lastPrice/open/high/low/lastClose/amount/volume/pvolume/stockStatus...)
|
||||
|
||||
## 八、改造点(已确认)
|
||||
|
||||
| 文件 | 改动 |
|
||||
|------|------|
|
||||
| `bridge_http_server.py` | 新增路由:`POST /data/subscribe`、`POST /data/unsubscribe`、`GET /data/tick` |
|
||||
| `bridge_ws_server.py` | 新增 `broadcast_all`(推送 whole 到唯一连接);现有心跳保留 |
|
||||
| `bridge_subscription.py`(新)| 订阅管理:订阅表(sub_id → type/codes)、snowflake sub_id、订阅/退订逻辑、QMT 订阅回调 → 推送 |
|
||||
| `bridge_main.py` | 初始化订阅管理器;adjust 里驱动 |
|
||||
| `bridge_data_adapter.py` | `get_full_tick` 已存在(批量支持)|
|
||||
|
||||
## 九、参考资料(仅背景,非设计结论)
|
||||
|
||||
- docs/设计/整体设计方案_v3.md 第五节:订阅与推送的总体规划
|
||||
- reference/xtquant_big_convert 的 quote_subscription_manager.py:订阅管理的参考实现
|
||||
@@ -0,0 +1,12 @@
|
||||
# 迭代记录索引
|
||||
|
||||
> 本目录存放每次迭代的设计/实现记录。每完成一次迭代,在下方表格登记一行。
|
||||
> 迭代规范见 `docs/项目规范.md` 第九节。
|
||||
|
||||
## 迭代索引表
|
||||
|
||||
| # | 迭代 | 日期 | 状态 | 关联文档 |
|
||||
|---|------|------|------|---------|
|
||||
| 1 | WS 单通道推送(一期:通用接口 + 全量tick订阅 whole) | 2026-08-25 ~ 2026-08-26 | ✅ 已完成 | [WS单通道推送设计.md](./WS单通道推送设计.md) |
|
||||
| 2 | 持仓查询接口(GET /trade/positions 增强:语义化字段 + summary) | 2026-08-26 | ✅ 已完成 | [持仓查询接口.md](./持仓查询接口.md) |
|
||||
| 3 | MCP 服务(桥内嵌 /mcp 端点:JSON-RPC tools) | 2026-08-27 | ✅ 已完成 | [MCP服务.md](./MCP服务.md) |
|
||||
@@ -0,0 +1,86 @@
|
||||
# 持仓查询接口(GET /trade/positions 增强)
|
||||
|
||||
> 版本: 1.0 (2026-08-26)
|
||||
> 状态: ✅ 已完成
|
||||
> 关联: docs/设计/整体设计方案_v3.md 第四节(trade 命名空间)、docs/桥接口清单与sfgrid满足度对照.md
|
||||
> 本次迭代: **持仓查询接口返回全部持仓信息(语义化字段 + 汇总),不做过滤筛选,不兼容旧调用模式**
|
||||
|
||||
## 一、已确认的设计决策
|
||||
|
||||
1. **接口**: `GET /trade/positions`(复用现有路由,不改 URI)
|
||||
2. **返回全部持仓信息**: 每一行 = 语义化字段(xt 风格,供 sfgrid 等消费方直接使用)+ 完整原始 m_* 字段(透传,不丢弃)
|
||||
3. **不做过滤筛选**: 不加 code/status 等过滤参数;客户端需要单票时自行从全量中取(sfgrid 的 getStockPosition 本就以全部持仓为缓存)
|
||||
4. **不兼容旧调用模式**: 不再承诺只返回 m_* 原始字段;新返回为超集(m_* 仍在,新增语义字段),旧调用方读 m_* 不受影响,但返回结构/示例以本设计为准
|
||||
5. **增加汇总 summary**: count(持仓只数)、total_market_value(总市值)、total_profit(总浮动盈亏)
|
||||
6. **字段映射**(QMT POSITION 行 → 语义字段,字段缺失时安全降级):
|
||||
|
||||
| 语义字段 | 来源(m_* 候选,按序探测) | 说明 |
|
||||
|----------|------------------------|------|
|
||||
| stock_code | m_strInstrumentID | 完整代码(带交易所后缀,如 600519.SH) |
|
||||
| stock_name | m_strInstrumentName | 股票名称 |
|
||||
| volume | m_nVolume | 总持仓量 |
|
||||
| available | m_nCanUseVolume | 可用持仓量 |
|
||||
| frozen_volume | m_nFrozenVolume | 冻结数量 |
|
||||
| on_road_volume | m_nOnRoadVolume | 在途数量 |
|
||||
| yesterday_volume | m_nYesterdayVolume | 昨仓数量 |
|
||||
| avg_price | m_dOpenPrice / m_dCostPrice | 持仓成本价 |
|
||||
| price | m_dLastPrice / m_dSettlementPrice / m_dOpenPrice | 最新价(缺失时兜底成本价) |
|
||||
| market_value | m_dMarketValue / m_dInstrumentValue / volume*price 计算 | 持仓市值 |
|
||||
| open_price | m_dOpenPrice | 开仓价(与 avg_price 同源) |
|
||||
| profit | m_dFloatProfit / 计算 (price-avg_price)*volume | 浮动盈亏 |
|
||||
| profit_pct | 计算 | 盈亏比例 % |
|
||||
| direction | m_nDirection | 方向(默认 48=多) |
|
||||
|
||||
7. **JSON 安全**: 所有值经 `_json_safe` 处理(QMT 可能返回 numpy 类型)
|
||||
|
||||
## 二、实现记录(已完成)
|
||||
|
||||
- `src/bridge_data_adapter.py` 新增 `get_positions()`:
|
||||
- 从 `bridge_util.get_trade_cache("position")` 读缓存(策略线程 300ms 刷新,HTTP 线程只读)
|
||||
- 每行先 `_obj_to_dict` 得到 m_* 字段,再补充语义字段(含缺失字段探测与计算兜底)
|
||||
- 计算 summary: count / total_market_value / total_profit
|
||||
- 返回 `{"positions": [...], "summary": {...}}`
|
||||
- `src/bridge_http_server.py` `_api_trade`: `dtype == "position"` 时调用新 `get_positions()`,返回 `{"ok":true,"data":{...}}`
|
||||
- `tests/test_trade.py`: 更新持仓断言(语义字段 + summary)
|
||||
- `docs/api_spec/openapi.yaml`: `/trade/positions` 响应示例更新为语义字段 + summary
|
||||
- 重新生成 `docs/api_spec/openapi.json`
|
||||
|
||||
## 三、返回结构(示例)
|
||||
|
||||
```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.SH",
|
||||
"m_nVolume": 100,
|
||||
"m_nCanUseVolume": 100,
|
||||
"m_dOpenPrice": 1500.0,
|
||||
"m_dFloatProfit": 1000.0
|
||||
}
|
||||
],
|
||||
"summary": {
|
||||
"count": 1,
|
||||
"total_market_value": 151000.0,
|
||||
"total_profit": 1000.0
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> 说明: 语义字段名以 xtquant 风格为准(sfgrid `qmt_real.py`/`data_store.py` 消费的 `volume/avg_price/stock_code/instrument_name` 等);原始 `m_*` 字段作为超集保留在同一行,避免旧调用方(如已部署脚本)因删字段而失效。
|
||||
Reference in New Issue
Block a user