Mehr als ein Grund, sich zu bewegen
CAPM hat einen Faktor, den Markt. 1992 zeigten Fama und French, dass zwei weitere einen großen Teil der Renditeunterschiede von Aktien erklären: die Größe (kleine Unternehmen verdienten mehr als große, Faktor SMB, small minus big) und der Wert (nach Buch-Markt-Verhältnis billige Aktien verdienten mehr als teure, Faktor HML, high minus low). Spätere Modelle fügten Momentum, Profitabilität und Investition hinzu. Jeder Faktor ist selbst eine Renditereihe, und die Ladung eines Assets darauf zeigt, wie stark es sich mit dieser Reihe bewegt.
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 SMBKleinste Quadrate in Matrixform
Mit mehreren Faktoren lautet die Regression asset = alpha + b1 * f1 + ... + bk * fk + Fehler. Man legt die Faktoren neben eine Einserspalte in eine Matrix X, und die Kleinste-Quadrate-Koeffizienten lösen die Normalgleichungen (X'X) c = X'y. In NumPy: np.linalg.solve(X.T @ X, X.T @ y). Es ist dieselbe Mechanik wie bei der Ein-Faktor-Regression, nun mit k + 1 Unbekannten. Der erste Koeffizient ist Alpha, die übrigen sind die Ladungen.
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))Wie viel erklären die Faktoren?
Das Bestimmtheitsmaß R² antwortet: der Anteil der Schwankung des Assets, den die Faktoren erklären, 1 - SSres / SStot, zwischen 0 (nichts) und 1 (alles). Ein diversifiziertes Aktienportfolio hat auf den Fama-French-Faktoren oft ein R² über 0,9: Sein Risiko ist fast nur Faktorrisiko. Eine Einzelaktie hat ein niedrigeres, und der Rest, die residuale Schwankung, ist unternehmensspezifisch. Ein zusätzlicher Faktor senkt R² in der Stichprobe nie, eine höhere Zahl allein beweist also nicht, dass ein Faktor zählt.
# 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- Ein Faktormodell regressiert Überrenditen auf mehrere Faktoren:
X = [Einsen | Faktoren], Koeffizienten[alpha, beta_1..beta_k]. - Lösen Sie die Normalgleichungen
np.linalg.solve(X.T @ X, X.T @ y); R² ist1 - SSres / SStotund sinkt nie, wenn man einen Faktor hinzufügt. - Das Modell impliziert
rf + sum(betas * premia); Ladungen und Prämien sind Schätzungen, und eine Faktorprämie kann verschwinden.
Als Nächstes: der Informationskoeffizient, messen, ob ein Signal Renditen überhaupt vorhersagt.
Lab: Was bewertet wird
- Mit
design_matrixdie Regression aufstellen25 Pkt. - Mit
fit_factor_modeldie Ladungen schätzen25 Pkt. - Mit
r_squareddie Anpassung bewerten25 Pkt. - Mit
factor_expected_returndie Risikoexpositionen bepreisen25 Pkt.