因子上线之后,还要处理动态问题:
因子择时,即确定在何种时点应重点配置哪类因子。
在多因子模型实践中,常见情形是:已筛选出多个有效因子并完成组合优化,但回测收益仍平平。原因在于因子并非始终有效。例如,2017年大盘价值风格占优,2021年小盘成长表现突出;若长期固定持有单一因子而不作调整,其效果近似于随机博弈。
实践中通常将因子择时分解为四个维度:宏观状态切换、因子动量与反转、波动率择时、估值差择时。
因子表现与宏观经济高度相关。例如,低波动因子在衰退期往往表现较好,但在复苏期则易被高 beta 股票超越。
其原因在于:衰退期投资者避险情绪上升,低波动股票相对抗跌;复苏期风险偏好回升,高弹性股票更受青睐。
核心逻辑: 宏观状态决定因子收益的土壤。不同因子在不同宏观环境下,收益来源完全不同。
常用的宏观状态划分方法,是基于美林时钟的改良版本:
| 宏观状态 | GDP增速 | 通胀水平 | 适合的因子 |
|---|---|---|---|
| 复苏期 | 上升 | 低位 | 动量、成长、小市值 |
| 过热期 | 上升 | 高位 | 价值、红利、低波动 |
| 滞胀期 | 下降 | 高位 | 低波动、质量、红利 |
| 衰退期 | 下降 | 低位 | 低波动、质量、国债 |
需注意:宏观状态切换并非瞬时完成。若采用月度数据频繁切换,易导致过度调仓并侵蚀收益。建议至少采用季度数据,或在滚动窗口内确认趋势后再行切换。
可基于 PMI、CPI、工业增加值等宏观指标构建综合打分体系。例如,PMI 连续两个月上升且高于 50,可标记为复苏期,以过滤噪声。
因子择时里,有一个很有意思的现象:因子本身也存在动量和反转效应。
其含义是:过去表现优异的因子,在未来一段时期内可能延续强势(动量),亦可能骤然转弱(反转)。
典型情形如下:2019 年小市值因子连续 12 个月跑赢大盘,大量量化基金增配小盘股;2020 年初小市值因子骤然失效,回撤超过 20%。此为典型的因子反转。
判断因子处于动量抑或反转状态,通常可参考以下两类指标:
# 因子动量信号计算示例(Python伪代码)
import pandas as pd
import numpy as np
def factor_momentum_signal(factor_returns, lookback=12):
"""
计算因子动量信号
factor_returns: 因子月度收益率序列
lookback: 回看窗口(月)
"""
# 计算滚动累计收益
cum_ret = factor_returns.rolling(lookback).sum
# 计算滚动波动率
vol = factor_returns.rolling(lookback).std
# 动量信号 = 累计收益 / 波动率(类似夏普比)
momentum_signal = cum_ret / vol
# 如果信号大于1.5,认为动量强;小于-1.5,认为反转风险大
signal = np.where(momentum_signal > 1.5, 1,
np.where(momentum_signal < -1.5, -1, 0))
return signal
注意事项: 不宜直接以因子收益率作为动量信号,易受极端值干扰。更稳健的做法是采用排名动量,即考察因子在过去 N 个月内的排名变化,而非绝对收益。
波动率择时的核心在于:不同波动率环境下,因子表现差异显著。
研究表明,低波动率环境下动量因子与成长因子表现更优;高波动率环境下价值因子与低波动因子更具抗跌性。
其原因在于:低波动反映市场情绪相对稳定,资金倾向于追逐趋势与成长;高波动常伴随恐慌或不确定性,资金回归基本面并寻求安全边际。
波动率择时的具体做法:
| 波动率状态 | 波动率分位数 | 超配因子 | 低配因子 |
|---|---|---|---|
| 低波动 | <30% | 动量、成长 | 低波动、价值 |
| 中波动 | 30%-70% | 均衡配置 | - |
| 高波动 | >70% | 低波动、价值 | 动量、小市值 |
波动率择时不宜过于频繁,通常采用周度信号,因日度波动率噪声较大。波动率状态切换时,因子权重调整幅度宜控制在 10%–20%,以避免过度反应。
最后一个维度为估值差择时,即考察因子之间的估值差异。
例如,当价值因子相对成长因子的估值折价达历史极值时,价值因子往往面临反弹;反之,若成长因子估值明显偏高,则需警惕回调风险。
2021 年初,中证 500 的 PE 相对沪深 300 的 PE 比值跌至历史低位,小盘价值风格随后于 2021 年跑赢大盘成长,与此判断一致。
估值差择时的核心指标:
# 估值差择时信号示例
def valuation_spread_signal(value_pe, growth_pe, lookback=60):
"""
估值差择时信号
value_pe: 价值因子组合的PE
growth_pe: 成长因子组合的PE
lookback: 回看窗口(月)
"""
# 计算估值差(成长PE / 价值PE)
spread = growth_pe / value_pe
# 计算历史分位数
percentile = spread.rolling(lookback).apply(
lambda x: (x[-1] - x.min) / (x.max - x.min)
)
# 信号:估值差低于10%分位数时超配价值,高于90%分位数时超配成长
signal = np.where(percentile < 0.1, 1, # 超配价值
np.where(percentile > 0.9, -1, 0)) # 超配成长
return signal
注意: 估值差择时并非万能。2018 年曾依据估值差信号超配价值因子,但价值因子此后仍下跌约半年,因当时宏观环境为衰退 + 通缩,价值因子本身不占优。估值差择时须与宏观状态结合使用,不宜单独依赖。
上述四个维度并非相互独立:宏观状态决定因子收益的大方向,因子动量反映短期趋势,波动率择时用于控制风险敞口,估值差则提供均值回复的参照。
常见做法为:先以宏观状态确定因子配置的总体框架,再以波动率择时作微调,最后以因子动量与估值差信号作战术调整。如此既可把握主要风格切换,亦可捕捉短期交易机会。
总结: 因子择时并非预测未来,而是管理概率。不必每次判断均正确,只需在概率有利时加大配置,长期即可取得超额收益。
本章从两个互补视角讨论因子还能不能用、还能用多久:因子拥挤度与容量(同一信号被过多资金共用时的 alpha 挤出),以及因子衰减、失效与生命周期(随时间推移预测力自然退化)。
因子投资的长期实践表明: 没有哪个因子能够永久产生超额收益 。
因子研究中,常见误区是仅关注因子收益与夏普比率,认为历史回测表现优异即可。然而,实盘收益大幅缩水的情形并不罕见:因子逻辑未必永久失效,更可能是拥挤(过多资金采用同一信号,超额收益被挤出),或衰减(生命周期进入成熟/衰退阶段)——二者是因子失效的两类常见机制,宜同时纳入监测框架。
因子拥挤度,即衡量同一策略被广泛使用并导致 alpha 衰减的程度。参与者过多时,单一策略的超额收益将难以为继。
早年小市值因子超额收益显著,筛选简便;当前环境下回撤可能较大。这并非因子逻辑必然错误,而是其生命周期与拥挤状况进入新阶段。
本章讨论因子拥挤度与生命周期两类实际问题:因子何时因拥挤而 alpha 被挤出?何时进入衰减/失效阶段?如何识别真实失效?失效后应如何应对?下文先讨论拥挤度定义、指标构建与容量测算,再讨论生命周期、衰减识别与失效应对,最后作统一小结。
因子拥挤度,衡量的是某个因子被市场参与者共同使用的程度。当大量资金都基于同一个信号进行交易时,这个因子的预测能力就会快速衰减。
拥挤度可视为因子生命周期的加速器:因子初被发现时收益高、容量大;随参与者增加,拥挤度上升,收益下降、波动扩大,最终趋近广为人知却难以获利。
核心观点: 拥挤度不是因子失效的原因,而是因子失效的催化剂。拥挤度越高,因子失效的速度越快。
如何量化拥挤度?需构建相应指标。
常用的拥挤度指标涵盖三个维度:波动率、相关性与换手率,分别从收益波动、暴露趋同与交易频率等角度刻画拥挤程度。
当某一因子变得拥挤时,其收益波动率通常显著上升。原因在于市场参与者使用相同信号,一旦信号反转,集中平仓易引发踩踏。
具体指标:
典型情形:某因子平时波动率约 5%,某月骤升至 15%。初看似市场波动所致,实为多家大型机构同时采用该因子引发信号共振——此为典型的拥挤度预警信号。
# 计算因子收益的滚动波动率
import pandas as pd
import numpy as np
def factor_volatility(factor_returns, window=20):
"""
计算因子收益的滚动波动率
factor_returns: 因子多空组合的日收益序列
"""
rolling_vol = factor_returns.rolling(window).std * np.sqrt(252)
return rolling_vol
# 计算波动率突变度
def vol_regime_change(rolling_vol, lookback=60):
current_vol = rolling_vol.iloc[-1]
avg_vol = rolling_vol.iloc[-lookback:].mean
return current_vol / avg_vol - 1 # 正值表示波动率上升
拥挤的另一表现是:不同股票的因子暴露高度趋同,即市场普遍集中于同一类股票。
具体指标:
建议以因子暴露的配对相关性中位数作为拥挤度指标,该指标对极端值不敏感、较为稳健。当中位数超过 0.6 时,宜提高警惕。
# 计算因子暴露的截面相关性
def factor_exposure_correlation(factor_exposures):
"""
factor_exposures: DataFrame, 行为股票, 列为时间
返回每个时间点的截面相关性
"""
# 计算所有股票两两之间的相关性
corr_matrix = factor_exposures.T.corr
# 取上三角矩阵的平均值(排除对角线)
upper_tri = corr_matrix.where(
np.triu(np.ones(corr_matrix.shape), k=1).astype(bool)
)
avg_corr = upper_tri.stack.mean
return avg_corr
拥挤的因子,往往伴随着高换手率。因为大家都在频繁交易,试图抢在别人前面。
具体指标:
曾观测某动量因子换手率在三个月内由 20% 升至 80%,高换手率反映追涨杀跌行为加剧、拥挤度偏高;约两个月后该因子显著失效。
注意:换手率指标应结合因子自身特性加以判断。部分因子天然高换手(如高频反转因子),部分因子天然低换手(如质量因子),不宜统一标准衡量。
因子容量,指的是一个因子在不显著降低预期收益的前提下,能够容纳的最大资金量。
测算容量的原因在于:不同资金规模适用的因子差异显著。容量较小的因子,大资金进入后将侵蚀自身 alpha。
常用的容量测算方法有两种:
这个方法的核心思想是:随着资金量增大,交易成本(冲击成本)会上升,直到吃掉所有超额收益。
步骤:
# 基于冲击成本的容量测算
def factor_capacity(factor_returns, avg_turnover, impact_model):
"""
factor_returns: 因子日收益序列
avg_turnover: 平均日换手率
impact_model: 冲击成本模型, 输入资金量返回冲击成本
"""
# 计算年化收益
annual_return = factor_returns.mean * 252
# 找到使净收益为零的资金量
def net_return(capital):
impact_cost = impact_model(capital, avg_turnover)
return annual_return - impact_cost
# 二分法求解
low, high = 1e6, 1e12 # 100万到1万亿
for _ in range(50):
mid = (low + high) / 2
if net_return(mid) > 0:
low = mid
else:
high = mid
return low
这个方法更直观:看因子持仓中,那些小市值股票的流动性是否足够。
步骤:
宜将两种方法结合——以冲击成本法估算理论容量,以持仓集中度法估算实际容量,取较小值,同时兼顾交易成本与流动性约束。
以下为实践中的注意事项:
建议为各因子设定拥挤度红灯阈值:例如波动率突变度超过 50%,或截面相关性中位数超过 0.6 时减仓,以规避拥挤风险。
每个因子均经历发现、成长、成熟与衰退四个阶段,其超额收益演变可概括为 S 型曲线。
核心观点: 因子的超额收益会随着市场参与者的增加而逐渐被稀释,直至消失。
因子生命周期曲线 时间 发现期 成长期 成熟期 衰退期 高 中 低 超额收益 学术发现 策略拥挤 收益峰值 失效拐点
该图横轴为时间,纵轴为超额收益。因子初被发现时参与者较少,收益相对稳定;学术论文发表后量化资金涌入,收益曲线陡升;当该因子被广泛采用,超额收益逐步衰减。
不同因子的衰减速度差异显著,主要影响因素如下:
| 因子类型 | 衰减速度 | 典型例子 | 原因分析 |
|---|---|---|---|
| 简单统计类 | 极快(1-2年) | 低波动、小市值 | 逻辑简单,容易被复制 |
| 基本面类 | 中等(3-5年) | 价值、质量 | 需要财报数据,门槛稍高 |
| 复杂结构类 | 较慢(5年以上) | 残差动量、行业轮动 | 逻辑复杂,实施成本高 |
| 另类数据类 | 取决于数据壁垒 | 卫星图像、供应链 | 数据获取难度决定护城河 |
经验法则: 因子衰减速度与复制成本负相关——复制成本越低,衰减越快。低波动因子计算简便,易于拥挤。
判断因子是否失效,不能仅凭回撤判定——因子回撤 20% 即宣告失效可能导致在低点退出。有效的识别方法可从以下三个维度入手:
IC(信息系数)是衡量因子预测能力的核心指标。失效的因子,IC序列会有明显变化:
import numpy as np
import pandas as pd
from scipy import stats
def detect_factor_decay(ic_series, window=60):
"""
检测因子衰减:滚动IC均值与t统计量
ic_series: 日度或月度IC序列
window: 滚动窗口
"""
rolling_mean = ic_series.rolling(window).mean
rolling_std = ic_series.rolling(window).std
rolling_t = rolling_mean / (rolling_std / np.sqrt(window))
# 判断标准:连续3个月t统计量低于1.96(95%置信水平)
decay_flag = (rolling_t < 1.96).rolling(3).sum >= 3
return rolling_mean, rolling_t, decay_flag
# 示例:某动量因子IC序列
np.random.seed(42)
ic_data = np.random.normal(0.05, 0.08, 120) # 模拟10年数据
# 最后24个月加入衰减
ic_data[-24:] = np.random.normal(0.01, 0.10, 24)
ic_series = pd.Series(ic_data)
mean, t_stat, flag = detect_factor_decay(ic_series)
print(f"最近一期t统计量: {t_stat.iloc[-1]:.2f}")
print(f"是否检测到衰减: {flag.iloc[-1]}")
最近一期t统计量: 2.40 是否检测到衰减: False
上述代码的核心逻辑为: 滚动检验 IC 的 t 统计量 。若连续数月 t 值低于 1.96,表明因子预测能力不再显著。部分因子 IC 均值仍为 0.03,但 t 统计量已降至 1.5 以下——此为典型的假性有效。
统计显著并不等同于经济有效,宜同时考察多空组合的夏普比率与最大回撤:
注意: 不要只看总收益。一个因子可能总收益还是正的,但收益来源已经变了。比如以前是选股能力,现在全靠运气——这种因子迟早出事。
此维度最易被忽视。因子失效前常伴随极端拥挤:
2019 年低波因子已出现上述信号并建议减仓;2020 年低波因子回撤超过 30%,与预期一致。
因子失效后的应对可遵循三步走策略:
不是所有回撤都是失效。先分清楚:
| 失效类型 | 特征 | 应对方式 |
|---|---|---|
| 暂时性失效 | IC波动大,但均值未变 | 等待均值回归,或加仓 |
| 结构性失效 | IC均值永久性下降 | 降低权重,寻找替代因子 |
| 制度性失效 | 市场规则改变导致 | 彻底放弃,重新设计 |
区分方法: 对因子收益作滚动回归,将其对市场与风格因子回归,检验 alpha 是否仍存在;若 alpha 消失,则为结构性失效。
确认结构性失效后,不宜一次性清仓,宜采用衰减权重法:
def decay_weighting(factor_ic, current_weight, decay_rate=0.1):
"""
因子衰减权重调整
factor_ic: 最近12个月IC均值
current_weight: 当前配置权重
decay_rate: 衰减速率
"""
# 如果IC低于阈值,开始衰减
if factor_ic < 0.02:
new_weight = current_weight * (1 - decay_rate)
else:
new_weight = current_weight
# 最低保留10%权重,防止完全错过反转
new_weight = max(new_weight, 0.1 * current_weight)
return new_weight
# 示例
current_w = 0.20 # 当前权重20%
ic_last_12m = 0.015 # 最近IC均值1.5%
new_w = decay_weighting(ic_last_12m, current_w)
print(f"调整后权重: {new_w:.2%}")
调整后权重: 18.00%
目的在于平滑过渡,避免剧烈调仓带来的冲击。若骤然清仓而因子随后反弹,将承受双向损失。
因子失效本身可应对,关键在于缺乏备选。建议每个因子均配置影子因子:
核心原则: 永远不要把所有希望寄托在一个因子上。多因子体系的意义,就是当一个因子失效时,其他因子还能撑住。
示例如下。2017 年某短期动量因子(过去 20 日收益)初建时表现良好,IC 均值 0.06,夏普比率 1.2。
2019 年 IC 开始下滑,滚动 t 检验显示 t 统计量由 3.0 降至 1.8;同期动量 ETF 大量涌现,拥挤度显著上升。
判断为结构性失效后,采取以下三项措施:
2020 年原动量因子回撤 25%,组合回撤仅 8%,残差动量承担了主要 alpha 来源。
注意事项: 因子失效后不宜通过修改参数试图挽救,例如将动量窗口由 20 日改为 30 日,往往导致过拟合并使实盘表现更差。 因子失效属于逻辑层面问题,而非参数问题 。
归纳而言,因子失效的两类常见机制——拥挤挤出与生命周期衰减——宜交叉监测、统一应对:
因子价值不仅取决于预期收益,更取决于可承载的资金规模,以及策略对环境变化的适应能力。
因子投资并非一劳永逸。市场与因子均在演变,长期存续的关键在于对拥挤风险与生命周期阶段的持续监测与动态调整。