你现在要在当前仓库中实现 A 股四指数轮动系统 v1 的第二阶段:信号层、组合层、回测层最小可用版本。 重要背景: - 第一阶段数据层已经完成,并且本地数据已建库成功。 - 标的固定为 4 个指数:上证50、沪深300、创业板50、科创50。 - 当前仍然是“指数研究层回测”,不是 ETF 执行层。 - 严禁引入个股逻辑、ETF 选择逻辑、实盘交易接口。 本阶段目标: 1)实现趋势过滤信号; 2)实现相对强弱排序与风险惩罚打分; 3)实现 Top1 / Top2 / 空仓组合构建; 4)实现最小可用回测引擎; 5)输出基础绩效指标; 6)补必要测试与 README 更新。 必须严格遵守的时点语义: - t 日收盘后,根据 t 日 close 与历史数据生成信号; - 在 t+1 日执行调仓; - 不允许使用 t 日收盘信号并按 t 日收盘成交; - 测试里必须覆盖这个约束,防止未来函数和时点错配。 请实现的策略 v1 规则: 一、趋势过滤 对每个指数在 signal_date 计算以下规则: - close > ma_20 - close > ma_60 - ma_20 > ma_60 - ret_20d > 0 满足至少 2 条,trend_pass = True。 二、综合打分 仅对 trend_pass=True 的指数参与排序。 打分由两部分组成: 1. 动量分数(横截面 rank,标的池为当日 4 个指数) - ret_5d 权重 0.20 - ret_10d 权重 0.25 - ret_20d 权重 0.30 - ret_60d 权重 0.25 2. 风险惩罚(横截面 rank) - vol_10d 权重 0.60 - vol_20d 权重 0.40 最终:final_score = score_mom - 0.30 * score_risk_penalty 三、组合规则 - 若合格标的 >= 2:支持 Top2 等权(50/50) - 若合格标的 = 1:100% 持有该指数 - 若合格标的 = 0:空仓 - 同时支持 Top1 模式,作为可配置项 四、调仓频率 先实现: - weekly - every_5_days 可选支持 daily,但不是重点。 五、回测层 - 使用本地 clean/features 数据 - 使用 trade_date 序列推进 - signal_date 与 execution_date 分离 - 默认无摩擦回测,但要预留成本字段:commission_bps / slippage_bps - 默认 cash_return = 0 六、指标输出 至少输出: - cumulative_return - annual_return - max_drawdown - annual_volatility - sharpe - calmar - turnover - rebalance_count - cash_days_ratio 并输出每日净值、每日持仓、调仓记录。 七、建议代码结构 建议新增: - src/signals/trend.py - src/signals/ranker.py - src/signals/scorer.py - src/signals/selector.py - src/portfolio/allocator.py - src/portfolio/rebalance.py - src/backtest/engine.py - src/backtest/execution.py - src/backtest/metrics.py 如果你认为需要微调结构,可以调整,但必须保持清晰。 八、CLI / 可运行入口 请至少提供一个可运行入口,例如: - python3 -m src.backtest.run --config configs/strategy/top2_weekly.yaml 或者等价命令。 需要有最小配置文件支持 weekly / every_5_days 两个版本。 九、测试要求 至少覆盖: - t 日信号、t+1 执行的时点测试 - trend filter 规则测试 - ranking / scoring 测试 - Top1 / Top2 / 空仓分配测试 - 回测净值与调仓记录基本正确性测试 十、文档要求 更新 README,补充: - 第二阶段模块说明 - 信号与执行时点语义 - 如何运行 weekly / every_5_days 回测 - 目前仍为指数研究层,不是实盘执行层 工作方式: - 先输出实现计划; - 再按模块逐步实现; - 每完成一部分就运行对应测试; - 最后运行完整测试; - 给出已完成模块、未完成项、假设与下一步建议。 运行环境要求: - 使用 python3,不要假设 python 命令存在; - 继续复用当前仓库和已有数据层; - 如需读取本地数据,请使用现有 data 目录。 当你完全完成后,请执行: openclaw system event --text "Done: index-rotation phase2 signal/backtest implemented" --mode now