σμ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 AcademyParcours
Ctrl K
AO
+1,2 k apprenants
ConnexionRejoindre ↗
Parcours
AO
+1,2 k apprenants
Connexion
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
Parcours Python›Module 7 · Recherche d'alpha et risque›Sujet 7.2·~1 hAvancé

Modèles multifactoriels : Fama-French

Position dans le parcoursModule 7 sur 11 · Sujet 2 sur 9
7.2 Modèles multifactoriels : Fama-French
—Score du lab— / 100XP total—Série—

Plus d'une raison de bouger

Le MEDAF n'a qu'un facteur, le marché. En 1992, Fama et French ont montré que deux autres expliquent une grande part des différences de rendement entre actions : la taille (les petites sociétés ont rapporté plus que les grandes, facteur SMB, small minus big) et la valeur (les actions bon marché selon le rapport valeur comptable/marché ont rapporté plus que les chères, facteur HML, high minus low). Des modèles ultérieurs ont ajouté le momentum, la rentabilité et l'investissement. Chaque facteur est lui-même une série de rendements, et l'exposition d'un actif à ce facteur dit à quel point il évolue avec cette série.

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

Les moindres carrés sous forme matricielle

Avec plusieurs facteurs, la régression est asset = alpha + b1 * f1 + ... + bk * fk + erreur. On place les facteurs à côté d'une colonne de uns dans une matrice X, et les coefficients des moindres carrés résolvent les équations normales (X'X) c = X'y. En NumPy : np.linalg.solve(X.T @ X, X.T @ y). C'est la même mécanique que la régression à un actif, avec maintenant k + 1 inconnues. Le premier coefficient est l'alpha, les autres sont les expositions.

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

Que expliquent les facteurs ?

Le R carré y répond : la part de la variation de l'actif que les facteurs expliquent, 1 - SSres / SStot, entre 0 (rien) et 1 (tout). Un portefeuille d'actions diversifié a souvent un R carré supérieur à 0,9 sur les facteurs de Fama–French : son risque est presque entièrement du risque factoriel. Une action seule a un R carré plus faible, et le reste, la variation résiduelle, est propre à l'entreprise. Ajouter un facteur ne peut jamais baisser le R carré dans l'échantillon, donc un nombre plus élevé ne prouve pas à lui seul qu'un facteur compte.

# 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
Les facteurs sont des paris, pas des repas gratuitsUne prime de facteur rémunère un risque qui fait mal dans les mauvaises périodes, et elle peut disparaître ou s'inverser pendant des années. Les expositions estimées sur un échantillon court sont bruitées, et avec des facteurs corrélés les coefficients individuels peuvent être instables même si l'ajustement est bon. L'usage d'un modèle factoriel est surtout de décomposer le risque et la performance : ce qui vient du marché, de la taille, de la valeur, et ce qui reste, l'alpha.
  • Un modèle factoriel régresse les rendements excédentaires sur plusieurs facteurs : X = [uns | facteurs], coefficients [alpha, beta_1..beta_k].
  • Résolvez les équations normales np.linalg.solve(X.T @ X, X.T @ y) ; le R carré est 1 - SSres / SStot et ne baisse jamais quand on ajoute un facteur.
  • Le modèle implique rf + sum(betas * premia) ; expositions et primes sont des estimations, et une prime de facteur peut disparaître.

À suivre : le coefficient d'information, mesurer si un signal prédit les rendements.

Lab : ce qui est noté

  • Préparer la régression avec design_matrix25 pts
  • Estimer les expositions avec fit_factor_model25 pts
  • Noter l'ajustement avec r_squared25 pts
  • Chiffrer les expositions avec factor_expected_return25 pts
Explorateur · lab-94-1
▾ lab-94-1
…
bash · dans le navigateur
learner@quantcraft:~/lab-94-1$
Python pas encore chargéPythonLn 1, Col 1Spaces: 4UTF-8

Réinitialiser ce sujet ?

Tout le contenu de lab-94-1 revient aux fichiers de départ et le terminal est vidé. Votre solution actuelle sera perdue : cette action est irréversible.

Sera réinitialisé
  • main.py → code de départ
  • Historique du terminal et sortie des tests
  • Modifications non soumises
Sera conservé
  • Meilleur score du lab
  • Votre XP et votre série
  • Progression du cours et notes

Connectez-vous pour exécuter votre code.

Tous les cours sont gratuits à lire. Créez un compte ou connectez-vous pour exécuter du code, lancer les tests et soumettre ce lab.

  • IDE dans le navigateur avec terminal bash — rien à installer
  • Correction instantanée, XP et votre place dans le parcours
Créer un compteSe connecter
OU
Continuer avec GitHub