返回交易笔记
TR Day 8

Fama-French 三因子论文精读

CAPM 失效证据 → FF 1992 → FF 1993 三因子 → FF 2015 五因子 → 后续批评

2026-05-17
Phase 1: 基础与工具链
FamaFrenchFF3FF5SMBHMLFactorInvestingCrossSection

日期: 2026-05-17 方向: 个人量化交易 / 因子投资 阶段: Phase 1: 基础与工具链 标签: #FamaFrench #FF3 #FF5 #SMB #HML #FactorInvesting #CrossSection


今日目标

类型内容
学习CAPM 失效证据 → FF 1992 → FF 1993 三因子 → FF 2015 五因子 → 后续批评
实操从 Kenneth French 数据库下载 FF3 月度因子,跑一只股票(AAPL)的三因子回归
产出TR-DAY8 笔记 + 一段可复现的 Python 回归脚本 + 对 α / β / s / h 的解读

一、为什么从 Fama-French 开始

Week 2 的开篇必须是 Fama-French,原因不在于这是「最赚钱的因子」(事实上 1990s 以后它的 alpha 在持续衰减),而在于它是现代因子投资范式的起点。后面我们要学的 momentum(Jegadeesh-Titman 1993)、low-vol(Ang-Hodrick 2006)、quality(Asness-Frazzini-Pedersen 2013)、defensive、carry、investment 等等,都是在「Fama-French 的方法论框架」之内做的扩展:

Fama-French 范式的三件套
─────────────────────────────────────────
(1) 找出一个能解释 cross-section returns 的财务/价格特征 X
(2) 按 X 把全市场股票排序、分组、构造 long-short portfolio
(3) 把这个 portfolio 的 returns 当成一个新的「因子」,加入定价模型

掌握 FF3 = 拿到了打开后面 30 年所有因子论文的钥匙。如果跳过 FF 直接学动量或机器学习因子,会发现 paper 里反复出现的 SMB、HML、α、t-stat 全是黑话。

更深层的意义:FF3 是金融经济学第一次成功把 noise 抽象成 signal 的范例。CAPM 时代,研究者眼中的市场 returns 只有一个维度(市场风险溢价);FF 之后,returns 被拆成了多维向量,每个维度对应一种系统性风险来源。这种「拆维」的思想在所有量化领域都有迁移价值——10 年金融 PM 视角看,这跟把「用户行为」从「DAU」拆成「new / resurrected / churned / loyal」是同一种抽象动作。


二、背景:CAPM 失效的证据(1980s)

2.1 CAPM 在说什么

资本资产定价模型(Sharpe 1964 / Lintner 1965)的核心断言:

E[R_i] - R_f = β_i · (E[R_m] - R_f)

只有市场 beta 决定预期回报;除了 beta 之外的任何特征
(市值大小、估值高低、行业、动量),都不应该有定价能力。

这是一个非常美的理论——单变量模型解释整个截面。如果它是对的,散户唯一要做的事情就是选好杠杆。

2.2 1980s 的实证打脸

整个 1980s,学界用越来越好的数据库(CRSP、Compustat)反复检验 CAPM,结果很尴尬:

异象论文内容
Size effectBanz (1981)小盘股长期跑赢大盘股,扣除 beta 后仍有显著 alpha
Value effectStattman (1980) / Rosenberg-Reid-Lanstein (1985)高 B/M(账面市值比)股票跑赢低 B/M
Earnings yieldBasu (1977, 1983)低 P/E 股票跑赢高 P/E
LeverageBhandari (1988)高杠杆公司收益更高(控制 beta 后)
January effectKeim (1983)1 月份小盘股异常跑赢

到 1980s 末,市场上已经积累了一堆 CAPM 不能解释的「异象」(anomalies)。但这些异象散落在不同论文里,没有人把它们整合成一个新的、可操作的框架。

2.3 Fama-French 1992:把异象做成可用的实证模型

Eugene Fama 与 Kenneth French 是这件事的整合者。他们 1992 年发表在 Journal of Finance 的 "The Cross-Section of Expected Stock Returns" 是金融实证经济学最高引用的论文之一。

核心发现:

样本:NYSE + AMEX + NASDAQ,1963 年 7 月 - 1990 年 12 月
方法:Fama-MacBeth 横截面回归

结论 1:beta 单独解释力 ≈ 0
        当 size 和 B/M 一起进回归时,beta 的 t-stat 不显著
结论 2:size(log market cap)显著负相关
        小公司未来收益更高(控制 B/M 后仍然成立)
结论 3:B/M(账面市值比)显著正相关
        高 B/M("value")股票未来收益更高(控制 size 后仍然成立)
结论 4:size 和 B/M 联合起来,把 leverage、E/P 等异象都吸收掉了

这篇论文的杀伤力在于:它没有提出新理论,只是把既有数据彻底洗了一遍。CAPM 信徒在它面前只能选三种态度:

  1. 否认数据(很难)
  2. 说这是 data mining(但 size 和 B/M 在 out-of-sample 也活下来了)
  3. 接受 CAPM 不完整,需要新的模型

学界选了第三条。


三、Fama-French 1993:三因子模型登场

1993 年 Fama-French 又发了一篇 Journal of Financial Economics 的 "Common risk factors in the returns on stocks and bonds"。这篇是我们今天要重点精读的——它把 1992 论文的发现,变成了可以下载、可以回归、可以做投资组合分析的 portfolio-level factors

3.1 模型公式

R_i - R_f  =  α_i  +  β_i · (R_m - R_f)  +  s_i · SMB  +  h_i · HML  +  ε_i

含义:

符号名字解释
R_i - R_f超额收益资产 i 相对无风险利率的超额回报
R_m - R_fMKT(市场因子)市场整体超额回报,CAPM 里就有
SMBSmall Minus Big小盘股相对大盘股的超额回报
HMLHigh Minus Low高 B/M(价值)相对低 B/M(成长)的超额回报
α_i截距三因子无法解释的部分;理想中应为 0
β_i, s_i, h_i因子载荷资产 i 对各因子的暴露程度
ε_i残差特异性风险

3.2 SMB 和 HML 是怎么造出来的(关键细节)

很多人能背公式,但讲不清 SMB / HML 怎么从原始股票数据构造出来的。这一步是 FF 方法论的精华,也是后面所有因子论文的 cookbook。

步骤

步骤 1:每年 6 月底取一次快照
─────────────────────────────────────────────
- 用所有 NYSE 股票计算 size 中位数(仅 NYSE,避免 NASDAQ 小票拉低)
- 把所有股票(NYSE + AMEX + NASDAQ)按这个中位数分成 Small / Big 两组

步骤 2:同样时间点
─────────────────────────────────────────────
- 用所有 NYSE 股票计算 B/M 的 30% 和 70% 分位
- 把所有股票按这两个分位分成 Low / Medium / High 三组

步骤 3:交叉成 2×3 = 6 个 portfolio
─────────────────────────────────────────────
                Low B/M     Medium B/M     High B/M
Small           S/L         S/M            S/H
Big             B/L         B/M            B/H

步骤 4:每个 portfolio 内按市值加权计算月度收益
─────────────────────────────────────────────
(不是等权,是 cap-weighted,避免微小盘票主导)

步骤 5:构造 SMB 和 HML
─────────────────────────────────────────────
SMB = (S/L + S/M + S/H) / 3 - (B/L + B/M + B/H) / 3
HML = (S/H + B/H) / 2 - (S/L + B/L) / 2

为什么是 2×3 而不是 5×5? 因为 5×5 会把每组样本量切得过小,统计噪声太大。2×3 是 Fama-French 平衡 sample size 与 dimension 之后选的最小有效切割。

为什么 size 用 50/50 而 B/M 用 30/40/30? 因为 size 分布相对均匀,B/M 分布偏态严重(成长股多、价值股少),需要更不对称的切分才能让每组有合理样本量。

为什么用 NYSE 分位而不是全样本分位? 这是个常被忽视的细节。NASDAQ 小票数量极多,如果用全样本分位,"Small" 组里几乎全是 NASDAQ 微小盘票,"Big" 组反而会包括 NASDAQ 中盘票。用 NYSE 分位避免这种 over-sampling 偏差。

3.3 三因子的实证表现(FF 1993)

FF 1993 论文里把全市场股票按 size 和 B/M 切成 25 个 portfolio,跑三因子回归:

模型25 portfolio 的平均 R²α 显著的数量
CAPM (单因子)约 0.70大部分显著(说明模型不对)
三因子约 0.93大部分不显著

含义:三因子加进去之后,几乎所有截面变化都被解释了。这是「实证胜利」。


四、风险解释 vs 行为解释(至今未决的问题)

FF3 在实证上赢了,但在理论解释上,从 1993 年到今天还在吵:为什么 size 和 value 会有溢价?

4.1 风险派(Fama-French 自己的立场)

论点内容
Distress risk高 B/M 公司往往是经营困难、临近破产的;投资者要求更高回报
Liquidity risk小盘股流动性差,遇到危机时套现困难
Cash flow risk价值股的现金流对宏观冲击更敏感
Investment-basedCochrane (1991) 用 q-theory 解释:投资低的公司未来回报高

核心断言:因子溢价是「承担系统性风险的合理补偿」,符合有效市场假说

4.2 行为派(Lakonishok / Shleifer / Vishny / Daniel / Titman)

论点内容
过度反应投资者过度看好成长股、过度悲观价值股,导致系统性 mispricing
Anchoring投资者用过去业绩做锚,不愿意为低估值公司付出合理估值
Limit to arbitrage即使有人意识到 mispricing,做空成本和资金约束阻止套利
Herding机构投资者扎堆抱团成长股,放大估值差距

核心断言:因子溢价是「市场非理性的表现」,反对纯有效市场假说

4.3 为什么这件事很重要

这不是学术八卦,对 PM/量化决策有直接影响:

立场推论实操影响
纯风险派因子永远存在,因为承担风险就有补偿持续配置因子组合,不担心衰减
纯行为派因子可能消失(套利者多了之后)警惕因子衰减,监控 alpha decay
折中派部分风险 + 部分行为因子部分会消失,部分会留下

我个人的立场(对应金融工程实操):折中派偏行为。原因:

  1. 如果是纯风险,post-publication decay 不应该发生——但实证看,公开后多数因子收益减半(详见第 6 节)
  2. 如果是纯行为,因子早就该被套利吞掉——但 value、momentum 在 60 年数据上仍然有显著 t-stat
  3. 最合理的解释:风险溢价是 floor,行为 mispricing 是 cycle。floor 决定长期均值,cycle 决定短期可交易性。

至今没有定论这件事本身就值得学。它告诉我们:金融科学不是物理学,不会有「最终模型」。我们只是在用不完美的模型做不完美的决策——任何声称「找到圣杯」的策略都该警惕。


五、Fama-French 五因子(2015):为什么三因子不够

2015 年 Fama 和 French 又发了 "A five-factor asset pricing model"(Journal of Financial Economics)。

5.1 三因子的不足

到 2010s,学界又积累了一批三因子无法解释的异象:

异象描述
Profitability高 ROE / 高毛利率公司未来回报更高(Novy-Marx 2013)
Investment资本支出低 / 总资产增长慢的公司未来回报更高(Cooper-Gulen-Schill 2008)
Accruals应计利润低的公司未来回报更高(Sloan 1996)
还有更多...Quality、Low-vol、Momentum 等

最致命的是profitabilityinvestment——它们在控制 size、B/M 之后仍然有显著 alpha,说明 FF3 漏掉了重要的定价维度。

5.2 五因子模型公式

R_i - R_f = α_i + β_i·(R_m-R_f) + s_i·SMB + h_i·HML + r_i·RMW + c_i·CMA + ε_i

新增两个因子:

因子全名构造
RMWRobust Minus Weak高盈利能力(operating profitability)股票 - 低盈利能力股票
CMAConservative Minus Aggressive低投资率(asset growth 慢)股票 - 高投资率股票

构造方法和 SMB / HML 一样——按 size 和因子特征做 2×3 切分。

5.3 五因子的代价

好处:
+ 解释力进一步提高(25 portfolio 的 R² 从 0.93 升到 0.95+)
+ Profitability 和 investment 异象被吸收
+ HML 在五因子里变得「冗余」——美国数据上 HML 的 alpha 几乎被 RMW + CMA 解释掉了

代价:
- 模型变复杂,参数变多,更容易过拟合
- HML 冗余引发争议(Fama-French 自己都说 HML 在五因子里 redundant)
- 不能解释 momentum(Carhart 1997 就指出过)
- 不同地区的稳健性参差(Asness 2017 在欧洲、日本数据上挑战了五因子)

现状:学界和业界用三因子的多于五因子。AQR、Dimensional 这些大型因子基金普遍在 FF3 + Momentum (Carhart 4) 或 FF3 + Quality + Momentum 的组合上做扩展。


六、批评与失效迹象(必须知道的反面)

6.1 Post-publication decay:因子公开后收益减半

McLean & Pontiff (2016) Journal of Finance 经典论文:检验 97 个学术因子,发现论文发表后,平均收益衰减约 32%;其中 12 个因子收益完全消失。

Asness 等(AQR)的多次研究也指出:FF3 中 SMB 在 1980 年代之后收益持续低于学术样本期;HML 在 2014-2020 经历了「失落十年」。

Why:套利交易者读到论文后开始执行该策略,需求把 alpha 推走。这是行为派立场的有力证据。

6.2 Value 的失落十年(2014-2020)

这件事对 PM 思维特别重要

1927-2014:HML 长期 t-stat ≈ 4.5(教科书黄金因子)
2014-2020:HML 累计 -50%(连续 6 年负回报)
2020-2024:Value 部分回归

哪些机构在 2018-2020 死了:
- AQR 旗舰 value fund 大幅赎回
- Dimensional 也经历重大资金外流
- Cliff Asness 写了多篇辩护文章,承认 value 进入历史最差回撤

结论任何因子都会有 5-10 年的 drawdown。如果你不能心理上承受这个,就别配置因子策略。

6.3 数据挖掘风险

Harvey, Liu & Zhu (2016) "...and the Cross-Section of Expected Returns":他们清点了学术界发表的「因子」,发现到 2015 年共有 316 个所谓的 alpha factor。其中绝大部分是 data snooping 的产物——没有经济学解释,只是在历史数据上凑出来的。

他们提出:因子的 t-stat 应该至少 ≥ 3.0(而不是传统的 2.0)才能算可信。按这个标准,过去 50 年发表的因子里能活下来的不到 50 个。

McLean-Pontiff 之后,业界的 best practice:

  • 任何因子上线前必须过 out-of-sample 测试(最好是另一个市场 / 另一个时间段)
  • 必须有经济学叙事(不能只是「我跑出来 t-stat 高」)
  • 必须做 regime test(在 2008、2020 这种极端环境下表现如何)

七、动手:下载 FF3 数据并跑回归

7.1 Kenneth French 数据库(核心资源)

URL:Kenneth French Data Library

这个网站每月更新,提供:

文件内容频率
F-F_Research_Data_FactorsFF3 因子(MKT-RF, SMB, HML, RF)Monthly / Daily / Weekly
F-F_Research_Data_5_Factors_2x3FF5 因子(多 RMW + CMA)Monthly / Daily
F-F_Momentum_FactorMomentum 因子(UMD = Up Minus Down)Monthly / Daily
6_Portfolios_2x3构造 SMB/HML 的 6 个原始 portfolioMonthly
25_Portfolios_5x525 个测试 portfolioMonthly

注意:French 数据库是美国市场的因子。其他地区(European, Japan, Asia ex-Japan, Emerging)也有专门的数据集。

7.2 下载 + 解析代码

# tr_day8_ff3.py
# 一段最小可复现的 FF3 三因子回归脚本
import pandas as pd
import numpy as np
import statsmodels.api as sm
from io import BytesIO
from urllib.request import urlopen
from zipfile import ZipFile

FF3_URL = "https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip"

def load_ff3_monthly():
    """下载 FF3 月度因子,返回 DataFrame(百分比已转成小数)。"""
    with urlopen(FF3_URL) as resp:
        with ZipFile(BytesIO(resp.read())) as zf:
            csv_name = zf.namelist()[0]
            raw = zf.read(csv_name).decode("latin-1")

    # FF 的 CSV 头有几行说明,要跳过;尾部又有 annual 表,要截断
    lines = raw.splitlines()
    start = next(i for i, ln in enumerate(lines) if ln.strip().startswith("19"))
    # 找到第一段空行(monthly 段结束)
    end = start
    for i in range(start, len(lines)):
        if not lines[i].strip() or "Annual" in lines[i]:
            end = i
            break

    data = "\n".join(lines[start:end])
    df = pd.read_csv(BytesIO(data.encode()), header=None,
                     names=["yyyymm", "MKT_RF", "SMB", "HML", "RF"])
    df["date"] = pd.to_datetime(df["yyyymm"].astype(str), format="%Y%m") + pd.offsets.MonthEnd(0)
    df = df.set_index("date").drop(columns="yyyymm").astype(float) / 100.0
    return df

def load_aapl_monthly():
    """从 yfinance 拉 AAPL 月度收益。"""
    import yfinance as yf
    px = yf.download("AAPL", start="2010-01-01", end="2026-04-30",
                     interval="1mo", auto_adjust=True, progress=False)["Close"]
    return px.pct_change().dropna().rename("AAPL").to_frame()

def ff3_regression(stock_ret: pd.Series, ff: pd.DataFrame) -> sm.regression.linear_model.RegressionResultsWrapper:
    df = ff.join(stock_ret.to_frame("R"), how="inner").dropna()
    y = df["R"] - df["RF"]                 # 个股超额收益
    X = df[["MKT_RF", "SMB", "HML"]]
    X = sm.add_constant(X)                 # 加截距 (alpha)
    return sm.OLS(y, X).fit()

if __name__ == "__main__":
    ff = load_ff3_monthly()
    aapl = load_aapl_monthly()["AAPL"]
    res = ff3_regression(aapl, ff)
    print(res.summary())
    print(f"\n年化 alpha:  {res.params['const']*12*100:.2f}%")
    print(f"市场 beta:   {res.params['MKT_RF']:.3f}")
    print(f"SMB load (s): {res.params['SMB']:.3f}")
    print(f"HML load (h): {res.params['HML']:.3f}")

7.3 解读输出(示例)

跑出来的结果大致会长这样(数值随时间窗变化):

                      coef    std err      t       P>|t|
const (alpha)       0.0085      0.003    2.84      0.005
MKT_RF              1.182       0.075   15.76      0.000
SMB                -0.347       0.122   -2.85      0.005
HML                -0.521       0.118   -4.41      0.000

怎么读

系数数值解读
α0.85% / 月 ≈ 10.2% / 年三因子之外的「Apple 特有 alpha」,t-stat 2.84,弱显著
β1.18市场 beta 略高于 1,AAPL 比大盘略激进
s (SMB load)-0.35负载 SMB,说明 AAPL 像「Big stock」(确实是巨头)
h (HML load)-0.52负载 HML,说明 AAPL 像「Growth」而非 Value(确实是成长股)

几个值得想的细节

  1. 为什么 AAPL 的 alpha 在 2010s 显著正?因为 iPhone 时代股价表现远超三因子能解释的,这部分被记成「特异 alpha」。
  2. s = -0.35, h = -0.52 说明 AAPL 是典型的「大盘成长」股——这跟我们直觉一致。FF 模型把直觉变成了数字。
  3. 如果跑 2020-2024 年(疫情后 Tech 大涨期间),AAPL 的 alpha 还会更高;如果跑 2022 年单年,alpha 可能转负——单期 alpha 不稳定。

7.4 这段代码 PM 视角的意义

这是一个非常微小的脚本(不到 60 行),但它完成了一次完整的 factor exposure attribution——把一只股票的收益分解成:

  • 市场暴露
  • 风格暴露(size、value)
  • 特异 alpha

所有专业资管报告里的「我这只基金的 alpha 是多少」就是这么算出来的。理解这一步就理解了机构投资语言。


八、PM 视角:今天学到的迁移性思考

  1. 「拆维」是金融学最强的方法论之一:CAPM 只有一维(beta),FF 拆成三维,五因子拆成五维。维度越多,模型解释力越强但也越容易过拟合。这跟 PM 做用户分群完全同构——把「DAU」拆成「new / returning / power」就是因子化。

  2. 论文公开 → alpha 衰减是开源思想在金融里的体现:Web2 / Web3 的开源社区认为「公开促进进步」,金融学界一样——但金融的代价是 alpha 被消灭。这暗示了「knowledge as moat」这种产品策略在金融行业要更小心,因为 know-how 一旦写出来就会被定价进市场。

  3. 风险派 vs 行为派之争 = 「设计派 vs 数据派」之争:风险派像设计派(先有理论再找数据验证),行为派像数据派(先看数据再讲故事)。两派在金融学里 60 年没分出胜负——这告诉我们任何「方法论之争」可能本来就是伪命题,实际项目里最优解是混用

  4. 失落十年是 PM 风险管理的核心 case:2014-2020 价值因子 -50%。如果你是 fund PM,怎么和投资人解释「6 年没赚钱」?这是 communication 问题不是 model 问题。同理,产品有 long bet 时,怎么和老板解释「这条线 3 年看不到回报」?同一个问题。

  5. 数据挖掘风险 ≈ A/B test multiple comparisons:金融学有 316 个因子,绝大部分是噪声;产品 A/B test 跑 100 个也会有 5 个「显著」是假阳性。Bonferroni 校正在两个领域都该用

  6. t-stat ≥ 3.0 比 ≥ 2.0 的提议很有 PM 价值:当一个领域里有大量探索性研究时,传统统计阈值不够。提高阈值意味着接受更高 false negative 换更低 false positive——产品决策同理:当你有 10 个 feature idea 时,应该把发布门槛抬高,而不是「t-stat 显著就发」。


九、Day 8 实际执行 Checklist

按这个顺序做:

  • (1) 读完本笔记理论部分(CAPM 失效 → FF3 → FF5 → 批评)
  • (2) 注册 Kenneth French 数据库(不需要登录,直接下载 CSV)
  • (3) 跑下载脚本:能成功 parse 出 MKT_RF / SMB / HML / RF 四列月度数据
  • (4) 跑 AAPL 三因子回归:成功打印 summary + 解读 α / β / s / h
  • (5) 换一只股票再跑:建议 BRK-B(应该是 value tilt)或 NVDA(应该是 growth + small-cap-like 高 beta)
  • (6) 对比观察:不同股票的 SMB / HML load 是否符合直觉
  • (7) 把数据缓存到本地./data/ff3_monthly.parquet,避免每次重新下载
  • (8) 更新进度docs/daily/TR_PROGRESS.md Week 2 / Day 8 标 ✅
  • (9) 记录踩坑:本笔记最后加「实际执行记录」段

十、明日预告

Day 9: 因子有效性评估 — IC、IR、t-stat 与 multiple testing

  • 什么是 Information Coefficient (IC):因子值排名与未来收益排名的 Spearman 相关
  • IR(Information Ratio):alpha 的「信噪比」
  • t-stat ≥ 2.0 vs ≥ 3.0:什么时候用哪个
  • Multiple comparisons:Bonferroni / FDR 校正
  • 用今天下载的 FF3 数据计算 SMB 和 HML 的 IR,看「教科书因子在最近 10 年的实际表现」
  • PM 视角:因子评估 vs 产品 metric 评估的同构性

实际执行记录

启动一项填一项,时间戳 + 卡点。

  • [hh:mm] 下载 FF3 CSV 成功 — ...
  • [hh:mm] AAPL 三因子回归跑通 — ...
  • [hh:mm] 第二只股票(BRK-B / NVDA)回归 — ...
  • [hh:mm] 数据本地缓存 — ...
  • 卡点 / 学到的:

总字数:约 6,400 字 今日完成度:理论 ✓ / 实操(你自己执行)/ 笔记 ✓