Factor Risk Premia Extraction

Extract factor-level risk premia from asset-level implied returns

THE BRIDGE

Asset Implied Returns \(\mu^*\)
--->
Cross-Sectional Regression
--->
Factor Premia \(\pi\)
--->
New Asset Pricing: \(\mu_{new} = r_f + B_{new}'\pi\)

1. The Factor Model

APT Framework

Asset returns are driven by systematic factors:

$$r_i = r_f + \sum_{k=1}^K \beta_{ik} f_k + \epsilon_i$$

Where:

2. OLS Cross-Sectional Regression

Extract Factor Premia

Given implied returns \(\mu^*\) and factor betas \(B\):

$$(\mu^* - r_f) = B\pi + e$$

OLS solution:

$$\hat{\pi} = (B'B)^{-1}B'(\mu^* - r_f)$$

3. Fama-MacBeth Two-Pass Procedure

Pass 1: Time-Series (Estimate Betas)

For each asset \(i\), regress returns on factors:

$$r_{i,t} - r_f = \alpha_i + \beta_i f_t + \epsilon_{i,t}$$

Output: \(\hat{B}\) matrix of estimated betas

Pass 2: Cross-Sectional (Estimate Premia)

For each time \(t\), regress returns on betas:

$$r_{i,t} - r_f = \gamma_{0,t} + \gamma_{1,t}\hat{\beta}_i + \eta_{i,t}$$

Output: \(\{\hat{\gamma}_t\}_{t=1}^T\)

Final Estimate

$$\hat{\pi} = \frac{1}{T}\sum_t \hat{\gamma}_t, \quad SE = \frac{\sigma_\gamma}{\sqrt{T}}$$

Shanken Correction

Adjusts standard errors for errors-in-variables bias:

$$SE_{Shanken} = SE_{FM} \times \sqrt{1 + \lambda'\Sigma_f^{-1}\lambda}$$

4. Python Usage

from brisma import (
    extract_factor_premia_ols,
    fama_macbeth_regression,
    price_new_asset,
    multi_factor_calibration,
)
import numpy as np

# Asset data
implied_returns = np.array([0.08, 0.06, 0.05, 0.04])
betas = np.array([[1.2, 0.5], [0.9, 0.8], [0.7, 1.2], [0.4, 0.3]])

# OLS extraction
result = extract_factor_premia_ols(implied_returns, betas, rf_rate=0.02)
print(f"Factor Premia: {result.factor_premia}")
print(f"R-squared: {result.r_squared:.3f}")

# Price a new asset
betas_new = np.array([1.5, 0.7])
pricing = price_new_asset(betas_new, result.factor_premia, rf_rate=0.02)
print(f"Expected Return: {pricing['expected_return']:.2%}")

# Fama-MacBeth (time series data)
returns = np.random.randn(120, 20) * 0.03 + 0.005
factors = np.random.randn(120, 2) * 0.02
fm_result = fama_macbeth_regression(returns, factors)
print(f"T-statistics: {fm_result.t_statistics}")

5. Multi-Factor Calibration

Using Anchor Assets

Instead of OLS, use specific "anchor" assets to pin down each factor premium:

$$\pi_k = \frac{\mu^*_{anchor} - r_f}{\beta_{anchor,k}}$$

Example: Use 10Y government bond to anchor duration premium.

anchor_assets = {
    "duration": (10, 7.0),  # Asset 10, beta=7 anchors duration
    "credit": (25, 5.0),    # Asset 25, beta=5 anchors credit
}
premia = multi_factor_calibration(implied_returns, factor_betas, anchor_assets)

6. API Reference

Function Description
extract_factor_premia_ols() OLS cross-sectional regression for factor premia
fama_macbeth_regression() Two-pass procedure with Shanken correction
price_new_asset() Price new assets using extracted factor premia
multi_factor_calibration() Calibrate premia using anchor assets
factor_model_diagnostics() Diagnostics: R2, pricing errors, contributions