From b6efec098f05cf8afd64fb0c35ced8dbf514bfcb Mon Sep 17 00:00:00 2001 From: xiaowu Date: Mon, 28 Sep 2026 16:02:32 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=E9=87=8F=E5=8C=96?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E5=AE=8C=E5=96=84=E8=B7=AF=E7=BA=BF=E5=9B=BE?= =?UTF-8?q?=20ROADMAP=EF=BC=88P0=20=E5=8F=AF=E4=BF=A1=E5=BA=A6/P1=20?= =?UTF-8?q?=E8=B4=A8=E9=87=8F/P2=20=E5=AE=9E=E7=9B=98=20+=20=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3=E8=AE=BE=E8=AE=A1=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/ROADMAP.md | 180 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 180 insertions(+) create mode 100644 docs/ROADMAP.md diff --git a/docs/ROADMAP.md b/docs/ROADMAP.md new file mode 100644 index 0000000..1b787e5 --- /dev/null +++ b/docs/ROADMAP.md @@ -0,0 +1,180 @@ +# quanxiel 量化系统 · 完善路线图(ROADMAP) + +> 编制:小五 | 2026-09-28 +> 定位:在现有「数据导入 + alpha 研究闭环」基础上,补齐 **回测可信度 / 风控 / 归因 / 自动化** 四块地基,打通「研究 → 实盘」。 + +--- + +## 0. 现状定位 + +| 已有 | 位置 | +|---|---| +| 数据导入(Tushare / 同花顺)+ 增量 + schema | `quantitative_data/` | +| 数据加载(DB + 模拟回退) | `alpha/data_loader.py` | +| 因子研究(注册表 / IC / 分层 / 中性化 / 换手) | `alpha/factors.py` | +| 策略(信号生成 / 分位 / 组合打分 / 权重) | `alpha/strategy.py` | +| 事件驱动回测(组合 / 持仓 / 交易成本) | `alpha/backtest.py` | +| 绩效评估(收益 / 风险 / 报告) | `alpha/evaluation.py` | +| 7 个策略 notebook | `alpha/*.ipynb` | + +**结论**:研究闭环已成;「研究 → 实盘」的整条链路基本缺失。缺口见下表。 + +--- + +## 1. 模块矩阵(已有 / 不完整 / 缺失) + +| 层 | 状态 | 说明 | +|---|---|---| +| 数据导入 | ✅ | 行情/财务/基本面/增量 | +| 数据质检 | ⚠️ | 仅 `check_daily_coverage`,缺系统化 DQ | +| Point-in-Time | ❌ | 财报未按公告日对齐;无成分股历史快照 | +| 因子研究 | ✅ | 基础技术+基本面因子 | +| 风格/风险模型 | ❌ | 无 Barra 类暴露与正交化 | +| 组合构建 | ⚠️ | 有简单权重,无优化器/约束求解 | +| 回测引擎 | ⚠️ | 无涨跌停/停牌/T+1/整手/参与率约束 | +| 风控 | ❌ | 基本空白 | +| 归因分析 | ❌ | 无 | +| 稳健性验证 | ❌ | 无 WFO / PBO | +| 实盘执行 | ❌ | 无交易接口/订单管理/对账 | +| 工程运维 | ⚠️ | 有导入脚本,无调度/监控 | +| 报告可视化 | ⚠️ | 有 markdown/df,无自动报告/dashboard | + +--- + +## 2. P0 — 让研究「可信」(最先做) + +> 不做这层,回测收益大概率是**假的**(未来函数 + 不可成交 + 无风控)。 + +### P0-1 回测真实性:A 股交易规则引擎 +- **新增** `alpha/market_rules.py` +- **接口**: + ```python + class MarketRules: + """A股交易规则约束,供回测下单前校验""" + def can_buy(self, ts_code, date, price) -> bool: ... # 涨停/停牌/次新 + def can_sell(self, ts_code, date, price) -> bool: ... # 跌停/停牌 + def round_lot(self, qty, side) -> int: ... # 100股整手(卖出可零股) + def max_volume(self, ts_code, date, participation=0.1) -> float: ... # 参与率上限 + def is_tradable(self, ts_code, date) -> bool: ... # 停牌过滤 + ``` +- **集成**:`BacktestEngine(config, market_rules=MarketRules(...))`;下单前 `execute()` 走校验 +- **数据依赖**:`daily` 已有 `pre_close/pct_chg`,涨跌停按 ±10%/±20% 阈值 + `stock_basic.market` 判定;停牌用 `vol=0` 或 `trade_cal` +- **验收**:构造一个"次日涨停买入"用例,断言该笔被拒 + +### P0-2 Point-in-Time(防未来函数) +- **数据侧** `quantitative_data/schema.sql` 新增表 `index_weight`(成分股历史) + ```sql + CREATE TABLE index_weight ( + index_code VARCHAR(20), con_code VARCHAR(20), + trade_date DATE, weight NUMERIC(10,6), + PRIMARY KEY (index_code, con_code, trade_date)); + ``` +- **加载侧** `alpha/data_loader.py` 增加 `as_of` 语义 + ```python + def load_financials(self, fields, start, end, as_of=None): + """as_of 非空时,仅取 ann_date <= as_of 的财报(点对点快照)""" + def load_universe(self, index_code, date) -> list[str]: + """取 date 当日在成分列表内的股票(历史成分)""" + ``` +- **验收**:同一财报在公告日前后取到不同值(公告前取不到) + +### P0-3 风控限额(事前约束) +- **新增** `alpha/risk/limits.py` + ```python + class RiskLimits: + def __init__(self, config: AlphaConfig): ... + def clamp_weights(self, weights, industry_map) -> pd.Series: ... + # 单票上限 max_position_pct / 行业上限 / 总仓位 + def check_drawdown_stop(self, nav_curve) -> bool: ... # 回撤熔断 + def risk_budget(self, weights, cov) -> dict: ... # 风险预算/贡献 + ``` +- **集成**:回测每期调仓前 `clamp_weights`;净值触发回撤阈值→降仓/清仓 +- **验收**:给定超限组合,输出满足全部限额的权重 + +--- + +## 3. P1 — 提升质量 + +### P1-4 收益归因 +- **新增** `alpha/attribution.py` + ```python + class BrinsonAttribution: + def run(self, portfolio_weights, benchmark_weights, + returns, industry_map) -> pd.DataFrame: + """返回 配置/选股/交互 三因子分解""" + class FactorAttribution: + def run(self, weights, factor_exposures, factor_returns) -> dict: + """因子收益贡献分解""" + ``` + +### P1-5 组合优化器 +- **新增** `alpha/optimizer.py`(依赖 `cvxpy`) + ```python + class MeanVariance: def solve(self, mu, cov, constraints) -> weights + class RiskParity: def solve(self, cov) -> weights + class BlackLitterman: def solve(self, prior, views, ...) -> mu + # constraints: 行业/风格中性、换手上限、个股上限、多空约束 + ``` +- **验收**:约束可行域内求解,权重和=1,满足全部约束 + +### P1-6 稳健性 / 过拟合检验 +- **新增** `alpha/validation.py` + ```python + class WalkForward: def run(self, strategy_factory, folds) -> pd.DataFrame # 滚动样本外 + def pbo(returns_matrix) -> float # 过拟合概率 (Bailey et al.) + def deflated_sharpe(returns, n_trials) -> float + def sensitivity(param_grid, evaluator) -> pd.DataFrame + ``` + +--- + +## 4. P2 — 走向实盘 + +### P2-7 调度 + 监控 +- `ops/daily_pipeline.py`:盘后自动 增量导入 → 信号生成 → 风控 → 报告 +- 调度:群晖 DSM 计划任务 / cron;失败告警走 OpenClaw(webhook) +- **新增** `ops/monitor.py`:数据到达检测、任务失败、仓位异常 + +### P2-8 实盘执行 + 对账 +- **新增** `execution/` + ```python + class BrokerAdapter(ABC): + def place_order(self, order) -> str: ... + def cancel_order(self, order_id): ... + def query_position(self) -> pd.DataFrame: ... + class QmtAdapter(BrokerAdapter): ... # A股 QMT/miniQMT + class SimAdapter(BrokerAdapter): ... # 仿真盘 + ``` +- **对账**:每日 `query_position` vs 内部账本,差异告警 + +### P2-9 报告 + Dashboard +- **新增** `report/`:自动日报/周报(净值/回撤/持仓/归因/暴露) +- Dashboard:复用 gemdalepi 静态站点方式,生成净值/回撤/暴露可视化页 + +--- + +## 5. 目录规划(目标) + +``` +quanxiel/ +├── quantitative_data/ # 数据(现有)+ index_weight +├── alpha/ # 研究(现有) +│ ├── market_rules.py # [P0-1] 新增 +│ ├── risk/ # [P0-3] 新增 +│ ├── attribution.py # [P1-4] 新增 +│ ├── optimizer.py # [P1-5] 新增 +│ └── validation.py # [P1-6] 新增 +├── execution/ # [P2-8] 新增 +├── report/ # [P2-9] 新增 +└── ops/ # 运维(现有)+ daily_pipeline.py / monitor.py +``` + +--- + +## 6. 建议实施顺序 + +1. **P0-1 交易规则** → 2. **P0-2 PIT** → 3. **P0-3 风控限额** +4. P1-4 归因 → 5. P1-5 优化器 → 6. P1-6 稳健性 +7. P2-7 调度 → 8. P2-8 实盘 → 9. P2-9 报告 + +> 交付节奏建议:每个模块「接口 + 最小实现 + 单测/验收用例」三件套,合入前跑通验收。