σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academy学习路线
Ctrl K
AO
+1.2k 位学习者
登录加入 ↗
学习路线
AO
+1.2k 位学习者
登录
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Python 学习路线›模块 7 · Alpha 研究与风险›主题 7.2·~1小时高级

多因子模型:Fama-French

路线进度模块 7/11 · 主题 2/9
7.2 多因子模型:Fama-French
—实验得分— / 100总 XP—连续天数—

不止一个波动的理由

CAPM 只有一个因子,即市场。1992 年法玛和弗伦奇表明,另外两个因子能解释股票收益差异的大部分:规模(小公司比大公司赚得多,因子 SMB,小减大)和价值(按账面市值比衡量的便宜股票比贵的赚得多,因子 HML,高减低)。后来的模型又加入了动量、盈利能力和投资。每个因子本身就是一条收益序列,资产对它的载荷表示它与这条序列联动得有多强。

import numpy as np

rng = np.random.default_rng(1)
n = 250
market = rng.normal(0.0004, 0.010, size=n)               # excess returns of three factors
smb = rng.normal(0.0001, 0.005, size=n)
hml = rng.normal(0.0001, 0.005, size=n)
factors = np.column_stack([market, smb, hml])             # shape (n, k) = (250, 3)

asset = 0.0002 + factors @ np.array([1.1, 0.5, -0.3]) + rng.normal(0, 0.004, size=n)
X = np.column_stack([np.ones(n), factors])                # design matrix: a column of ones for alpha
print(X.shape)                                            # (250, 4)
# The design matrix of three days and two factors
import numpy as np

factors = np.array([[0.010, -0.002], [-0.004, 0.001], [0.006, 0.003]])
X = np.column_stack([np.ones(len(factors)), factors])
print(X)                                           # a column of ones, then market and SMB

矩阵形式的最小二乘

有多个因子时,回归是 asset = alpha + b1 * f1 + ... + bk * fk + 误差。把各因子与一列 1 并排放进矩阵 X,最小二乘系数就是正规方程 (X'X) c = X'y 的解。在 NumPy 中是 np.linalg.solve(X.T @ X, X.T @ y)。它与前面的单资产回归是同一套机制,只是未知数变成了 k + 1 个。第一个系数是阿尔法,其余是各因子的载荷。

import numpy as np

rng = np.random.default_rng(1)
n = 250
factors = np.column_stack([rng.normal(0.0004, 0.010, size=n), rng.normal(0.0001, 0.005, size=n), rng.normal(0.0001, 0.005, size=n)])
asset = 0.0002 + factors @ np.array([1.1, 0.5, -0.3]) + rng.normal(0, 0.004, size=n)

X = np.column_stack([np.ones(n), factors])
coef = np.linalg.solve(X.T @ X, X.T @ asset)
print(np.round(coef, 4))                                   # [alpha, market, SMB, HML]: the loadings come out near [1.1, 0.5, -0.3]

residual = asset - X @ coef
r2 = 1 - np.sum(residual ** 2) / np.sum((asset - asset.mean()) ** 2)
print(round(float(r2), 4))

因子能解释多少?

R 平方回答了这个问题:因子解释了资产波动的多大比例,即 1 - SSres / SStot,介于 0(毫无解释)和 1(完全解释)之间。一个分散化的股票组合对 Fama–French 因子的 R 平方常常超过 0.9:它的风险几乎全是因子风险。单只股票的更低,剩下的残差波动属于公司特有。样本内增加一个因子绝不会降低 R 平方,所以数值更高本身并不能证明某个因子重要。

# What the model implies: the expected return from the loadings and the factor premia
import numpy as np

betas = np.array([1.1, 0.5, -0.3])             # market, SMB, HML loadings
premia = np.array([0.0006, 0.0002, 0.0002])    # expected daily factor returns
rf = 0.0001

expected = rf + np.sum(betas * premia)
print(round(float(expected), 6))               # 0.0008 per day, about 20% a year on 250 days
因子是下注,不是免费午餐因子溢价是对在糟糕时期会带来痛苦的风险的补偿,它可能连续多年消失甚至反转。用短样本估计的载荷噪声很大,因子之间相关时,即使拟合很好,单个系数也可能不稳定。因子模型的主要用途是分解风险和业绩:多少来自市场、规模、价值,剩下多少是阿尔法。
  • 因子模型把超额收益对多个因子回归:X = [全 1 列 | 因子],系数为 [alpha, beta_1..beta_k]。
  • 解正规方程 np.linalg.solve(X.T @ X, X.T @ y);R 平方为 1 - SSres / SStot,增加因子时不会下降。
  • 模型隐含 rf + sum(betas * premia);载荷和溢价都是估计值,因子溢价可能消失。

下一节:信息系数,度量一个信号是否真的能预测收益。

实验:评分内容

  • 用 design_matrix 搭建回归25 分
  • 用 fit_factor_model 估计因子载荷25 分
  • 用 r_squared 评价拟合优度25 分
  • 用 factor_expected_return 给因子暴露定价25 分
资源管理器 · lab-94-1
▾ lab-94-1
…
bash · 浏览器内
learner@quantcraft:~/lab-94-1$
Python 尚未加载PythonLn 1, Col 1Spaces: 4UTF-8

要重置此主题吗?

lab-94-1 中的所有内容将恢复为初始文件,终端也会被清空。你当前的解答将丢失,且无法撤销。

将被重置
  • main.py → 初始代码
  • 终端历史与测试输出
  • 未提交的更改
将被保留
  • 实验最高得分
  • 你的 XP 与连续天数
  • 讲解进度与笔记

登录后即可运行你的代码。

所有讲解均可免费阅读。创建账户或登录后,即可运行代码、运行测试并提交此实验。

  • 浏览器内 IDE 与 bash 终端,无需安装
  • 即时评分、XP 以及你在学习路线中的位置
创建账户登录
或
使用 GitHub 继续