“Why do some stocks outperform the overall market?”
This is a fundamental question that every curious investor eventually asks. While I’ve previously discussed Mean-Variance Optimization and Risk Parity, the Fama-French 3-Factor Model offers a direct way to understand the underlying “drivers” of your returns.
Due to its elegant simplicity and practical power, this model remains a cornerstone for quantitative analysts. In this article, I’ll deep-dive into the model’s structure, its advantages over CAPM, and show you exactly how to implement it using Python.
Overview of Fama-French 3-Factor Model
The Fama-French 3-factor model is a multi-factor model for explaining stock returns. This model analyzes return fluctuations in detail based on the following three factors:
- Market Risk Premium
- Return for the risk of the entire market.
- Size Factor (SMB: Small Minus Big)
- The tendency for small-cap stock returns to exceed large-cap stocks.
- Value Factor (HML: High Minus Low)
- The tendency for low-priced stocks (value stocks) to exceed high-priced stocks (growth stocks).
Advantages of Fama-French 3-Factor Model
- Multi-factor Approach
- By considering not only market risk but also size and value factors, it can explain return fluctuation factors in more detail.
- Support in Empirical Studies
- It has a relatively deep history, and its explanatory power and effectiveness have been confirmed in actual operation.
Disadvantages of Fama-French 3-Factor Model
- Increased Complexity
- Compared to CAPM (Capital Asset Pricing Model), it is slightly more complicated to understand and calculate due to the increased number of factors.
- Fluctuations by Era and Market
- Since the influence of factors changes depending on the era and market conditions, periodic re-evaluation of parameters is necessary.
- Ignoring Other Factors
- It may not be able to explain all returns because it does not consider other important factors such as momentum.
Calculation Method of Fama-French 3-Factor Model
The Fama-French 3-factor model is expressed by the following formula.
As you can see, the first two terms are equivalent to the CAPM formula. The basic idea is CAPM, and the Fama-French 3-factor model adds returns considered from size and value factors to the formula using a similar way of thinking.
How to Calculate SMB and HML
I found the note below easy to understand, so I’ll link it. Even if I understand it, I don’t have the energy to calculate it…
SMB and HML use the same values for the entire market. So if you look on the web, you might find them.
The Data Library contains current benchmark returns and historical benchmark returns data, downloads and details.
How to Calculate Beta
Beta is solved as a regression problem using past return data, risk-free rate, SMB, and HML. Be careful not to use the same value for different assets as it is unique to each stock or portfolio.
Calculating with Python
Let’s write some code. (Calculating with monthly data)
Code
import pandas as pdimport yfinance as yfimport zipfileimport urllib.requestfrom sklearn.linear_model import LinearRegressionimport numpy as np
# Get return dataticker = 'QQQ'start_date = '2018-01-01'end_date = '2023-01-01'
data = yf.download(ticker, start=start_date, end=end_date)
# Calculate monthly returndata_resampled = data.resample("ME").ffill()data_resampled.index = data_resampled.index.to_period("M")
# Convert to log returndata_resampled["Log_Return"] = np.log(data_resampled['Adj Close'] / data_resampled['Adj Close'].shift(1))*100data_resampled.dropna(inplace=True)
# Fetch Fama-French 3 factor returnsff3_url = 'https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/ftp/F-F_Research_Data_Factors_CSV.zip'urllib.request.urlretrieve(ff3_url,'ff3.zip')with zipfile.ZipFile('ff3.zip', 'r') as z: ff_csv = z.extract('F-F_Research_Data_Factors.CSV')
ff3_data = pd.read_csv(ff_csv, index_col=0, skiprows = 3)ff3_data = ff3_data[ff3_data.index.str.count(r'\d') == 6]ff3_data = ff3_data.astype('float64')
ff3_data.index.names = ["Date"]ff3_data.index = pd.to_datetime(ff3_data.index, format="%Y%m")ff3_data.index = ff3_data.index.to_period("M")
# Subtract RF (Risk-Free Rate) and calculate excess returnff3_factors_subset = ff3_data[ ff3_data.index.isin(data_resampled.index)].copy()
ff3_factors_subset["Excess_Return"] = data_resampled["Log_Return"] - ff3_factors_subset["RF"]
# Solve regression problemX = ff3_factors_subset[["Mkt-RF", "SMB", "HML"]]y = ff3_factors_subset["Excess_Return"]
model = LinearRegression().fit(X, y)
# Output alpha and betaalpha = model.intercept_betas = model.coef_
print(f'alpha: {alpha}')print(f'betas: {betas}')Reference: Fama-French Factor Model in Python
Execution Result
alpha: -0.012127937393119126betas: [ 1.09145358 -0.12557649 -0.33877354]Conclusion
The Fama-French 3-factor model is a powerful tool that explains stock return fluctuations in more detail by considering three factors: market risk, size, and value. Through this article, we learned the basic mechanism of the model, the calculation method, and a concrete practical example in Python. The Python code is likely ready to run as soon as you install the libraries (there may be environmental differences), so please make use of it.
If you want to know other models related to portfolio construction, please use the link collection below.
投資ポートフォリオ構築に関するモデル記事のリンク集。資産配分・期待リターン計算・リスク管理モデルを体系的にまとめています。









