02-因子溢价来源

预计学习时间:2-3 小时

难度:⭐⭐⭐⭐

核心问题:因子为什么能预测收益?是因为你承担了风险,还是因为大多数人犯了错误?


从一个根本问题出发

假设你发现”便宜的股票长期收益更高”——这个现象已经被学术界验证了几十年。

但关键问题是:为什么?

是市场犯了错误(便宜的股票被低估了),还是便宜的股票确实更”危险”(困境公司、破产风险),投资者只是得到了应有的补偿?

这个”为什么”的问题,决定了你对因子投资的态度:

  • 如果因子有效是因为风险补偿,那因子的溢价应该是稳定的、长期的
  • 如果因子有效是因为行为偏差,那当投资者”学习”了之后,溢价可能消失
  • 如果因子有效只是数据挖掘,那它在样本外根本不成立

本章深入讨论因子溢价的三种主要来源,以及由此衍生的重要问题。


一、风险补偿理论

1.1 核心思想:因子有效是因为你承担了某种系统性风险

这是最”正统”的解释,也是最被学术界接受的理论。

白话版本:你因为承担了某种风险,所以获得了额外补偿。因子溢价不是”捡便宜”,而是”风险的价格”。

1.2 CAPM:一个因子的世界

CAPM 是一切因子模型的起点。

它说:股票的预期收益只取决于一个风险——市场风险(系统性风险)

其中:

  • :股票 的预期收益
  • :无风险利率
  • :股票 对市场风险的暴露
  • :市场风险溢价

CAPM 的含义:Beta 越高的股票,承担的市场风险越大,预期收益越高。这个关系是线性的。

但 CAPM 有一个问题:现实中,很多高 Beta 的股票并没有获得更高的收益(低波动异象),而且很多与 Beta 无关的变量也能预测收益(价值、规模、动量)。

1.3 多因子模型:多个风险源,每个都有补偿

既然一个因子不够,那就加更多。

Fama-French 三因子模型(1993):

  • MKT:市场因子(和 CAPM 一样)
  • SMB(Small Minus Big):小公司 - 大公司的收益差
  • HML(High Minus Low):高 B/P - 低 B/P 的收益差

Fama-French 五因子模型(2015):

新增:

  • RMW(Robust Minus Weak):高盈利 - 低盈利
  • CMA(Conservative Minus Aggressive):保守投资 - 激进投资

多因子模型的核心逻辑:每个因子代表一种系统性风险。你暴露于某种风险,就会得到相应的补偿。

1.4 APT:套利定价理论

Ross(1976)提出的 APT 比 CAPM 更一般化。它不假设市场组合是最优的,而是说:

如果两个资产的因子暴露完全相同,它们的预期收益也应该相同。如果不相同,套利者就会买入便宜的、卖出贵的,直到价格调整到位。

其中 是因子 的风险溢价, 是资产 对因子 的暴露。

APT 不需要知道因子是什么——只要存在能驱动收益的系统性因子,APT 就成立。这是一个更灵活的框架。

1.5 Python:用模拟数据验证多因子模型

import numpy as np
import pandas as pd
import statsmodels.api as sm
 
np.random.seed(42)
 
# ============================================================
# 模拟 300 只股票 60 个月的数据
# ============================================================
n_stocks = 300
n_months = 60
 
# 模拟因子收益(每月随机,但有均值回归)
factor_names = ['MKT', 'SMB', 'HML', 'UMD']
true_premiums = [0.005, 0.003, 0.004, 0.006]  # 真实的因子溢价
 
factor_returns = np.zeros((n_months, len(factor_names)))
for t in range(n_months):
    for k in range(len(factor_names)):
        # 因子收益围绕真实溢价波动
        factor_returns[t, k] = (true_premiums[k]
                                + np.random.normal(0, 0.02))
 
# 模拟股票的因子暴露
betas = np.random.normal(0, 0.5, (n_stocks, len(factor_names)))
 
# 股票收益 = 因子暴露 × 因子收益 + 特质收益
stock_returns = np.zeros((n_months, n_stocks))
for t in range(n_months):
    stock_returns[t] = betas @ factor_returns[t] + np.random.normal(0, 0.05, n_stocks)
 
# ============================================================
# Fama-MacBeth 回归验证因子溢价
# ============================================================
# 第一步:每个月做截面回归
monthly_coefficients = []
for t in range(n_months):
    y = stock_returns[t]
    X = sm.add_constant(betas)
    model = sm.OLS(y, X).fit()
    monthly_coefficients.append(model.params)
 
coefficients = np.array(monthly_coefficients)
 
# 第二步:对系数取时间序列平均
print("=" * 60)
print("Fama-MacBeth 因子溢价估计")
print("=" * 60)
print(f"{'因子':>8} {'真实溢价':>10} {'估计溢价':>10} {'t 统计量':>10}")
print("-" * 40)
for k, name in enumerate(factor_names):
    mean_coef = np.mean(coefficients[:, k + 1])  # +1 跳过截距
    std_coef = np.std(coefficients[:, k + 1], ddof=1)
    t_stat = mean_coef / (std_coef / np.sqrt(n_months))
    print(f"{name:>8} {true_premiums[k]:10.4f} {mean_coef:10.4f} {t_stat:10.2f}")
 
print("\n结论: 如果 t 统计量 > 2,说明该因子的溢价在统计上显著")

1.6 风险补偿理论的局限性

问题说明
价值因子是风险吗?价值股=困境公司?但很多价值股经营很好
动量的风险是什么?动量崩盘风险?但崩盘的概率和频率无法精确量化
低波动因子的风险?低波动=低风险,但收益更高——这和风险补偿理论矛盾
因素太多如果每种收益差异都能用”某种风险”来解释,理论就失去了约束力

风险补偿理论最大的问题是”后验性”:先发现了因子,再去找”合理”的风险解释。这削弱了理论的预测能力。


二、行为金融解释

2.1 核心思想:因子有效是因为大多数人犯了心理偏差

如果风险补偿理论说”市场是对的,你得到了风险补偿”,那行为金融说:“市场经常犯错,因子溢价来自对错误的纠正”。

2.2 价值因子:投资者过度反应

故事:投资者看到一家公司连续几年业绩下滑,就认为”这家公司完了”,过度抛售导致价格过低。等到公司恢复增长,价格纠偏,价值投资者获利。

相关心理偏差

  • 锚定效应:投资者锚定过去的表现,低估了均值回归的可能性
  • 外推偏差:把过去的趋势外推到未来
  • 损失厌恶:不愿意卖出亏损的成长股(它们曾经是好公司)

2.3 动量因子:信息扩散缓慢

故事:好公司的利好消息不会一天就被市场完全消化。投资者需要时间来接收、理解、反应。在这个过程中,价格逐步上涨,形成了动量。

相关心理偏差

  • 处置效应:投资者倾向于”卖出赚钱的、持有亏钱的”,导致好的股票被过早卖出(减缓了上涨速度),坏股票被持有太久(减缓了下跌速度)
  • 确认偏差:投资者倾向于寻找支持自己观点的信息
  • 信息扩散的层级性:机构投资者先反应,散户后反应

2.4 规模因子:覆盖不足

故事:分析师和机构投资者主要覆盖大公司。小公司缺少研究覆盖和媒体关注,信息不对称更大,定价效率更低。

相关心理偏差

  • 注意力偏差:人们只关注”有名”的东西
  • 羊群效应:机构投资者集中在少数大股票上

2.5 风险补偿 vs 行为金融:一个统一的框架

因子风险补偿解释行为金融解释
价值困境公司的经营风险投资者对坏消息过度反应
规模小公司的融资和破产风险小公司被分析师和机构忽视
动量动量崩盘的尾部风险信息扩散缓慢 + 处置效应
质量高质量公司的可持续性不确定投资者忽视”枯燥”的好公司
低波动(风险补偿理论无法解释)杠杆约束 + 基准竞争 + 彩票偏好

实际中,两种解释可能同时成立。某个因子的溢价可能部分来自风险补偿,部分来自行为偏差。区分两者的比例很难,但理解两种解释都有助于你判断因子的未来有效性。


三、市场摩擦

除了风险补偿和行为偏差,还有一些更”机械”的原因导致因子溢价。

3.1 流动性溢价

不好卖的资产,持有成本高。你需要补偿:

  • 买卖价差
  • 市场冲击成本
  • 持仓等待时间

白话:流动性好的股票大家都愿意买,价格被推高;流动性差的股票没人愿意买,价格被压低。持有后者,你就获得了流动性溢价。

3.2 卖空限制

有些股票不能做空(或做空的成本极高)。这意味着:即使投资者认为某只股票被高估了,他也无法通过做空来纠正价格。高估的价格就维持着。

影响

  • 被高估的股票(通常是成长股、热门股)价格持续偏高
  • 相对地,被低估的股票(价值股)就有正溢价
  • 这是价值因子溢价的重要来源之一

3.3 搜索成本

投资者的时间和精力有限,不可能研究所有股票。信息获取和处理是有成本的。

影响

  • 投资者倾向于关注热门股票和知名公司
  • 被忽视的股票(小公司、冷门股)可能有更大的错误定价
import numpy as np
import pandas as pd
 
np.random.seed(42)
 
# ============================================================
# 模拟搜索成本对因子溢价的影响
# ============================================================
n_stocks = 500
 
# 每只股票的信息不对称程度(越大越难获得信息)
info_cost = np.random.uniform(0, 1, n_stocks)
 
# 真实的内在价值
true_value = np.random.normal(100, 20, n_stocks)
 
# 市场价格 = 真实价值 + 定价误差
# 信息成本越高,定价误差越大
pricing_error = np.random.normal(0, 10 * info_cost, n_stocks)
market_price = true_value + pricing_error
 
# 错误定价的绝对值
mispricing = np.abs(pricing_error)
 
# 按 info_cost 分组
df = pd.DataFrame({
    'info_cost': info_cost,
    'mispricing': mispricing,
    'market_price': market_price
})
df['cost_group'] = pd.qcut(df['info_cost'], 5,
                           labels=['极低', '低', '中', '高', '极高'])
 
print("搜索成本 vs 错误定价:")
print(df.groupby('cost_group')['mispricing'].describe()[['count', 'mean', 'std']])
 
# 结论:信息成本越高的股票,错误定价越大
# → 持有这些股票的投资者获得了"搜索成本溢价"

四、数据挖掘 vs 真实 Alpha

4.1 核心问题

你发现了一个”新因子”——在样本内回测表现很好。问题是:这是真实的 Alpha,还是你只是”运气好”?

4.2 多重检验问题

假设你试了 1000 个因子,每个因子的 p 值阈值设为 0.05。

在零假设下(所有因子都无效),你期望 个因子”显著”。但这些因子其实全是假的。

白话:试的越多,“碰巧”显著的越多。如果你在 1000 个因子中选最好的 10 个,当然很好看——但这是过拟合。

4.3 如何区分真实 Alpha 和数据挖掘?

方法原理具体做法
样本外检验在”没见过”的数据上验证留出 30% 数据做测试
经济直觉有理论解释的因子更可信因子是否有经济学逻辑?
多市场验证在不同市场/时间段都有效A 股有效的因子在美股也有效?
调整显著性水平考虑多重检验Bonferroni 校正:
因子生存期存活时间越长越可信因子被发现后是否持续有效?

4.4 Python:模拟多重检验问题

import numpy as np
import pandas as pd
 
np.random.seed(42)
 
# ============================================================
# 模拟 1000 个"假因子"
# ============================================================
n_factors = 1000
n_stocks = 300
n_months = 60
 
# 模拟数据:所有因子都是随机噪声,没有真实预测力
factor_returns = np.random.normal(0, 0.001, n_months)  # 每月市场收益
stock_returns = np.random.normal(0.01, 0.06, (n_months, n_stocks))
 
# 对每个假因子做 Fama-MacBeth 回归
import statsmodels.api as sm
 
significant_count = 0
t_stats_all = []
 
for i in range(n_factors):
    # 随机生成因子暴露(每次都不同 = 试 1000 个不同的因子)
    exposure = np.random.normal(0, 0.5, (n_stocks, n_months)).T
 
    # Fama-MacBeth:每月截面回归
    monthly_coefs = []
    for t in range(n_months):
        y = stock_returns[t]
        X = sm.add_constant(exposure[t])
        try:
            model = sm.OLS(y, X).fit()
            monthly_coefs.append(model.params[1])
        except:
            continue
 
    if len(monthly_coefs) > 10:
        mean_coef = np.mean(monthly_coefs)
        std_coef = np.std(monthly_coefs, ddof=1)
        t_stat = mean_coef / (std_coef / np.sqrt(len(monthly_coefs)))
        t_stats_all.append(t_stat)
 
        # 传统标准:|t| > 2 就认为显著
        if abs(t_stat) > 2:
            significant_count += 1
 
t_stats_all = np.array(t_stats_all)
print("=" * 50)
print("多重检验问题演示")
print("=" * 50)
print(f"真实有效因子数: 0(全部是随机噪声)")
print(f"发现'显著'因子数: {significant_count} / {n_factors}")
print(f"最大 t 统计量: {np.max(np.abs(t_stats_all)):.2f}")
print(f"最小 t 统计量: {np.min(np.abs(t_stats_all)):.2f}")
print(f"\n如果你只报告显著的因子,就是在欺骗自己")
 
# Bonferroni 校正
bonferroni_threshold = 2.58 / np.sqrt(n_factors)  # 更严格的阈值
bonferroni_significant = np.sum(np.abs(t_stats_all) > bonferroni_threshold)
print(f"\nBonferroni 校正后 (α = 0.05/{n_factors}):")
print(f"  校正后阈值: |t| > {bonferroni_threshold:.2f}")
print(f"  校正后显著因子数: {bonferroni_significant}")

五、因子拥挤(Crowding)

5.1 什么是因子拥挤?

因子拥挤是指太多投资者使用同一个因子,导致因子的 alpha 被稀释。

白话版本:如果你发现了一个好因子,而且只有你一个人用,你赚大钱。但如果所有人都用了这个因子,你就赚不到钱了——因为所有人都买一样的股票,价格已经被推到合理水平了。

5.2 因子拥挤的后果

后果说明
Alpha 衰减因子收益逐渐降低,趋近于零
回撤加大当投资者同时卖出时,因子集中崩盘
波动率上升拥挤因子的收益波动率增大
反转风险拥挤因子可能突然反转

5.3 如何检测因子拥挤?

import numpy as np
import pandas as pd
 
np.random.seed(42)
 
# ============================================================
# 模拟因子拥挤的信号
# ============================================================
n_months = 120  # 10 年
 
# 模拟因子收益
# 前 5 年:不拥挤,因子有稳定溢价
# 后 5 年:越来越拥挤,溢价衰减,波动加大
factor_returns = np.zeros(n_months)
 
for t in range(n_months):
    if t < 60:
        # 不拥挤阶段:稳定溢价
        factor_returns[t] = 0.005 + np.random.normal(0, 0.02)
    else:
        # 越来越拥挤:溢价衰减,波动加大
        crowding = (t - 60) / 60  # 拥挤度从 0 到 1
        premium = 0.005 * (1 - 0.8 * crowding)  # 溢价衰减 80%
        vol = 0.02 * (1 + crowding)              # 波动率增加
        factor_returns[t] = premium + np.random.normal(0, vol)
 
# ============================================================
# 检测拥挤的指标
# ============================================================
# 1) 滚动 12 个月 Sharpe
rolling_sharpe = pd.Series(factor_returns).rolling(12).apply(
    lambda x: np.mean(x) / np.std(x) * np.sqrt(12) if np.std(x) > 0 else 0,
    raw=True
)
 
# 2) 滚动 12 个月最大回撤
cumulative = (1 + pd.Series(factor_returns)).cumprod()
rolling_max = cumulative.rolling(12, min_periods=1).max()
rolling_drawdown = (cumulative - rolling_max) / rolling_max
 
# 3) 滚动相关性:因子收益之间的相关性上升(说明大家在交易同样的东西)
# 这里用因子收益的自相关作为代理
rolling_autocorr = pd.Series(factor_returns).rolling(12).apply(
    lambda x: pd.Series(x).autocorr(lag=1) if len(x) > 2 else 0,
    raw=True
)
 
# ============================================================
# 输出
# ============================================================
print("=" * 50)
print("因子拥挤检测")
print("=" * 50)
print(f"\n前 5 年(不拥挤):")
print(f"  年化收益: {np.mean(factor_returns[:60]) * 12:.2%}")
print(f"  年化波动: {np.std(factor_returns[:60]) * np.sqrt(12):.2%}")
print(f"  Sharpe: {np.mean(factor_returns[:60]) / np.std(factor_returns[:60]) * np.sqrt(12):.2f}")
 
print(f"\n后 5 年(拥挤):")
print(f"  年化收益: {np.mean(factor_returns[60:]) * 12:.2%}")
print(f"  年化波动: {np.std(factor_returns[60:]) * np.sqrt(12):.2%}")
print(f"  Sharpe: {np.mean(factor_returns[60:]) / np.std(factor_returns[60:]) * np.sqrt(12):.2f}")
 
print(f"\n拥挤指标变化:")
print(f"  前 5 年平均 Sharpe: {rolling_sharpe[:60].mean():.2f}")
print(f"  后 5 年平均 Sharpe: {rolling_sharpe[60:].mean():.2f}")

5.4 应对因子拥挤

  1. 因子多样性:不要只押注一个因子,分散到多个不相关的因子
  2. 动态因子配置:根据拥挤度调整因子权重
  3. 寻找新因子:在主流因子拥挤之前,研究更细分的因子
  4. 交易频率差异化:避免和拥挤的资金在同一时间交易

六、因子轮动

6.1 核心思想

不同因子在不同的经济环境下表现不同。因子轮动就是根据经济环境动态调整因子配置。

6.2 经济周期与因子的关系

经济阶段特征表现好的因子表现差的因子
复苏初期增长加速、利率低位动量、规模价值、低波动
复苏后期增长见顶、利率上升价值、质量规模、低波动
衰退初期增长放缓、利率高位低波动、质量动量、规模
衰退后期增长低迷、利率下降价值、动量低波动

6.3 价值 vs 成长的轮动

这是最常见的因子轮动。价值股和成长股的相对表现会随着利率环境变化:

  • 利率上升:折现率上升 → 远期现金流的现值下降 → 成长股受损(它们的价值更多来自远期)→ 价值股相对受益
  • 利率下降:折现率下降 → 远期现金流的现值上升 → 成长股受益 → 价值股相对受损
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
 
np.random.seed(42)
 
# ============================================================
# 模拟 10 年的价值/成长轮动
# ============================================================
n_months = 120
 
# 模拟利率周期(正弦波 + 噪声)
interest_rate_cycle = np.sin(np.linspace(0, 3 * np.pi, n_months)) * 0.5
rate_change = np.diff(np.concatenate([[0], interest_rate_cycle]))
 
# 价值因子收益:利率上升时表现好
value_returns = 0.003 + 0.01 * rate_change + np.random.normal(0, 0.02, n_months)
 
# 成长因子收益:利率下降时表现好
growth_returns = 0.003 - 0.01 * rate_change + np.random.normal(0, 0.02, n_months)
 
# 累计收益
value_cum = (1 + pd.Series(value_returns)).cumprod()
growth_cum = (1 + pd.Series(growth_returns)).cumprod()
 
print("价值 vs 成长轮动(模拟 10 年):")
print(f"  价值因子累计收益: {value_cum.iloc[-1] - 1:.2%}")
print(f"  成长因子累计收益: {growth_cum.iloc[-1] - 1:.2%}")
print(f"\n  相关系数: {np.corrcoef(value_returns, growth_returns)[0,1]:.3f}")
print("  (价值和成长通常负相关,这是轮动的基础)")

6.4 因子轮动的风险

  1. 宏观指标滞后:你用到的经济数据有延迟,等你确认经济阶段时,轮动可能已经发生了
  2. 过度交易:频繁轮动会产生大量交易成本
  3. 非线性关系:经济阶段和因子的关系不是稳定的,历史规律可能失效

七、跨市场因子可移植性

7.1 核心问题

一个在美股有效的因子,在 A 股、港股、欧洲市场也有效吗?

7.2 因子的跨市场有效性

因子美股A 股欧洲日本新兴市场
价值
规模
动量
质量
低波动

关键发现

  1. 价值和规模在全球都比较稳健
  2. 动量在发达市场很强,但在 A 股和日本较弱(短期反转更明显)
  3. 低波动在 A 股特别有效(A股散户多,偏好”暴富”股票,推高高波动股票价格)

7.3 为什么跨市场有效性不同?

原因说明
投资者结构A 股散户多,美股机构多 → 行为偏差类型不同
做空限制A 股做空难 → 错误定价更难被纠正
信息环境发达市场信息披露更完善 → 错误定价空间更小
制度差异涨跌停、T+1 等制度影响因子实现方式
文化因素不同文化对风险的偏好不同

7.4 跨市场研究的建议

  1. 不要直接照搬:美股的因子参数不能直接用于 A 股
  2. 本地化调整:调整因子构造方法以适应本地市场特征
  3. 样本外验证:在每个市场独立验证因子的有效性
  4. 理解机制:理解因子在特定市场有效的机制,而不是只看结果

小结

问题主要解释
因子为什么有效?风险补偿 + 行为偏差 + 市场摩擦(三者共存)
是风险还是错误定价?因子而异,但多数因子两者兼有
是真实 Alpha 还是数据挖掘?需要多重检验校正、样本外验证、经济直觉
因子会失效吗?会,拥挤导致 alpha 衰减
如何管理因子?因子多样性、动态配置、拥挤监控

最核心的教训:因子投资不是”找到一个永远有效的公式”。因子是一个有经济学基础的、会在特定环境下失效的、需要持续管理的投资框架。

→ 下一章:03-因子研究方法论 —— 从统计角度验证因子是否真的有效