Files

87 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 持仓查询接口(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_*` 字段作为超集保留在同一行,避免旧调用方(如已部署脚本)因删字段而失效。