# A 股四指数轮动系统 v1 本仓库当前已实现: - 第一阶段:数据层 - 第二阶段:信号层、组合层、回测层最小可用版本 当前仍然是指数研究层回测,不包含个股逻辑、ETF 选择逻辑或实盘交易接口。 ## 覆盖范围 - 固定标的:上证50、沪深300、创业板50、科创50 - 数据频率:日线 - 数据来源:本地 `data/` 分层 - 回测层只读取本地 `clean/features` 衍生结果,不访问网络 ## 当前模块 ```text configs/ instruments.yaml strategy/ top2_weekly.yaml top2_every_5_days.yaml data/ raw/ clean/ features/ meta/ src/ data/ signals/ trend.py ranker.py scorer.py selector.py portfolio/ allocator.py rebalance.py backtest/ execution.py engine.py metrics.py run.py tests/ ``` ## 数据分层 - `raw`:provider 原始缓存 - `clean`:标准化日线 - `features`:只基于本地 `clean` 计算的 rolling 特征 第二阶段 v1 使用的核心字段来自 `features`: - `close` - `daily_return` - `ret_5d` / `ret_10d` / `ret_20d` / `ret_60d` - `ma_20` / `ma_60` - `vol_10d` / `vol_20d` ## 策略 v1 规则 ### 1. 趋势过滤 在 `signal_date` 对每个指数检查: - `close > ma_20` - `close > ma_60` - `ma_20 > ma_60` - `ret_20d > 0` 默认满足至少 2 条时,`trend_pass = True`。 可通过策略配置中的 `trend_min_rules` 调整阈值,例如提高到 3 条以收紧入选条件。 ### 2. 综合打分 只允许 `trend_pass=True` 的标的进入最终选择,但横截面 rank 仍基于当日 4 个指数计算。 动量分数: - `ret_5d * 0.20` - `ret_10d * 0.25` - `ret_20d * 0.30` - `ret_60d * 0.25` 风险惩罚: - `vol_10d * 0.60` - `vol_20d * 0.40` 最终分数: ```text final_score = score_mom - 0.30 * score_risk_penalty ``` ### 3. 组合规则 - `Top2`:若合格标的数 `>= 2`,持有前两名,各 `50%` - `Top2`:若合格标的数 `= 1`,单标的 `100%` - `Top1`:只持有第一名 - 若合格标的数 `= 0`,空仓 - 可通过策略配置中的 `risk_penalty_multiplier` 调整风险惩罚强度(默认 `0.30`) ### 4. 调仓频率 当前支持: - `weekly` - `every_5_days` - `daily`(用于测试和最小实现,不是主配置) ## 信号与执行时点语义 这是第二阶段最重要的约束: - `t` 日收盘后,使用 `t` 日 `close` 与历史数据生成信号 - 在 `t+1` 日执行调仓 - 不允许用 `t` 日收盘信号按 `t` 日收盘成交 当前回测只有日频 close 数据,因此 v1 采用保守语义: - `t+1` 当天先计入旧仓位从 `t -> t+1` 的日收益 - 再在 `t+1` 收盘执行调仓 - 新仓位从 `t+2` 的日收益开始生效 这能明确避免未来函数和时点错配。测试已覆盖该约束。 ## 研究成本假设标准 当前统一使用三档成本场景: - `optimistic` = **10bp 总成本** - `base` = **15bp 总成本**(默认研究基准) - `conservative` = **20bp 总成本** 配置文件位于: ```text configs/research/cost_scenarios.yaml ``` 后续比较策略时,优先看 `base`,并同时检查 `optimistic` / `conservative` 两侧的稳定性。 ## 回测输出 回测至少输出: - `cumulative_return` - `annual_return` - `max_drawdown` - `annual_volatility` - `sharpe` - `calmar` - `turnover` - `rebalance_count` - `cash_days_ratio` 同时输出: - 每日净值 `daily_nav.csv` - 每日持仓 `daily_holdings.csv` - 调仓记录 `rebalances.csv` ## 运行方式 Top2 周频: ```bash python3 -m src.backtest.run --config configs/strategy/top2_weekly.yaml ``` Top2 每 5 个交易日: ```bash python3 -m src.backtest.run --config configs/strategy/top2_every_5_days.yaml ``` Top1 每 5 个交易日(较强风险惩罚候选配置): ```bash python3 -m src.backtest.run --config configs/strategy/top1_every_5_days_p05.yaml ``` Top1 每 5 个交易日(更强风险惩罚,适合低成本场景对比): ```bash python3 -m src.backtest.run --config configs/strategy/top1_every_5_days_p06.yaml ``` Top1 每 5 个交易日(主候选 + 成本敏感性配置): ```bash python3 -m src.backtest.run --config configs/strategy/top1_every_5_days_p05_cost10bp.yaml python3 -m src.backtest.run --config configs/strategy/top1_every_5_days_p05_cost15bp.yaml python3 -m src.backtest.run --config configs/strategy/top1_every_5_days_p05_cost20bp.yaml ``` 默认输出目录: ```text outputs/backtests// ``` 生成统一对比表: ```bash python3 -m src.backtest.compare ``` 默认会输出: ```text outputs/research/strategy_comparison.csv outputs/research/strategy_comparison.md ``` 例如: - `outputs/backtests/top2_weekly/summary.json` - `outputs/backtests/top2_weekly/daily_nav.csv` - `outputs/backtests/top2_weekly/daily_holdings.csv` - `outputs/backtests/top2_weekly/rebalances.csv` ## 第一阶段数据 CLI 首次全量初始化: ```bash python3 -m src.data.bootstrap --all ``` 按上次成功抓取位置增量更新: ```bash python3 -m src.data.update --since-last ``` 单标的历史回补: ```bash python3 -m src.data.backfill --instrument sse50 --start 2003-12-31 ``` 从本地层修复下游层: ```bash python3 -m src.data.repair --instrument sse50 --layer features ``` 查看状态: ```bash python3 -m src.data.status ``` ## 依赖 - `python >= 3.10` - `pandas` - `PyYAML` - `pyarrow` - `akshare` ## 测试 运行全量测试: ```bash python3 -m unittest discover -s tests -v ``` 当前测试覆盖: - 数据层编排与修复 - 特征不使用未来数据 - 趋势过滤规则 - 排序与打分 - `Top1 / Top2 / 空仓` 分配 - `t` 日信号、`t+1` 执行的时点约束 - 回测净值、持仓、调仓记录的基础正确性 - 统一比较表中的成本标签与相对收益字段 ## 边界与后续 当前版本仍有意保持最小化: - 不做 ETF 映射 - 不做成交价建模扩展 - 不做实盘交易接入 - 不引入个股层逻辑 若进入下一阶段,优先建议: - 增加成交成本和现金收益率的更细粒度建模 - 增加参数化样本区间与输出报表 - 增加基准对比与分年度绩效拆解