Files
etf/docs/动量因子对比调研报告.md

8.9 KiB
Raw Blame History

动量因子对比调研报告

调研日期2026-06-06
回测区间2020-01-10 ~ 2026-06-05
当前结论:slope_r2 作为默认因子(年化 19.84%,夏普 1.14


1. 问题背景

原始策略使用 weighted_momentum 因子,通过加权线性回归计算动量得分。诊断分析发现三个信号质量瓶颈:

  1. 跨市场动量不可比:同组换仓 alpha=+0.47%,跨组换仓仅 +0.03%
  2. IC 极低IC=0.07ICIR=0.17
  3. T+1 执行噪声:跨市场约 50% 翻转率

核心问题是:不同资产的动量得分量纲差异巨大(如 CL=F 原油极端值可达 375,527,068导致跨资产比较失真。


2. 四种因子公式对比

2.1 weighted_momentum加权线性回归动量

\text{Score} = (e^{\beta \times 250} - 1) \times R^2

计算逻辑

  • 价格变换:$y = \ln(\text{prices})$,取对数
  • 回归权重:$w = \text{linspace}(1, 2, n)$,近期权重线性递增
  • 加权线性回归:y = \beta x + \alpha
  • 年化收益:e^{\beta \times 250} - 1
  • $R^2$:加权决定系数

特点:近期加权强调趋势延续性,对数收益使跨资产量纲部分可比。


2.2 vol_adjusted_momentum波动率调整动量

\text{Score} = \frac{\text{年化收益}}{\text{年化波动率}} \times R^2

计算逻辑

  • 回归逻辑与 weighted_momentum 完全相同
  • 额外除以已实现波动率:\sigma = \text{std}(\text{daily\_returns}) \times \sqrt{250}
  • 最小波动率保护:\sigma \geq 0.01

学术来源Moskowitz, Ooi & Pedersen (2012) Time Series Momentum,类夏普比率构造。

特点:理论上使跨资产更可比,但实践中波动率计算对极端值敏感。


2.3 slope_r2斜率×归一化价格

\text{Score} = 10000 \times \text{slope} \times R^2

计算逻辑

  • 价格变换:$y = \text{prices} / \text{prices}[0]$归一化而非取对数
  • 无权重,普通最小二乘回归:y = \text{slope} \cdot x + \text{intercept}
  • $R^2$:无权重决定系数
  • 乘以 10000 使数值范围便于阅读

特点:归一化天然消除量纲差异,所有资产起点为 1.0,斜率在同尺度上可比。


2.4 momentum简单收益率

\text{Score} = \frac{\text{prices}[-1]}{\text{prices}[0]} - 1

计算逻辑

  • 最朴素:期末价格 / 期初价格 - 1
  • 不考虑趋势质量(无 $R^2$)、不考虑波动率

特点:简单但缺乏趋势质量过滤,对短期噪声敏感。


3. 回测对比结果

3.1 核心指标

因子类型 年化收益 夏普比率 最大回撤 Calmar 调仓次数 胜率
weighted_momentum 18.36% 1.02 -16.36% 1.12 405 54.0%
vol_adjusted_momentum 13.16% 0.85 -18.61% 0.71 393 55.9%
slope_r2当前默认 19.84% 1.14 -15.35% 1.29 394 54.1%
momentum 9.27% 0.57 -17.42% 0.53 729 53.3%

结论slope_r2 全面胜出,年化 +1.48%,夏普 +0.12,回撤改善 +1.01%。

3.2 数值尺度分析2024-06-03 截面)

因子 最大值 最小正值 max/min 比值
weighted_momentum 0.633 0.0003 2179x
vol_adjusted_momentum 4.812 0.0014 3378x
slope_r2 23.18 0.745 31x
momentum 0.046 0.0005 90x

slope_r2 的跨资产数值差距仅 31 倍,远小于其他因子的 2000~3000 倍,这是其跨市场可比的根本原因。


4. slope_r2 胜出的原因分析

4.1 跨市场可比性:归一化消除量纲

设计选择 weighted 的做法 slope_r2 的做法 为什么 slope_r2 更好
价格变换 \ln(p) p/p_0 归一化后所有资产同尺度
回归权重 近期加权(1→2) 无权重 25 天窗口已短,等权更抗噪
R^2 质量因子 都保留了趋势质量过滤

4.2 不加权 > 加权:降噪效应

25 天窗口本身就不长,加权(权重 1→2相当于把有效窗口缩到约 17 天,增加了随机性。等权回归对 25 天趋势的估计更稳健。

4.3 负价格免疫力

WTI 原油 2020-04-21 出现 -37.63 美元/桶的负价格。各因子处理方式:

因子 处理方式 问题
weighted \ln(\text{clip}(0.01)) = -4.6 虚假平台拉偏回归
vol_adjusted 对数收益率跳跃 vol 被放大score 压低
slope_r2 0.01/60 \approx 0.000167 跌幅压缩但不爆炸
momentum 25/0.01 - 1 = 2499 荒谬收益率,严重误判

5. 业界学界方法调研

5.1 Moskowitz, Ooi & Pedersen (2012) — TSMOM

核心公式

Signal = sign(r_{t-12, t})     // 仅取过去12月超额收益的符号
Position = (1/σ_t) × Signal    // 仓位反比于波动率

关键设计

  • 使用期货超额收益(简单收益),不用对数收益
  • 只用 sign正负号决定方向不用收益率幅度
  • 仓位大小由波动率倒数控制

对负价格的态度:简单收益天然兼容负价格,(560)/60 = 108\% 合法。

5.2 Baltas & Kosowski (2012) — 线性趋势拟合

"Momentum trading signals generated by fitting a linear trend on the asset price path maximise the out-of-sample performance while minimizing the portfolio turnover."

这正是 slope_r2 的思路——直接拟合价格路径而非计算收益率。

结论:线性趋势拟合 > 简单收益率 > 加权收益率。

5.3 Dudler, Gmuer, Malamud (2014) — Risk-Adjusted Momentum

\text{RAMOM} = \text{mean}\left(\frac{r_1}{\sigma_1}, \frac{r_2}{\sigma_2}, \ldots, \frac{r_n}{\sigma_n}\right)

每天先算风险调整收益 $r_t/\sigma_t$,再取均值作为信号。比 TSMOM 整体更优。

5.4 AQR / Man Group / Winton — 实盘 CTA 做法

方法 做法 代表机构
简单收益替代对数 r = (P_t - P_{t-1}) / P_{t-1} AQR, Man AHL
排除/跳过 窗口内出现非正价格时信号设为 0 多数 CTA
连续合约 使用 roll-adjusted futures 价格 所有正规 CTA
波动率缩放 只用 sign + vol 倒数,不用幅度 Moskowitz 方案

6. 负价格处理机制分析

6.1 当前实现的问题

四个因子均使用 np.clip(prices, 0.01, None) 处理负价格:

prices = np.clip(prices, 0.01, None)  # 负值 → 0.01

问题:这是粗暴的掩盖而非正确处理。

因子 clip 后的核心问题 严重程度
weighted \log(0.01) = -4.6 形成假平台,拉偏回归
vol_adjusted 对数收益率剧烈跳跃vol 被放大
slope_r2 跌幅被压缩,但不产生数值爆炸
momentum 首尾任一被 clip 就产生荒谬比值 极高

6.2 推荐改进方案

方案 A排除法推荐

窗口内出现非正价格 → 返回 None,该资产不参与排名。

def _compute_momentum(self, signal_code: str, date: pd.Timestamp) -> Optional[float]:
    # ... 获取 prices ...
    if np.any(prices <= 0):
        return None  # 负价格期间不参与交易
    # ... 计算 score ...

优点

  • 负油价在历史上只出现几天,排除影响极小
  • 避免所有 clip 导致的信号扭曲
  • 实现成本极低

方案 B简单收益替代对数

weighted_momentumvol_adjustedlog(prices) 改为简单收益率。但 slope_r2 已在价格空间操作,无需修改。

方案 C保持现状

slope_r2 已是当前最优(年化 19.84%且对负价格抵抗力最强。clip 只在极端情况触发,实际影响有限。


7. 结论与建议

7.1 当前决策

采用 slope_r2 作为默认因子,配置已切换至 config_simple.yaml

factor:
  type: slope_r2
  n_days: 25

7.2 理论依据

  1. 跨市场可比:归一化价格天然消除量纲差异
  2. 趋势质量R^2 过滤噪声趋势
  3. 抗极端值:不使用对数,对负价格免疫力最强
  4. 学术支持Baltas & Kosowski (2012) 证实线性趋势拟合优于简单收益率

7.3 后续优化方向

方向 描述 优先级
负价格排除 窗口内出现非正价格时返回 None 低(实际影响极小)
多窗口融合 结合 5/25/60 天信号
截面 rank 动量值转截面百分位排名 slope_r2 已天然可比)

附录:实验代码

对比实验脚本:rotation/experiments/factor_comparison.py

运行方式:

cd /Users/aszer/code/etf
set -a && source .env && set +a
python rotation/experiments/factor_comparison.py

结果输出:rotation/experiments/output/factor_comparison_results.json