From 7b229ced145264b6f50f1aa86b3d5ff0e48b02bc Mon Sep 17 00:00:00 2001 From: aszerW Date: Sat, 6 Jun 2026 23:59:41 +0800 Subject: [PATCH] docs: add strategy summary snapshot (2026-06-06, ca933e4) First stage summary documenting core strategy logic, key design decisions, and select_num/weight backtest comparison results. Stored in dedicated docs/strategy_summaries/ directory with date + commit hash naming for reproducibility. --- .../strategy_summary_20260606_ca933e4.md | 258 ++++++++++++++++++ 1 file changed, 258 insertions(+) create mode 100644 docs/strategy_summaries/strategy_summary_20260606_ca933e4.md diff --git a/docs/strategy_summaries/strategy_summary_20260606_ca933e4.md b/docs/strategy_summaries/strategy_summary_20260606_ca933e4.md new file mode 100644 index 0000000..9c23a07 --- /dev/null +++ b/docs/strategy_summaries/strategy_summary_20260606_ca933e4.md @@ -0,0 +1,258 @@ +# ETF 轮动策略阶段总结 + +> **生成日期**:2026-06-06 +> **Git Commit**:`ca933e4` +> **复现方式**:`git checkout ca933e4` 后运行 `rotation/simple_rotation.py` + +--- + +## 1. 策略概述 + +**定位**:基于动量因子的跨市场 ETF 轮动策略,通过每日截面排名在 11 个全球资产中选择强势标的,利用动量效应获取超额收益。 + +**资产池**:11 个信号标的,覆盖 A 股、港股、美股、日股、欧洲、商品、债券七个大类。 + +| 大类 | 信号标的 | 交易 ETF | 说明 | +|:---|:---|:---|:---| +| A 股 | 399006.SZ 创业板指 | 159915.SZ 创业板 ETF | | +| A 股 | H30269.CSI 红利低波 | 512890.SH 红利低波 ETF | | +| 港股 | HSI 恒生指数 | 159920.SZ 恒生 ETF | | +| 港股 | HSTECH.HK 恒生科技 | 513130.SH 恒生科技 ETF | 2020-07 上市 | +| 美股 | NDX 纳指 100 | 513100.SH 纳指 ETF | | +| 日股 | N225 日经 225 | 513520.SH 日经 ETF | | +| 欧洲 | GDAXI 德国 DAX | 513030.SH 德国 ETF | | +| 商品 | GC=F 黄金期货 | 518880.SH 黄金 ETF | | +| 商品 | HG=F 铜期货 | 159980.SZ 有色 ETF | | +| 商品 | CL=F 原油期货 | 160723.SZ 嘉实原油 | | +| 债券 | 931862.CSI 短债指数 | 931862.CSI 短债指数 | 防御配置 | + +**回测区间**:2020-01-10 ~ 2026-06-05,共 1549 个交易日。 + +--- + +## 2. 核心逻辑流程 + +### 2.1 每日时间线 + +``` +T 日 09:00 信号生成(使用 T-1 日及之前的收盘价) + ↓ +T 日 09:30 执行调仓(如触发) + ↓ +T 日 15:00 计算当日收益,更新 NAV +``` + +### 2.2 信号生成 + +**动量因子**:当前使用 `slope_r2`(slope × R²),25 天回看窗口。 + +``` +slope_r2_score = 10000 × slope × R² + +其中: + slope: 对归一化价格 p/p[0] 做线性回归的斜率 + R²: 回归决定系数(拟合优度) +``` + +该因子的设计意图: +- **slope** 捕捉趋势方向和强度 +- **R²** 衡量趋势质量(高 R² = 趋势稳定,低 R² = 噪声大) +- 二者相乘实现"趋势强度 × 拟合质量"的双重过滤 + +**其他可用因子**(通过配置切换): + +| 因子 | 公式 | 特点 | +|:---|:---|:---| +| `momentum` | (p[-1] / p[0]) - 1 | 简单收益率 | +| `weighted_momentum` | annualized_return × R² | 加权回归 | +| `slope_r2` | 10000 × slope × R² | 当前默认 | +| `standardized_slope` | slope / SE(slope) | t 统计量 | +| `vol_adjusted_momentum` | (return / vol) × R² | 类夏普构造 | + +### 2.3 持仓选择 + +信号生成采用**大类竞争 + 动态阈值 + 债券填充**三层机制: + +1. **大类竞争**:每个 group 内选动量 score 最高的标的作为 winner +2. **动态阈值**:非 BOND 组 winner 的 raw_momentum 必须 >= bond_momentum × ratio(当前 ratio=1.0),否则被过滤 +3. **截面排名**:所有通过阈值的 winner 按 score 降序排列,选 top-N(select_num) +4. **债券填充**:若 winner 数量不足 select_num,用债券填充剩余 slot + +**债券的双重角色**: +- **阈值过滤器**:债券动量作为其他标的入选的动态门槛 +- **仓位填充**:市场弱势时(多数标的动量低于债券),作为防御性持仓 + +### 2.4 调仓判定 + +``` +is_rebalance = (sorted(new_holdings) != sorted(current_holdings)) and len(current_holdings) > 0 +``` + +当新选出的持仓与当前持仓不同时触发调仓。调仓时扣除交易成本(默认 0.1%)。 + +### 2.5 仓位加权 + +支持两种模式,仅在调仓日更新权重(权重锁定机制): + +**equal(等权)**: +``` +weight_i = 1/N +``` + +**rank(排名加权)**: +``` +weight_i = (N - i) / triangular(N) + +其中 triangular(N) = N × (N + 1) / 2 +``` + +以 select_num=3 为例:第 1 名 50%,第 2 名 33%,第 3 名 17%。 + +**权重锁定机制**: + +``` +_generate_signals() → 计算 _pending_weights(每天,仅用于信号选择) + ↓ +run() 主循环 → is_rebalance? + ├─ 是: active_weights = _pending_weights (锁定新权重) + └─ 否: 保持 active_weights 不变 (权重不变) +``` + +这确保了持仓不变时,仓位权重不会因排名顺序变化而波动。 + +### 2.6 收益计算 + +| 场景 | 计算方式 | +|:---|:---| +| 调仓日 - 卖出 | (open - prev_close) / prev_close × weight | +| 调仓日 - 买入 | (close - open) / open × weight | +| 调仓日 - 调仓成本 | -0.1% | +| 非调仓日 - 持有 | (close - prev_close) / prev_close × weight | + +--- + +## 3. 关键设计决策 + +| 决策 | 选择 | 原因 | +|:---|:---|:---| +| 动量因子 | slope × R² | slope 捕捉趋势方向,R² 过滤噪声趋势,双重过滤提升信噪比 | +| 回看窗口 | 25 天 | 中期动量(约 1 个月),平衡响应速度与噪声过滤 | +| 债券阈值 | 使用配置的因子函数 | 保持阈值两边量纲一致,仅在 VOL_ADJUSTED_MOMENTUM 时 fallback | +| 权重锁定 | 仅调仓日更新 active_weights | 避免持仓不变时权重随排名波动,减少无效换手 | +| 大类竞争 | 每组选 top 1 | 天然实现大类分散,避免同一大类集中持仓 | +| 交易成本 | 0.1% / 次 | 模拟真实 ETF 交易摩擦成本 | +| 信号时间 | T-1 日收盘价 | 模拟 T 日 9:00 前可获取的信息,避免未来数据 | + +--- + +## 4. 对比实验结果 + +### 4.1 实验矩阵 + +| 维度 | 取值 | +|:---|:---| +| select_num | 1, 2, 3 | +| weight | equal, rank | +| 其他参数 | 与默认配置一致 | + +共 6 组配置(select_num=1 时 equal/rank 等价,实际 5 种独立结果)。 + +### 4.2 结果汇总 + +| select_num | weight | 年化收益 | 夏普比率 | 最大回撤 | Calmar | +|:---:|:---:|:---:|:---:|:---:|:---:| +| 1 | equal/rank | **43.20%** | 1.246 | -26.33% | **1.641** | +| 2 | equal | 22.57% | 1.082 | -18.34% | 1.230 | +| 2 | rank | 26.38% | 1.117 | -19.09% | 1.382 | +| 3 | equal | 20.39% | **1.160** | **-14.65%** | 1.392 | +| 3 | rank | 23.52% | 1.150 | -16.27% | 1.446 | + +### 4.3 关键发现 + +**1. rank 加权系统性提升年化收益** + +在 select_num >= 2 时,rank 加权相比 equal 加权: +- select_num=2:26.38% vs 22.57%(+3.81%) +- select_num=3:23.52% vs 20.39%(+3.13%) + +原因:rank 加权将更多仓位集中在排名最高的标的上,放大了动量最强的资产的收益贡献。 + +**2. select_num=1 是收益天花板** + +单标的集中持仓实现了 43.20% 的年化收益,但代价是 -26.33% 的最大回撤。select_num=1 时 equal/rank 等价,因为只选 1 个标的。 + +**3. equal 加权夏普比率略高** + +| select_num | equal 夏普 | rank 夏普 | 差值 | +|:---:|:---:|:---:|:---:| +| 2 | 1.082 | 1.117 | rank +0.035 | +| 3 | **1.160** | 1.150 | equal +0.010 | + +select_num=3 + equal 的夏普比率最高(1.160),同时回撤最小(-14.65%),体现了分散化的风险调整优势。 + +**4. Calmar 比率视角** + +- select_num=1:Calmar 1.641(收益/回撤最优) +- select_num=3 + rank:Calmar 1.446(多标的中最优) + +**5. 回撤控制** + +select_num 越大,回撤越小: +- 1 标的:-26.33% +- 2 标的:-18% ~ -19% +- 3 标的:-14% ~ -16% + +分散化有效降低了极端回撤。 + +--- + +## 5. 当前默认配置 + +```yaml +rotation: + diversified: true # 大类竞争(每组选 top 1) + select_num: 3 # 持仓数量 + weight: rank # 排名加权(50%/33%/17%) + threshold: + mode: dynamic + dynamic: + reference: 931862.CSI # 债券作为动态阈值参考 + ratio: 1.0 # 阈值 = bond_momentum × 1.0 + fallback_enabled: true + fallback_value: 0.0 + +factor: + type: slope_r2 # 动量因子类型 + n_days: 25 # 回看窗口 + +rebalance: + min_hold_days: 1 + trade_cost: 0.001 # 0.1% 交易成本 + +backtest: + start_date: '2020-01-10' + +benchmark: + code: 000300.SH # 沪深300作为基准 +``` + +--- + +## 6. 代码文件索引 + +| 文件 | 职责 | +|:---|:---| +| `rotation/simple_rotation.py` | 核心策略引擎:动量因子、信号生成、回测主循环、收益计算 | +| `rotation/config_loader.py` | 配置加载:Pydantic Schema、枚举类型、YAML 解析 | +| `rotation/config_simple.yaml` | 策略配置文件:资产池、因子、轮动、回测参数 | +| `rotation/backtest_viewer.html` | 回测可视化:NAV 曲线、持仓明细、交易记录 | + +### 核心函数速查 + +| 函数 | 位置 | 说明 | +|:---|:---|:---| +| `slope_r2_score()` | simple_rotation.py | 默认动量因子:10000 × slope × R² | +| `compute_position_weights()` | simple_rotation.py | 仓位加权:equal / rank 两种模式 | +| `_generate_signals()` | simple_rotation.py | 信号生成:大类竞争 + 阈值过滤 + 债券填充 | +| `_calculate_daily_return()` | simple_rotation.py | 收益计算:调仓/持有两种场景 | +| `run()` | simple_rotation.py | 回测主循环:每日迭代 + 权重锁定 |