Appearance
设计:周频动量 ETF 轮动 + 多层风控
2026-06-24。每周一调仓,全市场 ETF 池,风险调整动量选股 + 四层风控。仅研究学习,不构成投资建议。
1. 目标与总览
每周一在全市场流动性 top-N 的 ETF 里,用风险调整动量选最强的 ≤10 只、风险平价分仓;再叠四层风控,趋势走坏时逐级降险直至空仓避险,余额转入避险 sleeve(债券/货币 ETF)。
信号全部用上一交易日(上周五)收盘前数据,周一收盘执行,无未来函数。
上周五收盘数据
[0] 池子(PIT) 全市场场内ETF → 名称分类 → 成交额top-N → 近63日日均成交额>门槛
[1] 进攻·相对动量 score = 过去L日收益 / 过去L日波动 (跳过近skip日)
[2] 选择 全池降序取 top-10,同类别最多 cap 只 → 候选篮子
[3] 风控A·趋势过滤 剔除 score≤0 或 价<200日线 → 幸存篮子(可能<10,甚至0)
[4] 仓位·风险平价 幸存标的 risk_parity_weights 定权(单只上限) → 进攻权重
[5] 风控B·波动率目标 σ_p=组合近期波动 → scale=min(1, σ_target/σ_p),进攻权重整体×scale
[6] 风控C·回撤熔断 策略净值回撤>10% → 强制最低仓位,直到趋势过滤(市场)重新转正才回场
余额(1−进攻仓位) → 避险sleeve:动量最高且>0的债券ETF,否则货币ETF/现金
→ run_rebalance_backtest(整手/佣金/weight-band/sweep_code)四层风控各管一个失效模式:A 系统性熊市(整体撤离)、B 波动放大(降仓)、C 尾部黑天鹅(硬熔断)、风险平价(单标的不主导组合风险)。
2. 定稿决策
- 风控 B:连续波动率目标(非二元 risk-on/off)。
scale = min(1, σ_target/σ_p),不加杠杆(上限 1)。 - 风控 C:熔断阈值 −10%;触发后强制避险,等趋势过滤重新转正(市场基准价 > 200 日线)才回场——不是固定冷却周数。
- 进攻:风险调整动量(收益/波动)。持仓 top-10 + 每类 cap 只。权重风险平价。
- 池子:全市场动态池(成交额 top-N,复用
build_universe_all)。 - 节奏:每周一(自然周首个交易日,休市顺延)。
3. 模块与接口
新建 src/quant/strategy/momentum_rotation.py(纯函数,3.8 安全,可单测)
risk_adjusted_momentum(prices, asof, lookback=60, skip=5) -> Series每列:窗口内日收益均值 / 日收益标准差(类 Sharpe 动量),跳过近skip日。select_top_capped(scores, categories, n=10, cap=2) -> list[str]按分降序取至 n,单类别不超过 cap。trend_filter(prices, asof, candidates, scores, ma_window=200) -> list[str]保留score>0且price[asof] > MA(ma_window)的标的(绝对动量 + 均线)。vol_target_scale(weights, returns, asof, target_vol, vol_window=60, max_leverage=1.0) -> float用近期协方差算组合年化波动 σ_p;min(max_leverage, target_vol/σ_p)。class CircuitBreaker(threshold=0.10):状态机。step(nav, regime_on) -> defensive: bool。维护净值高点;回撤≤−threshold→tripped; tripped 且 regime_on→解除;返回是否强制避险。class MomentumRotationStrategy:持有 config + 熔断状态,__call__(date, nav) -> {code: weight}, 组合上面各层 +risk_parity_weights+ 避险 sleeve 选择。
复用
run_rebalance_backtest、risk_parity_weights、build_universe_all+_categorize、 AShareCostModel/涨跌停、metrics、TushareFundSource。
小改 src/quant/backtest/portfolio.py
run_rebalance_backtest 让 weight_fn 可选接收当前净值:若其签名参数 ≥2,则调用 weight_fn(date, nav_now),否则保持 weight_fn(date)。向后兼容(现有月度脚本不受影响), 以便熔断层读到策略自身回撤。
新建 scripts/run_momentum_rotation.py
取数(全市场ETF) → 每周一调仓日 → 跑策略 → 消融(完整四层 / 仅相对动量 / 逐层开关) → 基准(沪深300买入持有、全池等权) → 指标 + 净值/回撤/仓位暴露图 + 报告。
4. 参数默认(全部可配)
| 参数 | 默认 |
|---|---|
| 动量回看 L / 跳过 skip | 60 / 5 交易日 |
| 波动窗口 | 60 日 |
| 池规模 / 流动性门槛 | 成交额 top-100 / 近63日日均>3000万 |
| 持仓数 / 类内上限 | 10 / 2 |
| 风险平价权重界 | [5%, 20%] |
| 趋势过滤 | score>0 且 价>200日线 |
| 波动率目标 | 年化 11% |
| 熔断 / 回场 | −10% / 市场基准>200日线 |
| 成本 / 换手带 | 佣金万三、无印花、weight-band 1% |
5. 回测与验证
- 消融:完整四层 vs 仅相对动量 vs 逐层开关,量化每层贡献。
- 基准:沪深300 买入持有 + 全池等权。
- 指标:年化/波动/夏普/最大回撤/换手/在场率(% 周处于进攻)。
- 产出:净值图 + 回撤图 + 仓位暴露时序图。
- 单测:逐层纯函数 + 熔断状态机(合成数据,3.8 本地可跑)。
6. 非目标(YAGNI)
不做:日内/分钟级、加杠杆(vol target 上限 1)、个股、机器学习信号、实盘下单对接。