CAPM 告诉我们:想多赚,就多承担市场风险(高 β)。但 Frazzini & Pedersen (2014) 用一份名为 Betting Against Beta(做空 Beta,简称 BAB) 的因子,把这句话钉在了墙上。他们的发现是反直觉的:低 β 股票长期跑赢高 β 股票——而且是在「做多低 β、做空高 β」、把组合 β 中性化之后,依然截获到显著正 alpha。
结论先放这:杠杆厌恶是这背后的机制,而不是传统的「高风险高收益」。在我们的自洽合成里,受杠杆约束的投资者把高 β 股票价格推高(其预期收益被压低、CAPM 斜率从理论 0.060 压平到实际的 −0.013,截距却抬到 +0.048),低 β 股票被压低(预期收益抬高)。BAB 组合(多低 β / 空高 β、各按 1/β 加杠杆)实现年化 +9.95%、波动 5.3%、Sharpe 1.88,而全市场买入持有只有 Sharpe 0.18、高 β 腿 Sharpe 0.07——这中间的落差,正是被「杠杆约束」错误定价出来的 alpha。

一、为什么高 β 没有拿到足额补偿#
CAPM 的预言很干净:证券市场线(SML)是过原点的直线
斜率就是市场风险溢价。问题是这条直线在真实数据里太平了——甚至可能是向下弯的。Frazzini-Pedersen 的解释是杠杆约束(leverage aversion):
- 很多投资者(共同基金、养老金、散户)被禁止或强烈不情愿用杠杆;
- 他们想「多配市场敞口」时,唯一的办法是买高 β 股票(一只 β=2 的股票 ≈ 自带 2 倍杠杆);
- 于是高 β 股票需求被拉高 → 价格被推高 → 未来预期收益被压低;
- 反过来,低 β 股票因为「不够刺激」被抛售 → 价格压低 → 预期收益抬高。
结果:SML 不是过原点的直线,而是截距为正、斜率偏低——低 β 被系统性抬高、高 β 被系统性压低。这正是我们图 1 看到的现象。
注意:这不是「低风险高收益」的另一种说法。它是说 即便控制 β,低 β 也拿到比 CAPM 预言更多的收益——是定价错误,不是风险补偿。
二、从零构造合成数据:把异常写进生成过程#
为了干净地演示机制,我们生成 300 只股票、240 个月(20 年)的月度超额收益。核心设定就是「SML 太平」:
import numpy as np
rng = np.random.default_rng(20260714)
N, T = 300, 240
Rf = 0.002 # 月度无风险
mu_m, sig_m = 0.005, 0.040 # 市场月度超额收益 均值/波动
C_ANOM = 0.0060 # 杠杆厌恶异常强度
beta = rng.uniform(0.3, 2.2, N) # 个股 beta 0.3~2.2
idio = rng.uniform(0.015, 0.045, N) # 特质波动
mkt_ex = rng.normal(mu_m, sig_m, T) # 市场月度超额收益
eps = rng.standard_normal((T, N)) * idio
# 关键设定:alpha = C·(1 - beta),低 beta 正、高 beta 负
alpha = C_ANOM * (1.0 - beta)
ret = alpha[None, :] + beta[None, :] * mkt_ex[:, None] + eps
excess = ret - Rfpython这里 alpha = C·(1−β) 就是「SML 截距为正、斜率偏低」的生成来源:低 β 拿到正 alpha,高 β 拿到负 alpha。注意这纯粹是人为写进去的定价错误,用来演示估计与组合逻辑——真实世界的异常来自投资者行为,落地要用真实数据库(见文末)。
三、检验 SML:斜率被压平、截距被抬高#
把个股年化超额收益对 β 做 OLS,看实际 SML:
ann_ex = excess.mean(0) * 12
A = np.vstack([np.ones(N), beta]).T
coef = np.linalg.lstsq(A, ann_ex, rcond=None)[0]
capm_int, capm_slope = coef[0], coef[1]
mkt_prem_ann = mkt_ex.mean() * 12 # 理论 SML 斜率
print(capm_slope, capm_int, mkt_prem_ann)
# 实际斜率 -0.0130, 截距 +0.0482, 理论斜率 +0.060python三个数字连起来就是杠杆厌恶的证据:
- 理论斜率 = +0.060:如果市场有效,SML 就该这么陡;
- 实际斜率 = −0.013:不仅不陡,还略微向下——高 β 完全没有按 β 线性拿到更多收益;
- 实际截距 = +0.048:所有股票(即便 β=0)都被抬高了 4.8% 年化,这是低 β 端被错误定价最直观的体现。
图 1 里灰色点是 300 只个股,红线是理论 SML(陡),绿虚线是实际 SML(平且上移)——两条线之间的「缺口」,就是被杠杆约束压低/抬高的 alpha。
四、beta 十分位:高 β 实际收益远低于 CAPM 预测#
把 300 只股票按 β 切成 10 个十分位,比较「实际年化收益」与「CAPM 预测收益 = β × 市场溢价」:
order = np.argsort(beta)
deciles = np.array_split(order, 10)
dec_ann = np.array([excess[:, d].mean(1).mean() * 12 for d in deciles])
dec_beta = np.array([beta[d].mean() for d in deciles])
dec_pred = dec_beta * mkt_prem_ann # CAPM 预测
alpha_by_dec = dec_ann - dec_predpython结果一览(十分位从低 β 到高 β):
| β 十分位 | 实际年化 | CAPM 预测 | 实际 alpha |
|---|---|---|---|
| 1(最低 β) | +4.5% | +2.4% | +2.0% |
| 5 | +2.9% | +6.9% | −4.0% |
| 10(最高 β) | +2.2% | +12.7% | −10.5% |
低 β 十分位实际拿到 4.5%,而 CAPM 只预言 2.4%——正的 2.0% alpha;高 β 十分位实际只有 2.2%,CAPM 却预言 12.7%——被压低了 10.5%。图 2 把这两条柱子并排画出来,缺口一目了然。

注意一个常被误读的点:高 β 组实际收益(2.2%)依然高于无风险,只是远低于 CAPM 预言。杠杆厌恶因子赚的不是「高 β 亏钱」,而是「高 β 没赚到它该赚的钱」与「低 β 多赚了」之间的落差。
五、构造 BAB 组合:多低 β、空高 β,各按 1/β 加杠杆#
Frazzini-Pedersen 的 BAB 因子做法很巧妙:只取两端,并让两条腿各自的 β 都放大到 1,这样组合整体 β ≈ 0(市场中立),截获的是纯 alpha 而非市场方向。
D1 = deciles[0] # 低 beta 十分位
D10 = deciles[9] # 高 beta 十分位
beta_D1, beta_D10 = beta[D1].mean(), beta[D10].mean()
ex_D1 = excess[:, D1].mean(1) # 低 beta 腿月度超额(等权)
ex_D10 = excess[:, D10].mean(1) # 高 beta 腿月度超额(等权)
lev_long = 1.0 / beta_D1 # ≈ 2.45
lev_short = 1.0 / beta_D10 # ≈ 0.47
bab_ex = lev_long * ex_D1 - lev_short * ex_D10
bab_beta = lev_long * beta_D1 - lev_short * beta_D10 # ≈ 0
bab_ann = bab_ex.mean() * 12
bab_vol = bab_ex.std(ddof=1) * np.sqrt(12)
bab_shp = bab_ann / bab_vol
# BAB: 年化 +9.95%, 波动 5.3%, Sharpe 1.88, beta ≈ 0python为什么各按 1/β 加杠杆?因为低 β 腿本身市场敞口只有 0.41,乘以 2.45 之后变成 1;高 β 腿市场敞口 2.11,乘以 0.47 之后也变成 1。多空相减,市场敞口几乎抵消(β≈0),剩下的就是两条腿的 alpha 落差。
六、结果:BAB 碾压市场与高 β 腿#
把 BAB 与全市场买入持有、单独做多高 β 腿对比:
bab_cum = np.cumprod(1 + bab_ex)
mkt_cum = np.cumprod(1 + excess.mean(1))
hb_cum = np.cumprod(1 + ex_D10)python| 组合 | 年化 | 波动 | Sharpe | β |
|---|---|---|---|---|
| BAB(多低 β / 空高 β) | +9.95% | 5.3% | 1.88 | ≈0 |
| 全市场等权买入持有 | +3.20% | 18.0% | 0.18 | 1.0 |
| 高 β 腿(做多 D10) | +2.18% | 30.8% | 0.07 | 2.11 |
BAB 用 1/3 的波动,拿到了市场 3 倍的 Sharpe,且几乎不暴露市场方向。图 3 的累积净值曲线里,BAB(绿)一路平稳上行,市场和做多高 β(灰/红)则大幅波动、长期落后。

直觉校验:如果 BAB 只是「低波动异象」的换皮,那它应该和市场负相关或低相关;但这里的 BAB 是多空 β 中性,它赚的是「SML 斜率被压平」的结构性错误定价,和低波动因子的来源不同(低波动因子多为单边多头低 β,仍带方向敞口)。
七、六类真实陷阱(高阶必读)#
1. 幸存者偏差与数据覆盖。 我们用 300 只「始终存活」的股票。真实世界里高 β 股票更容易在崩盘中退市,幸存者偏差会系统性高估高 β 的实际收益、削弱 BAB 信号。落地必须用 point-in-time 无幸存者数据库(如 CRSP 全样本)。
2. 杠杆约束的假设强度。 模型把异常完全归因于杠杆约束。但低 β 跑赢也可能是杠杆供给有限 + 散户偏好彩票股等多因素叠加。BAB 在 2008 后、低利率时代强度明显变化——它不是常量异常。
3. 1/β 加杠杆的实务不可行。 低 β 腿要加 2.45 倍杠杆、且要能做空高 β 腿。真实里融资约束、做空成本(借券费率、难以借到)、保证金追缴,会直接吃掉 alpha。我们完全没有建模这些成本。
4. 流动性与规模。 低 β 股票常是小盘、低流动性标的,建仓冲击成本可能让理论 Sharpe 1.88 在真实里大幅缩水。BAB 的实际容量远低于论文里的大盘版本。
5. 回归窗口与 β 估计误差。 β 用全样本 OLS 估计,存在估计误差 + 时变 β。真实里要用滚动窗口或收缩估计,且 β 会 regime switch,固定 β 分位会漂移。
6. 截距为正的「伪异常」风险。 我们的 SML 截距 +0.048 部分来自生成时把异常写进了 alpha。真实数据里,若全市场收益序列本身有未被风险因子解释的共同漂移,截距可能被错误解读为 alpha。务必用多因子模型(FF3/FF5)后再看 BAB 的截距是否仍显著。
八、代码清单与落地路径#
完整可运行脚本已生成:generate_leverage_aversion_images.py,含全部数据生成、SML 检验、十分位与 BAB 组合逻辑(配图同源)。落地到真实研究时:
- 用 CRSP/Compustat 取美国股票的月度收益与市值;
- 用过去 3 年滚动 OLS 估 β,避免时变偏差;
- 按 NYSE 分位点切 β 十分位,每月再平衡;
- 多空两端各按 1/β 缩放,扣除借券费率与交易成本后看净 alpha;
- 跑 FF5 回归,确认 BAB 截距在控制规模/价值/盈利/投资后仍显著。
BAB 的价值不在于「无脑买低 β」,而在于它证伪了 CAPM 的线性定价,暴露出「杠杆约束」本身就是一类可被定价、可被交易的风险/错误定价来源。理解它,比复制它更重要。
本文为量化专栏第 N 篇。所有数值来自自洽合成,仅用于演示估计与组合机制;真实异常强度、显著性请以无幸存者偏差数据库为准。