184 lines
12 KiB
Markdown
184 lines
12 KiB
Markdown
# Phase 3D 实盘交易集成设计(miniQMT bridge 架构)
|
||
|
||
> 日期:2026-07-10 | 状态:设计中(网络层已完成,bridge/编排待开发)
|
||
> 前序:Phase 3C 模拟盘(PaperEngine 双源+双层记账,commit 1646903/0656108 已完成)
|
||
> 关联:[[khquant-analysis]](xtquant 参考)、vps-access skill、`docs/data-platform/daily-update-design.md`
|
||
|
||
---
|
||
|
||
## 1. 背景与目标
|
||
|
||
C 期模拟盘已端到端跑通(PaperEngine:raw/qfq 双源 + 总账/分户双层记账 + 软限额 + 占用成本 + 分红送股)。D 期目标:**接入实盘**,实现「模拟→实盘」同引擎切换。
|
||
|
||
核心约束(决定架构):
|
||
- **miniQMT 仅 Windows 桌面**,必须登录常驻,提供 `xtquant` Python API
|
||
- **sanguo 跑 NAS Linux Docker 容器**(`sanguo_vnpy_v2`)
|
||
- **Windows 与 NAS 在不同网络**(异地),需跨网打通
|
||
- 实走为**日线级**(每日 20:30 单根 bar 推进),对延迟不敏感
|
||
|
||
→ 结论:唯一可行路径是 **miniQMT(xtquant)**,PTrade/QMT 完整版封闭不可集成(详见 [[khquant-analysis]] 同源调研)。
|
||
|
||
---
|
||
|
||
## 2. 总体架构
|
||
|
||
```
|
||
[网络A · 局域网] [公网 VPS] [网络B · 异地]
|
||
43.133.235.218
|
||
NAS Docker ┌─ frps(:7000) Windows 机器
|
||
sanguo_vnpy_v2 ──HTTPS────────►│ Caddy(:443) ├ miniQMT 客户端(登录常驻)
|
||
live_orchestrator 下单/查询 │ bridge.mysanguo.top ├ bridge 服务(:8765) ← D期写
|
||
│ → 127.0.0.1:18765 │ ↓ xtquant 本地 IPC
|
||
└─ frps(:18765) ◄─frp隧道──── └ frpc(连 frps:7000)
|
||
```
|
||
|
||
下单链路(6 跳):
|
||
`sanguo(NAS) → 公网 → Caddy(VPS:443) → frps(18765) → frp隧道 → Windows frpc → bridge(:8765) → xtquant → miniQMT`
|
||
|
||
日线级单 bar 推进,延迟完全无感;高频不适用(非本项目场景)。
|
||
|
||
---
|
||
|
||
## 3. 网络层(已完成 ✅)
|
||
|
||
| 组件 | 配置 | 状态 |
|
||
|------|------|------|
|
||
| Windows frpc | `frp v0.69.1`,`frpc.toml`(serverAddr 43.133.235.218:7000 + token + qmt-bridge proxy 8765→18765)| ✅ 已连(VPS 18765 监听确认)|
|
||
| frps(VPS)| 无 allowPorts 限制 | ✅ |
|
||
| Caddy(VPS)| `bridge.mysanguo.top { reverse_proxy 127.0.0.1:18765 }` | ✅ validate + reload |
|
||
| DNS(NameSilo)| `bridge A 43.133.235.218` TTL 3600 | ✅ 生效 |
|
||
| HTTPS 证书 | Caddy 自动 ACME(TLS1.3)| ✅ |
|
||
| 全链路验证 | `curl https://bridge.mysanguo.top` → `502 server: Caddy` | ✅ 502=隧道通到 Windows(8765 待写)|
|
||
|
||
Windows frpc 开机自启:任务计划程序(`sanguo-frpc`,onstart + 失败重启)或启动文件夹,见 NAS `/volume1/stock/frp_windows/README.md`。
|
||
|
||
---
|
||
|
||
## 4. bridge 服务设计(Windows 端,D-1 待开发)
|
||
|
||
### 4.1 形态
|
||
- **FastAPI** HTTP 服务,监听 `127.0.0.1:8765`(仅本地,frpc 转发外部流量)
|
||
- 启动时初始化 `xtquant.XtQuantTrader`(连本地 miniQMT 客户端)+ `xtdata`(行情)
|
||
- 自启:任务计划程序(`sanguo-bridge`,onstart,依赖 miniQMT 客户端已登录)
|
||
|
||
### 4.2 接口(最小集,YAGNI)
|
||
|
||
| 方法 | 路径 | 入参 | 返回 | 说明 |
|
||
|------|------|------|------|------|
|
||
| GET | `/health` | — | `{status, miniqmt_connected}` | 健康检查(frpc/Caddy 探活)|
|
||
| POST | `/order` | `{code, action:buy/sell, price, volume, reason}` | `{order_id, ok}` | 下单(`xt_trader.order_stock`)|
|
||
| POST | `/cancel` | `{order_id}` | `{ok}` | 撤单 |
|
||
| GET | `/account` | — | `{cash, frozen, market_value, total}` | 资金(`xt_trader.query_stock_asset`)|
|
||
| GET | `/positions` | — | `[{code, volume, can_use, avg_price, ...}]` | 持仓(`xt_trader.query_stock_positions`)|
|
||
| GET | `/trades` | `?since=<ts>` | `[{code, action, price, volume, time}]` | 成交回报(账本同步用)|
|
||
|
||
> 股票代码格式:xtquant 用 `600000.SH` / `000001.SZ`(sanguo 内部 `sh600000`,bridge 做转换)。
|
||
|
||
### 4.3 xtquant 调用要点(参考 OSkhQuant 架构,不抄代码)
|
||
- `xt_trader = XtQuantTrader(path, session_id)`;`xt_trader.start()`;`connect()` 后 `subscribe(account)`
|
||
- 下单:`xt_trader.order_stock(account, code, order_type, volume, price_type, price, strategy_name, order_remark)`
|
||
- `price_type`:限价 `XT_PRICE_LIMITED` / 市价 `XT_PRICE_LATEST_PRICE` 等
|
||
- A 股 T+1:`query_stock_positions` 的 `can_use_volume` 即可卖量(buy 当日计 frozen)
|
||
- 行情:`xtdata.download_history_data` + `get_market_data_ex`(实盘 step 用实时,非历史)
|
||
- 回调:`xt_trader.register_callback` 异步接收成交通知
|
||
|
||
---
|
||
|
||
## 5. sanguo 端改造(D-3 待开发)
|
||
|
||
### 5.1 配置(config/data_platform.yaml 加)
|
||
```yaml
|
||
live:
|
||
bridge_url: https://bridge.mysanguo.top
|
||
bridge_token: ${BRIDGE_TOKEN} # 环境变量,不进 git
|
||
enabled: false # 总开关,模拟联调时再开
|
||
```
|
||
|
||
### 5.2 live_orchestrator 改造(`sanguo_trader/live_orchestrator.py`)
|
||
现状:`live_step` 恢复状态 → warmup → 当日 bar → `engine.step` → 存状态。`step` 返回 `(pending_new, closes)`。
|
||
|
||
D 期加「实盘执行分支」:当 `account.mode == 'live'` 且 `live.enabled`:
|
||
1. `step` 产生的**当日成交**(`closes`)→ 同步 POST `/order` 到 bridge(真实下单到 miniQMT)
|
||
2. 次日开盘前,从 bridge `GET /positions` `/account` 拉真实持仓/资金,**校正** account 账本(真实回报为准,纠模拟撮合漂移)
|
||
3. 鉴权:每个请求带 `X-Bridge-Token` header
|
||
|
||
### 5.3 模拟撮合 vs 实盘下单的关系(关键设计决策)
|
||
|
||
| 模式 | 说明 | D 期采用 |
|
||
|------|------|---------|
|
||
| **A 影子下单**(推荐先)| PaperEngine 照常模拟撮合(账本准),同时把信号 POST bridge「影子」下单到 miniQMT 模拟环境,**对比两者**验证一致性 | ✅ 联调期 |
|
||
| **B 实盘驱动** | 真实下单 + 成交回报驱动账本,PaperEngine 退化为信号生成器 | 切实盘后 |
|
||
|
||
→ 联调先用 A(模拟盘端到端,零资金风险),一致性验证后切实盘切 B。
|
||
|
||
---
|
||
|
||
## 6. 鉴权与安全(⚠️ bridge.mysanguo.top 已公网暴露)
|
||
|
||
**实测**:域名一上线即被扫描器(`81.171.74.60` 等)打 `/dump.sql` `/wp-config.php` `/secrets.json`。必须:
|
||
|
||
1. **共享密钥**:每个请求 header `X-Bridge-Token: <random>`,bridge 校验,不符 401。token 走环境变量(sanguo + Windows bridge 两端同值),**不进 git**
|
||
2. **最小接口**:只放 §4.2 的接口,不暴露 xtquant 全能力
|
||
3. **限速**:FastAPI middleware 限流(防爆破)
|
||
4. **可选 IP 白名单**:sanguo 经 VPS 反代,bridge 看到的源 IP 是 VPS(43.133.235.218)→ bridge 可加白名单只接受 frps 来源
|
||
5. **审计日志**:bridge 记录每笔下单(code/action/volume/price/来源 IP/时间),便于复盘异常
|
||
|
||
---
|
||
|
||
## 7. 端到端联调方案(模拟盘先行)
|
||
|
||
| 阶段 | 环境 | 资金风险 | 目标 |
|
||
|------|------|---------|------|
|
||
| D-4a | miniQMT **模拟客户端**(现已在跑)| 零 | bridge 端到端打通:sanguo 信号 → bridge → miniQMT 模拟下单 → 回报 |
|
||
| D-4b | 模拟客户端 + **影子对比** | 零 | PaperEngine 模拟撮合 vs bridge 真实下单,验证一致性(成交价/持仓/资金)|
|
||
| D-4c | **小资金实盘**(切实盘账户)| 低 | 真金白银小单验证,切换模式 B |
|
||
| D-4d | 正式实盘 | 正常 | 纳入每日 20:30 scheduler |
|
||
|
||
---
|
||
|
||
## 8. 任务拆分(D 期工作清单)
|
||
|
||
| 编号 | 任务 | 端 | 状态 |
|
||
|------|------|-----|------|
|
||
| D-1 | bridge MVP(health/order/account/positions + 鉴权)| Windows | ✅ 代码 `eff9ed2` + 公网实测(health/account/positions/order 端到端 200)|
|
||
| D-2 | bridge 自启 + frpc 自启 + 稳定性 + 半自动更新 | Windows | ✅ 自启(启动文件夹)+ bridge 完善 `cadc59e`(自动重连 miniQMT + /health 真实探活 + 交易日判断)+ 半自动更新(`update.bat` `b25b1e0` + sparse clone,见 windows-bridge-setup.md `8f51b02`/`aef4612`)|
|
||
| D-3 | sanguo 影子下单分支(bridge_client + 幂等)| NAS | ✅ 代码 `ff84b3d` + 持久测试 11 + mock bridge 4(`38f5635`/`2393097`)|
|
||
| D-4a | 端到端影子下单(真 bridge)| 两端 | ✅ 注入成交 → 自动影子 → 真 bridge → miniQMT 报单 order_id 1090519054/1090519055 + 幂等验证 |
|
||
| D-4b | 模拟撮合 vs 实盘成交价一致性 | 两端 | ⏳ 周一交易日(5 次试单确认 miniQMT `[120141][证券交易未初始化]`:交易日才初始化交易通道 + 行情站点周末关 → 无法成交,等周一)|
|
||
| D-4c | 模式 B(bridge 回报驱动账本)| 两端 | ✅ 代码 `e77c9df` + test_reconcile 10 + 真桥验证(reconcile 读 bridge → 校正 account 1000万/空 + 持久化)|
|
||
| D-5 | 文档/验收/部署 | — | ✅ 设计 §8 + Windows 部署清单 + bridge 部署/半自动更新(windows-bridge-setup.md)+ Issue #4 进度(8 条 comment)|
|
||
|
||
> **验证总账**(不依赖周一的,全过):D-1 公网实测 / D-3 持久测试 + NAS 环境 108 passed / D-4a 端到端影子(真 bridge order_id)/ D-4c 模式 B reconcile(真桥账本校正)/ D-2 bridge 完善(探活 + 容错在 miniQMT 行情关场景验证生效)/ D-5 文档。
|
||
> **D-4b 等周一**:miniQMT 行情站点开 + 交易日初始化(120141 消失)→ scheduler 20:30 触发 live_step(开 enabled + mode_b + token),策略信号 → 模拟撮合 + bridge 真实成交 → 对比 paper_trades.price vs bridge /positions avg_price。
|
||
|
||
### 运维发现(D 期联调实测,Issue #4 comment #1127/#1128)
|
||
|
||
1. **miniQMT `[120141][证券交易未初始化]`**:miniQMT 证券交易初始化**只在交易日做**(init_date 同步当日)。非交易日(周末/节假日)+ 行情站点关 → 报单必 120141。scheduler 应只在交易日 20:30 触发实盘下单。
|
||
2. **miniQMT 行情站点周末维护关闭**:周末 bridge 连不上 miniQMT(`miniqmt_connected:false`)。/health 真实探活如实反映(验证 D-2 探活生效,旧版会假阳性 true)。
|
||
3. **bridge 不自动重连 miniQMT**(已修复 `cadc59e`):miniQMT 重启后旧连接失效,新版 `_retry_with_reconnect` 自动重连重试。
|
||
4. **token 分离(⚠️ 切实盘前必办)**:当前 gitea access token 混做 BRIDGE_TOKEN(测试阶段图省事)。bridge.mysanguo.top 公网每请求传 token,暴露面 > gitea token 只在本地 clone URL。**切实盘前分离**:BRIDGE_TOKEN 用独立 `secrets.token_urlsafe(32)`,gitea token 只 clone。
|
||
|
||
---
|
||
|
||
## 9. 风险与兜底
|
||
|
||
| 风险 | 影响 | 兜底 |
|
||
|------|------|------|
|
||
| Windows/miniQMT/frpc/bridge 四常驻,任一断 | 下单链路断 | 日线级 → 「断线次日补」+ bridge `/health` 探活 + scheduler 重试 |
|
||
| VPS 单点 | 全链路断 | 接受(日线级);备选 Tailscale 直连绕 VPS |
|
||
| bridge token 泄露 | 任意人可下单 | 环境变量 + 不 commit + 审计日志 + 限速 |
|
||
| miniQMT 停新申请(2026/7/6)| 新账户无法开 | 老账户可用;新账户换其他提供 miniQMT 券商(华泰/中泰/国信)|
|
||
| 模拟撮合与实盘成交价漂移 | 账本不准 | 模式 B 以 bridge 回报为准校正 |
|
||
| 公网扫描/攻击 | bridge 被打 | §6 鉴权 + 最小接口 + 限速 |
|
||
|
||
---
|
||
|
||
## 10. 相关
|
||
|
||
- 源码参考:`/volume1/KnowledgeBase/github-repos/OSkhQuant`(xtquant 调用链路,CC BY-NC 仅参考架构)
|
||
- [[khquant-analysis]] wiki
|
||
- [[vps-deployment]] wiki(FRP/Caddy 基建)
|
||
- vps-access skill
|
||
- 前序:`docs/superpowers/specs/2026-07-07-phase3c-paper-trading-design.md`
|
||
- 网络层落地:NAS `/volume1/stock/frp_windows/`(frpc + README)
|