Files
stock/TECH_STACK.md
2026-08-07 16:08:34 +08:00

188 lines
15 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.
# 股市回测平台 — 技术选型推荐(纯回测范围)
> **一句话总体推荐****Python 单语言后端**FastAPI + 自研回测引擎)为"大脑与事实源"**Vue 单页前端**为"渲染器与控制台"**PostgreSQL/TimescaleDB + Redis** 承载数据,三者用 **OpenAPI 契约**解耦。
>
> **范围明确**:本平台**只做历史回测 + 回放式模拟交易,不做实盘**。因此砍掉了所有实盘专属基建券商网关、Windows broker、程序化交易报备、限速、Kill Switch、talipp 流式指标等)——这些正是最难维护、风险最高的部分。
>
> 核心判断:**A 股的量化生态(数据源、回测库)几乎只以 Python 存在**——"后端选 Python"是生态约束下的唯一合理解。
---
## 范围变更记录2026-08
原方案含实盘量化。经确认**只做回测 + 回放式模拟,不做实盘**后,移除:
| 移除项 | 原因 |
|---|---|
| vnpy / xtquant / xttrader 实盘网关 | 实盘下单专用,无实盘即不需要 |
| **Windows broker 节点(永久运维分叉)** | QMT 必须常驻 Windows无实盘 → 纯 Linux部署统一 |
| 程序化交易报备 / 硬限速≤299笔/秒) | 只对实盘程序化交易生效,纯回测不受管 |
| Kill Switch / 风控闸门 / 幂等下单 / 断线重连 | 全是"防回测 bug 造成真实亏损"的护栏 |
| talipp 流式增量指标 | 实盘每根新K线增量算用回测批量算用 TA-Lib/自研即可 |
| CTP期货、券商资质、投资者适当性 | 实盘门槛 |
**保留并强化的核心**单一回测引擎fast/strict、防过拟合体检、基准归因、复权因子管道、A股交易成本建模、指标单一事实源。
**澄清**:最早的"对接交易所显示买卖点"——**不需要真连交易所**。回测信号标在历史 K 线上即是买卖点显示。
---
## 一、技术栈总表
| 层 | 选型 | 作用 | 说明 |
|---|---|---|---|
| **前端基座** | Vue 3.5 + Vite + TypeScript + Pinia | SPA、状态管理 | 用户已有 Vue 生态 |
| **UI 组件** | **PrimeVue 5** | 表单/参数面板/大表/筛选 | DataTable 成熟度对数据密集控制台是决定性的 |
| **K 线主图** | **lightweight-charts 5.x** | 纯渲染器:主图 + 指标副图 + `createSeriesMarkers` 标买卖点 | TradingView 出品;不用任何内置指标算法(单一事实源) |
| **分析面板** | ECharts 6.1 + vue-echarts | 净值/回撤/收益分布/热力图 | WebGL 大数据 |
| **前端指标预览** | 防抖调后端算 | 单一指标实现 | 前端不保留任何指标库 |
| **后端服务** | FastAPI + Uvicorn + Pydantic v2 | REST + 自动 OpenAPI 契约 | 契约先于业务锁定 |
| **回测引擎(单一)** | **自研Polars/Numpy 向量化内核 + 事件化规则注入** | 唯一事实源fast/strict 两档 | 不做"快层+真层"双引擎 |
| **指标计算** | 纯 pandas/numpy 实现MVP→ TA-Lib生产 | 回测/图表共享同一份结果 | Windows 上 TA-Lib C 库难装MVP 用纯 Python接口留好可替换 |
| **任务编排** | MVP 同步;长回测引入 Dramatiq + 进程池 | 绕 GIL多进程并行参数扫描 | 进度落库 checkpoint |
| **元数据库** | PostgreSQL 16/17 + async SQLAlchemy 2.0 + Alembic | 用户/策略/回测元数据/回测运行注册表 | — |
| **时序主库** | **TimescaleDB 2.28+**(同一 PG 实例的扩展) | K 线 Hypertable + Continuous Aggregates 多周期 + 列式压缩 | 用户已有 Postgres → 直接装扩展即可MVP 暂用 SQLite 零配置起步 |
| **缓存** | Redis规模化后 | 热点 K 线缓存、任务队列 broker | MVP 不引入 |
| **交易日历** | exchange_calendars`XSHG`+ tushare `trade_cal` 兜底 | 回测/回放对齐、版本化 | `XSHG` 覆盖截至 20252026+ 需兜底 |
| **A股数据源** | Tushare Pro+ AKShare校验+ BaoStock末位 | 历史 K 线/复权/财务/分红 | 多源冗余2025-08 Tushare 曾停摆 |
| **MVP 数据** | 合成数据种子(随机游走 OHLCV | 零依赖即时可跑 | DataProvider 接口下可一行切到 Tushare |
| **港美股数据** | Polygon更名 Massive付费档 | 历史+实时(远期) | 仅开发期 mock 用免费源 |
| **鉴权** | JWT + RBAC多用户时 | 用户/策略级权限 | MVP 单用户可暂缓 |
---
## 二、系统架构
```
┌──────────────────────────────────────────────────────────────────┐
│ 前端 (Vue 3.5 + Vite + TS + Pinia + PrimeVue) │
│ ┌────────────┐ ┌──────────────────┐ ┌────────────────────────┐ │
│ │ PrimeVue 5 │ │ lightweight- │ │ ECharts 6.1 │ │
│ │ 参数表单 │ │ charts 5.x │ │ 净值/回撤/归因/过拟合 │ │
│ │ 策略选择 │ │ K线+指标副图+ │ │ │ │
│ │ │ │ 买卖点markers │ │ │ │
│ └────────────┘ └──────────────────┘ └────────────────────────┘ │
│ shallowRef+markRaw; series 不入响应式; onMounted/onBeforeUnmount │
└──────────────┬───────────────────────────────────────────────────┘
│ REST类型化客户端由 OpenAPI 生成)
┌──────────────────────────────────────────────────────────────────┐
│ 后端 (FastAPI + Uvicorn + Pydantic v2) [纯 Linux] │
│ ┌────────────┐ ┌──────────────────────┐ ┌────────────────────┐ │
│ │ REST │ │ DataProvider 适配器 │ │ 领域模型契约 │ │
│ │ OpenAPI 契约│ │ Tushare/AKShare/ │ │ Instrument/Bar/ │ │
│ │ │ │ Synthetic/复权管道 │ │ Signal/Order/Fill/ │ │
│ │ │ │ │ │ Position/Portfolio/ │ │
│ │ │ │ │ │ Strategy/Universe/ │ │
│ │ │ │ │ │ Calendar │ │
│ └────────────┘ └──────────────────────┘ └────────────────────┘ │
│ │ ┌─────────────────────────────────────────────────┐ │
│ │ │ 单一回测引擎 (Numpy/Polars + 规则注入) │ │
│ │ │ ├ fast 档: 关 T+1/费用, 交互试探 │ │
│ │ │ └ strict档: T+1/涨跌停/封板/成交量约束/全费用 │ │
│ │ │ + 防过拟合体检(walk-fwd/OOS/FDR/敏感性) │ │
│ │ │ + 基准归因(超额/信息比率/beta/alpha) │ │
│ │ │ + 回测运行注册表(run_id→策略版本+参数+数据快照) │ │
│ │ └─────────────────────────────────────────────────┘ │
└────────┼─────────────────────────────────────────────────────────┘
┌───────────────────┐ ┌──────────────────────┐
│ PostgreSQL 16/17 │ │ DataProvider 数据源 │
│ + TimescaleDB │ │ Tushare(主)/AKShare │
│ K线 Hypertable │ │ BaoStock(末位) │
│ CAGG 多周期 │ │ Synthetic(MVP) │
│ + 关系/元数据 │ │ Polygon(港美股,远期) │
└───────────────────┘ └──────────────────────┘
```
### 三个必须分离的关注点
| 关注点 | 落在哪 | 为什么 |
|---|---|---|
| 信号生成(指标+策略) | Python 后端,单一实现 | 回测与图表必须用同一份结果,否则"看着赚回测亏" |
| 订单执行(撮合) | PaperBroker虚拟成交 | 隔离策略逻辑与成交逻辑;无实盘则永远是虚拟 |
| 数据获取 | DataProvider 适配器 + 复权管道 | 上游随时失效,必须可热切换 |
### 先于业务落地的"领域模型契约"MVP 第一周定稿)
`Instrument` / `Bar`(OHLCV+复权标识+周期) / `Signal` / `Order` / `Fill`(含费用明细) / `Position` / `Portfolio` / `Strategy`(+版本) / `Universe`(股票池+成分历史) / `TradingCalendar`
---
## 三、关键取舍裁决
1. **纯 Python 单语言栈。** A 股数据源与回测生态只以 Python 存在;性能瓶颈在向量化计算与多进程,不在 HTTP 层。
2. **数据库TimescaleDB 单库起步。** 它是 Postgres 扩展(用户已有 Postgres 可直接装),同一库内"信号 JOIN 行情 JOIN 订单"+ ACID。**分钟级全市场**≈十亿行确定要做时再把分钟K/Tick 下沉 ClickHouse 分层关系层与日K 留 PG。
3. **K 线主图用 lightweight-charts 5.x纯渲染器** 不用任何内置指标算法;指标值全部后端算好喂给它。不用 klinecharts内置指标会与回测两套算法漂移
4. **决策级指标全在后端 Python。** 前端预览一律调后端,前端不保留指标库实现。
5. **单一回测引擎 + 质量档位fast/strict**,不做双引擎。同一撮合逻辑、同一代码路径,仅开关不同:
- `fast`:关 T+1/费用/成交量约束,纯向量化,交互试探、参数网格。
- `strict`:全开 A 股规则,出可审计报告。
> vectorbt **开源版基于 pandas/NumPy不支持 Polars**Polars 属闭源付费 PRO。向量化内核自研Polars/Numba
---
## 四、A股交易成本表已修正可配置 + 按生效日期版本化,基准日 2026-08
| 费用项 | 费率 | 方向 | 生效依据 |
|---|---|---|---|
| 印花税 | **0.05%(千分之零点五)** | **单边卖出** | 2023-08-28 减半(原 0.1% |
| 过户费 | **0.001%(万分之零点一)** | **沪深双边均收** | 2022 年统一下调(原沪市万 0.2 单边) |
| 佣金 | **万 1 含规费**(最低 5 元) | 双边 | 2026 主流;最低 5 元须建模 |
| 滑点 | 1-2 tick | 双边 | 可配置 |
> 费用必须是**参数表 + 生效日期版本化 + 显式基准日**,非硬编码常量。
---
## 五、分阶段落地路线
### 阶段 0回测 MVP + 可视化(进行中)
跑通"输入 MACD/RSI/KDJ 参数 → 后端回测 → 画 K线+指标+收益+最大回撤+夏普+买卖点"。SQLite 默认库 + 合成数据零依赖可跑。**不引入**Redis、Dramatiq、任何行情/交易网关、K8s。
### 阶段 1完整回测 + 回放式模拟
- strict 档完整性T+1、涨跌停主板±10%/科创创业±20%/北交所±30%)、**成交量约束**(单笔 ≤ bar 成交量 10-25%)、**封板建模**(一字板不可买/不可卖、停牌事件流、100 股整数手、全费用、滑点。
- **股票池 + 成分历史**(生存者偏差):用"当时成分股"而非"今天成分股"。
- **防过拟合体检**回测报告一等公民walk-forward、OOS 切分、参数敏感性、多重比较修正Bonferroni/FDR/White's Reality Check/SPA、样本自由度告警。
- **基准归因**超额收益、信息比率、跟踪误差、beta/alpha、up/down capture。
- **回测运行注册表**`run_id → 策略版本 + 参数快照 + 数据快照 + 环境指纹 + 结果指纹`
- **结果缓存 + 多回测对比**:相同三元组命中缓存;参数微调前后 diff 视图。
- 切真实数据源Tushare 主 / AKShare 校验),全量本地落地缓存;**复权因子管道**(增量 + 回溯回填)。
- 切到用户 Postgres + TimescaleDBhypertable + CAGG
- 回放式模拟盘:选历史区间逐 bar 虚拟交易PaperBroker
### 阶段 2分钟级 + 规模化 + 工程化
- 分钟级全市场回测(≈十亿行):按需引入 ClickHouse 分层分钟K/Tick关系层与日K 留 PG。
- Dramatiq + 进程池跑长回测/参数扫描,进度落库 checkpoint。
- 可观测:结构化日志 + 核心 metric回测耗时 P95、数据延迟→ OpenTelemetry + Grafana。
- K8s + ArgoCD 部署。
---
## 六、关键风险与对策
### 6.1 数据正确性
- **A股复权是最大隐患**:复权因子是每日增量、且会回溯修正的流。维护复权因子管道,查询显式选择前/后复权,否则回测收益与图表价格不一致。
- **生存者偏差**用当时成分股回测Tushare 为主、AKShare 校验,差异超阈值告警。
- **单点数据源风险已验证**2025-08-26 TusharePro 停运,仅依赖 Tushare 的系统当天停摆 → 强制多源 + 本地落地缓存。
- **数据治理**新鲜度监控、质量校验OHLC 不合理/成交量为负/缺口)、数据血缘。
### 6.2 性能瓶颈
- **最致命陷阱:把大数据塞进 Pinia reactive**。必须 `shallowRef + markRaw` + 仅加载可见区间按 pan/zoom 增量拉取;**series 数据不入响应式**;图表实例 onMounted/onBeforeUnmount 严格绑定。
- **GIL 误用**CPU 密集回测走独立进程池FastAPI 路由只 dispatch。
- **十亿级撑爆内存**:谓词下推按 symbol+区间载入;前端服务端聚合/降采样再渲染。
- **TimescaleDB**chunk 对齐查询模式CAGG 刷新滞后读防护(`materialized_only` + 时间戳护栏);并发读副本/连接池。
### 6.3 可维护性
- **避免停维库**backtrader 自 2023 停维、pandas-ta 停滞。指标自研隔离层,便于将来换 TA-Lib。
- **回测可复现性**:每次回测绑定策略版本+参数+数据快照三元组。
### 6.4 合规(已大幅缩水)
- 数据源 ToS 对商业/再分发有约束;公开免费接口(新浪/东财/腾讯)盘中高并发被封,仅作降级。**商用上线前须取得数据授权**Wind/Choice/聚宽/Tushare 高级档)。
### 6.5 版本陷阱
- lightweight-charts v5`createSeriesMarkers(series, markers)` 取代 v4 `setMarkers()`
- TimescaleDB 2.28+ 弃 PG15锁 PG16/17。
- exchange_calendars `XSHG` 覆盖截至 20252026+ 需 extensions/tushare 兜底。
- ECharts v6 WebGL 在低端机需回归测试。