Files
sanguo_vnpy_v2/docs/superpowers/specs/2026-07-07-phase3b-vue-frontend-design.md
T
claude_dev f0f08d32c3 docs(phase3b): 投研+回测 Web 控制台(Vue 前端)设计文档
- 4 期愿景:投研→回测→模拟→实盘(国金QMT),本期 B=投研+回测
- 对齐 vnpy client 回测模块 + 投研自有
- 技术栈 Vue3+Vite+TS+ElementPlus+ECharts+Pinia
- 部署:8000 切 sanguo_api,Vue 静态挂 FastAPI,不动端口/反代
- 含后端补 5 类接口(资金曲线/每日盈亏/成交/K线/报告)
- 4 切片 S0→S1→S2→S3
2026-07-07 00:25:31 +08:00

280 lines
14 KiB
Markdown
Raw 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.
# Phase 3b:投研 + 回测 Web 控制台(Vue 前端)设计
> 日期:2026-07-07
> 阶段:Phase 3bB 期)
> 状态:设计待审阅
> 维护:Main Agent
---
## 1. 背景与目标
已交付:
- Phase 1 数据层(A 股 K 线 / SQLite 读取)
- Phase 2 因子 + 回测引擎(`sanguo_factor` / `sanguo_backtest`,真数据跑通)
- Phase 3a 研究 API`sanguo_api`JWT / 异步任务 / WebSocket / 结果查询),本机 + 容器 pytest 通过
两个缺口:
1. **没有前端**——只有 API,用户无法在网页上操作。
2. **`sanguo_api` 未挂公网**——实机查证:公网 `vnpy.mysanguo.top` → 容器:8000 现在跑的是**旧 `sanguo_web`(实盘交易 API,44 路由)**,没有回测/因子接口;Phase 3a 的 `sanguo_api` 只在容器里 pytest 跑过。
**本期目标**:建一个 Vue 前端控制台,对齐 vnpy 桌面 client 的**回测模块**功能 + 投研(因子)自有模块,并把 `sanguo_api` 切到公网 8000,使整条链路从 `vnpy.mysanguo.top` 可用。
---
## 2. 范围
**完整愿景(用户确认,4 期递进)**:投研 → 回测 → 模拟 → 实盘(实盘最后,走**国金证券 QMT** / xtquant)。
**本期 B= B1)范围**
| 类别 | 内容 |
|---|---|
| ✅ 投研 | 因子分析(多标的 / 多因子 / 日期)→ IC 表 + tears 报告 |
| ✅ 回测 | CTA 策略回测(对齐 vnpy client 回测模块:统计全表 / 资金曲线 / 每日盈亏 / 成交记录 / K线+买卖点)+ 参数优化 |
| ✅ 前端 | Vue 3 SPA |
| ✅ 后端补 | 5 类新接口 + 现有接口扩展 |
| ✅ 部署 | 切 `sanguo_api` 到 8000Vue 静态挂 FastAPI |
**不在本期(out of scope**
- ❌ 模拟盘(C 期,后端模拟引擎尚未建)
- ❌ 实盘交易(D 期,国金 QMT;旧 `sanguo_web` 交易路由本期下线,D 期合并回来)
- 导航**预留 4 入口**,模拟/实盘灰显"敬请期待",避免日后重写布局。
---
## 3. 整体架构
```
浏览器 (Vue 3 SPA)
↕ HTTPS vnpy.mysanguo.top ← 外网链路不动(frpc/socat/Caddy 不碰)
FastAPI sanguo_api (容器:8000,从 sanguo_web 切过来)
├─ / → Vue 静态文件 (StaticFilesSPA history fallback)
├─ /api/v1/* → 研究 APIauth / backtest / factor / task / ws
└─ 调后端引擎 → sanguo_backtest / sanguo_factor / sanguo_data
SQLite + A 股 K 线 (NAS /volume1/stock)
```
---
## 4. 前端技术栈
| 层 | 选型 | 备注 |
|---|---|---|
| 框架 | Vue 3 + `<script setup>` + Composition API | 用户指定 Vue |
| 语言 | TypeScript | 控制台体量需要,利维护 |
| 构建 | Vite | 快、标准 |
| UI 库 | Element Plus | 中文量化圈最常用,表格/表单/弹窗齐全 |
| 图表 | ECharts | K线 candlestick + markPoint(买卖点)/ 折线(资金曲线)/ 柱状(每日盈亏)/ 热力图(优化)|
| 状态 | Pinia | Vue 3 标准 |
| 路由 | Vue Router | 标准 |
| HTTP | Axios + JWT 拦截器 | 自动附 Authorization401 回登录 |
| 实时 | 原生 WebSocket | 对接已有 `/api/v1/ws/task/{id}` |
**前端代码目录**:新建 `frontend/`(仓库根),与 Python 包并列。`npm run build` 产物输出到 FastAPI 可挂载的静态目录。
---
## 5. 部署方案(守住红线)
**红线**(用户多次强调):
- 不改容器端口(8000 不变)
- 不动 `vnpy.mysanguo.top` 反向代理 / 转发
- 不碰 frpc / socat / Caddy
**本期改动(只动 NAS 容器内部)**
1. 容器 uvicorn 目标:`sanguo_web.api:app``sanguo_api.app:create_app`(用 `--factory`,传 db_path / file_dir / auth_config / max_workers
- 入口脚本:`docker/entrypoint.sh:283`(改 uvicorn 目标)
2. Vue 打包静态 → FastAPI `StaticFiles(directory=..., html=True)` 挂在 `/`,配 SPA history fallbackcatch-all 回 `index.html`
3. 开发期:本地 Vite dev server5173+ `vite.config.ts` proxy `/api``/ws` → 容器/本地 FastAPI
**部署流程**(沿用项目约定):本机改代码 → rsync 到 NAS 安装目录 → `docker restart sanguo_vnpy_v2`
> 已知问题:本 session rsync/scp 到 NAS 不稳(status 43 / Connection closed)。临时用 `ssh sanguo-nas "cat > /path" < local` 重定向;排期修 sftp 子系统。
---
## 6. 页面设计
### 6.1 页面地图
```
登录页 /login
└ 主控制台(左侧栏 4 入口)
├ 回测 ✅ (S1 / S3)
│ ├ 新建回测 /backtest/new
│ ├ 任务进度 /backtest/task/:id WS 实时阶段)
│ ├ 结果页 /backtest/result/:id (统计/曲线/盈亏/成交/K线买卖点)
│ ├ 参数优化 /backtest/optimize (S3)
│ └ 历史任务 /backtest/history (S3)
├ 投研 ✅ (S2)
│ ├ 新建因子分析 /factor/new
│ └ 结果页 /factor/result/:id IC 表 / tears 报告)
├ 模拟 ⬜ 敬请期待(C 期)
└ 实盘 ⬜ 敬请期待(D 期 · 国金 QMT)
```
### 6.2 页面详情
**登录页**:用户名 + 密码 → `POST /api/v1/auth/login` → 存 JWTlocalStorage)→ 跳主控制台。
**主控制台 shell**:顶栏(系统名 / 用户 / 登出)+ 左侧栏 4 入口(回测/投研点亮,模拟/实盘灰显)+ `<router-view>`
**回测-新建**
- 策略下拉(`GET /strategy/list`)→ 选中后按 `GET /strategy/{name}/params` 渲染动态参数表单
- 标的输入(如 600000)+ 日期区间 +(S3)费率/滑点/资金
- 提交 → `POST /api/v1/backtest/cta` → 拿 task_id → 跳进度页
**回测-进度**`GET /task/{id}` + `WS /ws/task/{id}`,显示状态(pending/running/done/failed+ 中文阶段("排队中/回测中/完成")。done → 跳结果页。
**回测-结果**(对齐 vnpy client 回测模块):
- 统计全表(sharpe / total_return / max_drawdown / win_rate / …,来自 `GET /task/{id}/result`
- 资金曲线(`GET /task/{id}/equity-curve` → ECharts 折线)
- 每日盈亏(`GET /task/{id}/daily-pnl` → ECharts 柱状)
- 成交记录表(`GET /task/{id}/trades` → Element Table
- K线 + 买卖点(`GET /kline?symbol&start&end` + 成交点 → ECharts candlestick + markPoint
**回测-优化**S3):策略 + 参数网格 → `POST /api/v1/backtest/optimize` → 结果表 + 热力图(`GET /task/{id}/optimization-results`)。
**回测-历史**S3):`GET /task?type=cta` → 任务列表,可点回看结果。
**投研-新建**:因子下拉(`GET /factor/list`,如 ma5/ma10/ma20/vol_ma5+ 多标的(多选,如 600000/000001/300750+ 日期 → `POST /api/v1/factor/analyze` → 进度。
**投研-结果**
- IC 表(`GET /task/{id}/ic-summary`:各周期 mean/std/icir/t_stat/count
- tears 报告内嵌(`GET /task/{id}/report/{factor}` 返回 HTML → iframe
---
## 7. 核心流程
### 7.1 回测流程
选策略(DoubleMaStrategy)→ 填参数(fast_window/slow_window)→ 选标的(600000+ 日期 → 提交 → 看进度"回测中" → 完成 → 结果页:统计全表 / 资金曲线 / 每日盈亏 / 成交表 / K线带买卖箭头。**体感对齐 vnpy client 回测模块。**
### 7.2 因子分析流程
选因子(ma5+ 多标的(600000/000001/300750alphalens 横截面需 ≥2)+ 日期 → 提交 → 进度 → 结果页:IC 表(1D/5D/10D mean/icir/t_stat+ tears 报告。
---
## 8. 后端 API
### 8.1 现有(Phase 3a,复用)
| 方法 | 路径 | 用途 |
|---|---|---|
| POST | `/api/v1/auth/login` | 登录取 JWT |
| POST | `/api/v1/backtest/cta` | 提交 CTA 回测 → task_id |
| POST | `/api/v1/backtest/optimize` | 提交参数优化 → task_id |
| POST | `/api/v1/factor/analyze` | 提交因子分析 → task_id |
| GET | `/api/v1/task/{id}` | 任务状态 + 阶段 |
| GET | `/api/v1/task/{id}/result` | 统计 statistics |
| WS | `/api/v1/ws/task/{id}?token=` | 实时阶段推送 |
### 8.2 本期新增(按切片)
| 切片 | 方法 | 路径 | 返回 | 说明 |
|---|---|---|---|---|
| S1 | GET | `/api/v1/strategy/list` | `[{name, class_name}]` | 枚举 vnpy_ctastrategy 可用策略 |
| S1 | GET | `/api/v1/strategy/{name}/params` | `{parameters:[...], defaults:{}}` | 读策略类 `.parameters` 渲染表单 |
| S1 | GET | `/api/v1/task/{id}/equity-curve` | `[{date, balance}]` | 暴露 BacktestResult.equity_curve |
| S1 | GET | `/api/v1/task/{id}/daily-pnl` | `[{date, pnl}]` | 每日盈亏 |
| S1 | GET | `/api/v1/task/{id}/trades` | `[{datetime, direction, offset, price, volume}]` | cta_engine 需实现成交记录(现为 None)|
| S1 | GET | `/api/v1/kline?symbol&start&end` | `[{datetime, open, high, low, close, volume}]` | 历史 K 线(读 A 股 DB;评估能否复用旧 sanguo_web `/market/kline`|
| S2 | GET | `/api/v1/factor/list` | `[{name, desc}]` | 枚举已注册因子(ma5/ma10/ma20/vol_ma5|
| S2 | GET | `/api/v1/task/{id}/ic-summary` | `{factor:{periodD:{mean,std,icir,t_stat,count}}}` | 暴露 FactorReport.ic_summary |
| S2 | GET | `/api/v1/task/{id}/report/{factor}` | HTML | tears 报告服务(StaticFiles 或 FileResponse|
| S3 | 扩展 | `POST /api/v1/backtest/cta` | — | schema 加 rate/slippage/capital 字段;cta_engine 接收 |
| S3 | GET | `/api/v1/task/{id}/optimization-results` | `[{params, statistics}]` | 优化结果结构化 |
| S3 | GET | `/api/v1/task?type=&status=` | `[task 摘要]` | 任务历史列表 |
---
## 9. 数据契约
### 9.1 BacktestResult(现有,`sanguo_backtest/result_store.py`
`task_id, type, status, strategy, symbol, params, start, end, statistics, equity_curve, trades, error_msg`
### 9.2 新增返回结构
- **equity-curve**`[{date: "YYYY-MM-DD", balance: number}]`
- **daily-pnl**`[{date, pnl: number}]`
- **trades**`[{datetime, direction: "多/空", offset: "开/平", price, volume, commission, ...}]`(对齐 vnpy TradeData
- **kline**`[{datetime, open, high, low, close, volume}]`
- **ic-summary**`{factor: {"1D"|"5D"|"10D": {mean, std, icir, t_stat, count}}}`
- **optimization-results**`[{params: {...}, statistics: {...}}]`
所有接口返回 JSON 安全值(Timestamp→str,已在 cta_engine statistics 处理过同样问题)。
---
## 10. 切片交付计划
每片独立可演示、可验收。S1 最重(vnpy client 对齐主战场)。
### S0 脚手架
- **前端**Vite + Vue3 + TS + Element Plus + ECharts + Pinia + Router + Axios 项目骨架;登录页 + JWT 拦截器;4 入口侧栏 shell(回测/投研点亮,模拟/实盘灰显);路由 + history fallback
- **后端**:容器 uvicorn 切 `sanguo_api`FastAPI 挂 SPA 静态
- **验收**:从 vnpy.mysanguo.top 能登录、看到空壳控制台
### S1 回测核心(对齐 vnpy client 回测)
- **前端**:新建回测 / 进度 / 结果页(统计全表 + 资金曲线 + 每日盈亏 + 成交表 + K线买卖点)
- **后端**`strategy/list``strategy/{name}/params``task/{id}/equity-curve``/daily-pnl``/trades``/kline`cta_engine 实现成交记录
- **验收**:跑 DoubleMaStrategy on 600000,结果页与 vnpy client 回测模块一致
### S2 投研核心
- **前端**:新建因子分析 / 结果页(IC 表 + tears 报告内嵌)
- **后端**`factor/list``task/{id}/ic-summary``task/{id}/report/{factor}`
- **验收**:跑 ma5(多标的),看 IC 表 + tears 报告
### S3 优化 + 收尾
- **前端**:参数优化(热力图)/ 历史任务 / 回测费率·滑点·资金可调
- **后端**`backtest/cta` 加参数;`optimization-results``GET /task` 列表
- **验收**:跑优化看热力图、查历史、费率可调
---
## 11. 非功能
- **安全**JWT(已有);SPA 用 localStorage 存 tokenAxios 拦截器附 `Authorization: Bearer`401 → 清 token 回登录;HTTPS 由外网链路保证
- **错误处理**API 错误统一 Element Plus `ElMessage`;任务 failed 展示 `error_msg`
- **测试**
- 前端:Vitest + Vue Test Utils(工具函数 / 关键组件)
- 后端:pytest(新接口单测 + 复用现有容器冒烟模式)
- 容器:`scripts/smoke_phase3b.py`(端到端:登录 → 提交回测 → WS 进度 → 结果页接口齐)
- **代码风格**:前端遵循 ECC coding-style(小文件、不可变、早返回、命名);后端沿用现有 sanguo_* 风格
---
## 12. 风险与约束
| 风险 / 约束 | 处理 |
|---|---|
| 切 8000 到 sanguo_api 会下线旧交易路由 | 已确认(A 方案);D 期合并回来 |
| 两套 auth 都占 `/api/v1/auth/login` | 本期只用 sanguo_api JWTsanguo_web 下线,无冲突 |
| rsync/scp 到 NAS 不稳 | ssh-exec 重定向;排期修 sftp 子系统 |
| 容器 Python 3.10 vs 本机 3.14 | 前端 Node 工具链独立;后端接口在容器测(沿用 Phase 3a 模式)|
| vnpy 零修改原则 | 不改 `vnpy_v4.4.0/`;策略/参数从类属性读 |
| NAS CPU 弱(J4125 无 AVX2| 已有 `POLARS_SKIP_CPU_CHECK`;前端构建在 Mac,产物部署 |
---
## 13. 未来(C / D 期,预留)
- **C 模拟盘**:新建模拟引擎(forward 纸面交易)+ 任务类型 `paper`;前端点亮"模拟"入口
- **D 实盘**:合并 `sanguo_web` 交易路由(需统一 auth,解决 `/api/v1/auth/login` 冲突)+ 接国金 QMTxtquant);前端点亮"实盘"入口
- 导航骨架已预留,C/D 无需重写布局
---
## 14. 开放项(实现阶段确认)
- `/kline` 是否复用旧 `sanguo_web``/api/v1/market/kline`(依赖行情网关 vs 历史 DB)—— S1 评估
- token 存 localStorage(简便)vs httpOnly cookie(更安全)—— S0 默认 localStorage,可调
- 策略参数表单的复杂参数类型(范围/枚举)支持深度 —— S1 按需
---
## 参考文档
- Phase 3a 设计:`docs/superpowers/specs/2026-07-06-phase3a-web-api-design.md`
- 部署实况:`docs/deployment/nas-deploy-plan.md`
- 旧 Web 部署设计:`docs/design/deployment/docker-web-deployment.md`