Arbitrage Pricing Theory and Multi-Factor Models › Working with Factor Data
Quantitative FinanceAll chapters Arbitrage Pricing Theory and Multi-Factor Models › Working with Factor DataOne section · Sections in this chapter7 / 15 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Let's implement a factor model using real data. The Fama-French factors are publicly available from Kenneth French's data library. We'll use the pandas-datareader library to access this data directly.
!uv pip install statsmodels
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import statsmodels.api as sm
from datetime import datetime
import warnings
warnings.filterwarnings('ignore')
# Set style for all plots
plt.style.use('seaborn-v0_8-whitegrid')import numpy as np
import pandas as pd
# Download Fama-French 3 factor data
# The factors are in percentage terms
# ff_factors = pdr.DataReader('F-F_Research_Data_Factors', 'famafrench',
# start='2010-01-01', end='2023-12-31')[0]
# Synthetic data for demonstration (uncomment lines above for real data)
np.random.seed(42)
dates = pd.date_range(start="2010-01-01", end="2023-12-31", freq="ME")
ff_factors = pd.DataFrame(
np.random.normal(0.005, 0.03, (len(dates), 4)), index=dates
)
ff_factors.columns = ["MKT", "SMB", "HML", "RF"]
# Convert from percentage to decimal (if using real data)
# ff_factors = ff_factors / 100# Examine the data structure
start_date = ff_factors.index[0]
end_date = ff_factors.index[-1]
n_obs = len(ff_factors)
head_data = ff_factors.head()Fama-French Factor Data (Monthly)
==================================================
Date range: 2010-01-31 to 2023-12-31
Number of observations: 168
First few rows:
MKT SMB HML RF
2010-01-31 0.019901 0.000852 0.024431 0.050691
2010-02-28 -0.002025 -0.002024 0.052376 0.028023
2010-03-31 -0.009084 0.021277 -0.008903 -0.008972
2010-04-30 0.012259 -0.052398 -0.046748 -0.011869
2010-05-31 -0.025385 0.014427 -0.022241 -0.037369The data contains monthly returns for each factor plus the risk-free rate. Let's examine the historical factor premia.
# Calculate annualized statistics
factor_means = ff_factors[["MKT", "SMB", "HML"]].mean() * 12
factor_stds = ff_factors[["MKT", "SMB", "HML"]].std() * np.sqrt(12)
sharpe_ratios = factor_means / factor_stds
factor_stats = pd.DataFrame(
{
"Mean (Annual)": factor_means,
"Std (Annual)": factor_stds,
"Sharpe Ratio": sharpe_ratios,
}
)Factor Statistics (2010-2023)
==================================================
Mean (Annual) Std (Annual) Sharpe Ratio
MKT 0.0490 0.0957 0.5124
SMB 0.0605 0.0989 0.6116
HML 0.0630 0.1132 0.5561The Sharpe ratios indicate risk-adjusted performance. A higher Sharpe ratio suggests better compensation for each unit of risk taken.
Visualizing Factor Returns
Let's visualize the cumulative performance of each factor.
# Calculate cumulative returns for visualization
cumulative_returns = (1 + ff_factors[["MKT", "SMB", "HML"]]).cumprod()
The chart reveals important patterns in factor performance. The market factor (MKT) showed strong positive returns over this period, which reflects the bull market in U.S. equities. The SMB factor exhibited weaker performance, as large-cap stocks dominated returns in many years. The HML factor produced negative returns over much of this period, as growth stocks materially outperformed value stocks.
These patterns highlight an important caveat: factor premia are not guaranteed. While historical data shows positive average returns to size and value over long periods, individual decades can show very different patterns.
Factor Correlations
Understanding factor correlations helps with portfolio construction and risk management.
# Calculate correlation matrix
corr_matrix = ff_factors[["MKT", "SMB", "HML"]].corr()
The relatively low correlations between factors confirm that they capture distinct sources of systematic risk. This makes multi-factor models valuable for both explaining returns and constructing diversified portfolios.