σμ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 AcademyRutas
Ctrl K
AO
+1,2 k estudiantes
Iniciar sesiónUnirse ↗
Rutas
AO
+1,2 k estudiantes
Iniciar sesión
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Ruta de Python›Módulo 7 · Investigación de alfa y riesgo›Tema 7.2·~1 hAvanzado

Modelos multifactoriales: Fama-French

Posición en la rutaMódulo 7 de 11 · Tema 2 de 9
7.2 Modelos multifactoriales: Fama-French
—Puntuación del lab— / 100XP total—Racha—

Más de una razón para moverse

El CAPM tiene un factor, el mercado. En 1992 Fama y French mostraron que otros dos explican gran parte de las diferencias de rendimiento entre acciones: el tamaño (las empresas pequeñas ganaron más que las grandes, factor SMB, small minus big) y el valor (las acciones baratas por valor contable/mercado ganaron más que las caras, factor HML, high minus low). Modelos posteriores añadieron momentum, rentabilidad e inversión. Cada factor es una serie de rendimientos, y la exposición de un activo a ella dice cuánto se mueve con esa serie.

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

Mínimos cuadrados en forma matricial

Con varios factores la regresión es asset = alpha + b1 * f1 + ... + bk * fk + error. Se colocan los factores junto a una columna de unos en una matriz X, y los coeficientes de mínimos cuadrados resuelven las ecuaciones normales (X'X) c = X'y. En NumPy: np.linalg.solve(X.T @ X, X.T @ y). Es la misma maquinaria que la regresión de un solo factor, ahora con k + 1 incógnitas. El primer coeficiente es alfa, el resto son las exposiciones.

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))

¿Cuánto explican los factores?

El R cuadrado lo responde: la parte de la variación del activo que explican los factores, 1 - SSres / SStot, entre 0 (nada) y 1 (todo). Una cartera de acciones diversificada suele tener un R cuadrado superior a 0,9 con los factores de Fama–French: su riesgo es casi todo riesgo factorial. Una acción individual tiene uno menor, y el resto, la variación residual, es propia de la empresa. Añadir un factor nunca baja el R cuadrado en la muestra, así que un número mayor no prueba por sí solo que un factor importe.

# 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
Los factores son apuestas, no comida gratisUna prima de factor es la recompensa por un riesgo que duele en los malos momentos, y puede desaparecer o invertirse durante años. Las exposiciones estimadas con una muestra corta son ruidosas, y con factores correlacionados los coeficientes individuales pueden ser inestables aun con buen ajuste. El uso de un modelo factorial es sobre todo descomponer riesgo y rendimiento: cuánto vino del mercado, tamaño, valor, y cuánto, el alfa, queda.
  • Un modelo factorial regresa los rendimientos en exceso sobre varios factores: X = [unos | factores], coeficientes [alpha, beta_1..beta_k].
  • Resuelva las ecuaciones normales np.linalg.solve(X.T @ X, X.T @ y); el R cuadrado es 1 - SSres / SStot y nunca baja al añadir un factor.
  • El modelo implica rf + sum(betas * premia); exposiciones y primas son estimaciones, y una prima de factor puede desaparecer.

A continuación: el coeficiente de información, medir si una señal predice los rendimientos.

Lab: qué se califica

  • Preparar la regresión con design_matrix25 pts
  • Estimar las exposiciones con fit_factor_model25 pts
  • Puntuar el ajuste con r_squared25 pts
  • Poner precio a las exposiciones con factor_expected_return25 pts
Explorador · lab-94-1
▾ lab-94-1
…
bash · en el navegador
learner@quantcraft:~/lab-94-1$
Python aún no cargadoPythonLn 1, Col 1Spaces: 4UTF-8

¿Restablecer este tema?

Todo lo que hay en lab-94-1 vuelve a los archivos iniciales y se limpia el terminal. Tu solución actual se perderá: no se puede deshacer.

Se restablecerá
  • main.py → código inicial
  • Historial del terminal y salida de pruebas
  • Cambios sin enviar
Se conservará
  • Mejor puntuación del lab
  • Tu XP y tu racha
  • Progreso de la lección y notas

Inicia sesión para ejecutar tu código.

Todas las clases se pueden leer gratis. Crea una cuenta o inicia sesión para ejecutar código, lanzar las pruebas y enviar este lab.

  • IDE en el navegador con terminal bash — sin instalar nada
  • Corrección instantánea, XP y tu lugar en la ruta
Crear una cuentaIniciar sesión
O
Continuar con GitHub