This code replicates the Fama-French (2015) five-factor model from scratch using WRDS data (CRSP and Compustat). It is designed to be transparent, self-contained, and ready for academic research.
For decades, finance researchers have been trying to answer a deceptively simple question: why do some stocks earn higher returns than others?
The earliest answer was the Capital Asset Pricing Model (CAPM), which said that a stock's expected return depends on just one thing — how much it moves with the overall market. That was elegant, but it turned out to be wrong. Or at least, incomplete.
In 1993, Eugene Fama and Kenneth French showed that two additional characteristics — firm size and book-to-market ratio — do a much better job of explaining the cross-section of stock returns. Their three-factor model became the workhorse of empirical finance. If you've taken an introductory investments course, you've almost certainly seen it.
By 2015, Fama and French recognized that even three factors weren't enough. Two more patterns had been documented so consistently that they couldn't be ignored:
- Firms with high operating profitability tend to earn higher returns.
- Firms that invest conservatively (i.e., grow their assets slowly) tend to earn higher returns.
Adding these two factors gave us the five-factor model. It is now the standard benchmark in most empirical asset pricing work.
This is the return on the broad stock market minus the return on Treasury bills. It captures the basic idea that stocks are riskier than bonds, and investors expect to be compensated for bearing that risk. When the market drops 20%, nearly every stock drops with it — that shared exposure is what this factor measures.
Small firms have historically earned higher average returns than large firms. The most common explanation is that small firms are riskier — they have less diversified revenue streams, thinner management teams, and less access to capital markets. Investors who hold small stocks are bearing real economic risk, and SMB is the compensation for that risk.
In the five-factor model, SMB is constructed as the average of three size spreads — one from each of the three independent sorts (on B/M, profitability, and investment). This makes it cleaner than the original three-factor SMB, which came from a single sort.
This is the return spread between "value" stocks (high book-to-market) and "growth" stocks (low book-to-market). A high book-to-market ratio means the market is pricing the firm well below its accounting value — often because the firm is in some kind of trouble. These beaten-down stocks have historically earned higher returns, on average, than the glamorous growth stocks that everyone wants to own.
Whether this is a risk premium or a behavioral anomaly remains one of the great debates in finance. Fama would say it's risk. Shiller would say it's mispricing. The data doesn't settle the argument.
Firms with high operating profitability — measured as (revenue − cost of goods sold − SG&A − interest expense) divided by book equity — earn higher returns than firms with low profitability. This is intuitive: profitable firms generate more cash flow per dollar of equity, and the market rewards that.
What's less intuitive is why this wasn't in the original model. The answer is that the empirical evidence wasn't strong enough in 1993. By 2015, the pattern had been documented across enough markets and time periods that Fama and French felt confident including it.
Firms that invest conservatively — meaning their total assets grow slowly — earn higher returns than firms that invest aggressively. This is the most counterintuitive of the five factors. You might think that firms investing heavily are growing and should earn higher returns. But the data says otherwise.
One explanation is that aggressive investment often reflects empire-building by managers, or overinvestment in projects with diminishing returns. Another is that the market tends to overprice firms with high expected growth. Either way, the pattern is robust.
This is where the details matter. Getting the methodology wrong — even slightly — can produce factors that look nothing like the official ones on Kenneth French's website.
Every June, we sort all stocks into portfolios based on three characteristics: size (market cap), book-to-market, and either profitability or investment. Crucially, Fama and French use three separate, independent 2×3 sorts:
- Size × Book-to-Market → 6 portfolios → produces SMB(B/M) and HML
- Size × Operating Profitability → 6 portfolios → produces SMB(OP) and RMW
- Size × Investment → 6 portfolios → produces SMB(Inv) and CMA
The final SMB factor is the average of the three SMB components. This is a deliberate design choice — it ensures that SMB is not contaminated by any single characteristic.
All breakpoints come from NYSE stocks only. This is important. NASDAQ and AMEX have many tiny stocks that would distort the breakpoints if included. The size breakpoint is the NYSE median market cap. The B/M, OP, and Inv breakpoints are the 30th and 70th NYSE percentiles.
Book equity comes from the most recent fiscal year ending at least six months before portfolio formation. For a firm with a December fiscal year end, we use December year t−1 data to form portfolios in June of year t. The six-month gap ensures that the accounting data was actually public when we use it. Portfolios are then held from July of year t through June of year t+1.
Portfolio returns are value-weighted (weighted by market cap at the end of the prior month). This matches the official Fama-French factors.
The implementation is a single Python file (main.py) with a clear pipeline:
-
CRSP download — Pulls monthly stock returns, prices, and shares outstanding. Filters to common stocks (share codes 10, 11) on NYSE, AMEX, and NASDAQ. Excludes financial firms (SIC 6000–6999). Adjusts returns for delisting to avoid survivorship bias.
-
Compustat download — Pulls annual accounting data. Computes book equity following the Davis, Fama, and French (2000) definition: stockholders' equity + deferred taxes − preferred stock. Computes operating profitability and asset growth (investment).
-
CRSP-Compustat link — Merges the two datasets using the CCM link table, respecting link validity dates and prioritizing primary links.
-
June portfolio formation — For each June, matches each stock's market cap with the most recent book equity (subject to the six-month lag rule). Computes B/M, OP, and Inv. Applies NYSE breakpoints to form three sets of six portfolios.
-
Monthly factor returns — For each month from July through the following June, computes value-weighted returns for each portfolio. Calculates SMB, HML, RMW, and CMA. Matches the risk-free rate from Kenneth French's data library.
-
Output — Saves the monthly factor returns to
output/ff5_factors.csv.
You need a WRDS account (most universities provide institutional access).
pip install wrds pandas numpy pandas-datareader
cp env_example.txt .env
# Open .env and enter your WRDS username and password
python main.py --start 2000-07-01 --end 2023-12-31The output file contains six columns: date, mkt_rf, smb, hml, rmw, cma, and rf.
- Fama, E.F. and French, K.R. (2015). "A five-factor asset pricing model." Journal of Financial Economics, 116(1), 1-22.
- Fama, E.F. and French, K.R. (1993). "Common risk factors in the returns on stocks and bonds." Journal of Financial Economics, 33(1), 3-56.
- Davis, J.L., Fama, E.F. and French, K.R. (2000). "Characteristics, Covariances, and Average Returns: 1929 to 1997." Journal of Finance, 55(1), 389-406.
- Kenneth French's Data Library: https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
@software{jihwanw_ff5,
author = {jihwanw},
title = {Fama-French 5 Factor Model},
year = {2026},
publisher = {GitHub},
url = {https://github.com/jihwanw/fama-french-5factor},
doi = {10.5281/zenodo.18883752}
}재무금융에서 수십 년간 연구자들이 매달려온 질문이 있습니다. 왜 어떤 주식은 다른 주식보다 수익률이 높은가?
가장 먼저 나온 답은 CAPM이었습니다. 주식의 기대수익률은 시장과 얼마나 같이 움직이느냐, 딱 하나에 달려 있다는 이론이었죠. 깔끔했지만, 현실과 맞지 않았습니다.
1993년, Fama와 French가 두 가지 특성을 더 발견했습니다. 기업 규모와 장부가 대비 시가 비율이 주식 수익률의 차이를 훨씬 잘 설명한다는 것이었습니다. 이 3 Factor 모델은 실증 재무금융의 표준 도구가 되었습니다. 투자론 수업을 들어보셨다면 한 번쯤 보셨을 겁니다.
2015년에 Fama와 French는 3개로는 부족하다는 것을 인정했습니다. 두 가지 패턴이 너무 일관되게 나타나서 무시할 수 없었기 때문입니다.
- 수익성이 높은 기업의 주식이 더 높은 수익률을 기록한다.
- 투자를 보수적으로 하는 기업의 주식이 더 높은 수익률을 기록한다.
이 두 팩터를 추가한 것이 5 Factor 모델입니다. 현재 대부분의 실증 자산가격 연구에서 표준 벤치마크로 사용됩니다.
전체 주식시장 수익률에서 국채 수익률을 뺀 것입니다. 주식이 채권보다 위험하니까, 투자자들은 그 위험을 감수하는 대가를 요구합니다. 시장이 20% 빠지면 거의 모든 주식이 같이 빠지죠 — 그 공통된 위험 노출을 측정하는 것이 이 팩터입니다.
소형주가 역사적으로 대형주보다 높은 평균 수익률을 기록해왔습니다. 가장 흔한 설명은 소형주가 더 위험하다는 것입니다. 매출이 다각화되지 않았고, 경영진이 얇고, 자본시장 접근성이 떨어집니다. 소형주를 보유하는 투자자는 실질적인 경제적 위험을 감수하는 것이고, SMB는 그 위험에 대한 보상입니다.
5 Factor 모델에서 SMB는 세 가지 정렬(B/M, 수익성, 투자)에서 나온 규모 스프레드의 평균입니다. 단일 정렬에서 나온 3 Factor SMB보다 더 깨끗합니다.
장부가 대비 시가가 높은 "가치주"와 낮은 "성장주" 사이의 수익률 차이입니다. 장부가 대비 시가가 높다는 것은 시장이 그 기업을 회계 가치보다 훨씬 낮게 평가하고 있다는 뜻입니다 — 보통 기업이 어떤 어려움에 처해 있기 때문이죠. 이렇게 외면받는 주식들이 역사적으로 모두가 사고 싶어하는 화려한 성장주보다 높은 수익률을 기록해왔습니다.
이것이 위험 프리미엄인지 행동 편향인지는 재무금융의 큰 논쟁 중 하나입니다. Fama는 위험이라고 하고, Shiller는 잘못된 가격이라고 합니다. 데이터만으로는 결론이 나지 않습니다.
영업이익률이 높은 기업이 낮은 기업보다 높은 수익률을 기록합니다. 직관적으로 이해가 됩니다 — 수익성이 높은 기업은 자기자본 1원당 더 많은 현금흐름을 만들어내고, 시장은 그것에 보상합니다.
왜 원래 모델에 없었을까요? 1993년에는 실증적 증거가 충분하지 않았기 때문입니다. 2015년이 되어서야 충분한 시장과 기간에 걸쳐 패턴이 확인되었습니다.
총자산이 천천히 성장하는(보수적으로 투자하는) 기업이 빠르게 성장하는(공격적으로 투자하는) 기업보다 높은 수익률을 기록합니다. 5가지 팩터 중 가장 직관에 반하는 결과입니다. 많이 투자하는 기업이 성장하니까 수익률이 높을 것 같지만, 데이터는 반대를 말합니다.
한 가지 설명은 공격적 투자가 경영진의 제국 건설이나 수익률이 떨어지는 프로젝트에 대한 과잉투자를 반영한다는 것입니다. 또 다른 설명은 시장이 높은 성장 기대를 가진 기업을 과대평가하는 경향이 있다는 것입니다.
세부사항이 중요합니다. 방법론을 조금만 틀려도 Kenneth French 웹사이트의 공식 팩터와 전혀 다른 결과가 나옵니다.
매년 6월, 모든 주식을 세 가지 특성에 따라 포트폴리오로 분류합니다. 핵심은 Fama-French가 3개의 독립적인 2×3 정렬을 사용한다는 것입니다:
- 규모 × B/M → 6개 포트폴리오 → SMB(B/M)과 HML 산출
- 규모 × 수익성 → 6개 포트폴리오 → SMB(OP)과 RMW 산출
- 규모 × 투자 → 6개 포트폴리오 → SMB(Inv)과 CMA 산출
최종 SMB는 세 SMB 구성요소의 평균입니다.
모든 기준점은 NYSE 주식만으로 계산합니다. NASDAQ과 AMEX에는 아주 작은 주식이 많아서 기준점이 왜곡되기 때문입니다. 규모 기준점은 NYSE 시가총액 중앙값, B/M·수익성·투자 기준점은 NYSE 30번째와 70번째 백분위수입니다.
장부가치는 포트폴리오 구성 최소 6개월 전에 끝난 가장 최근 회계연도의 데이터를 사용합니다. 12월 결산 기업이라면 t-1년 12월 데이터를 t년 6월에 사용합니다. 6개월 간격은 회계 데이터가 실제로 공개된 후에 사용하기 위한 것입니다. 포트폴리오는 t년 7월부터 t+1년 6월까지 유지합니다.
포트폴리오 수익률은 시가총액 가중(전월 말 시가총액 기준)입니다. 공식 Fama-French 팩터와 동일합니다.
구현은 단일 Python 파일(main.py)이며, 명확한 파이프라인으로 구성되어 있습니다:
-
CRSP 다운로드 — 월별 주식 수익률, 가격, 발행주식수를 가져옵니다. 보통주(share code 10, 11)만 필터링하고, 금융업(SIC 6000-6999)을 제외합니다. 상장폐지 수익률을 보정하여 생존편향을 방지합니다.
-
Compustat 다운로드 — 연간 회계 데이터를 가져옵니다. Davis, Fama, French (2000) 정의에 따라 장부가치를 계산합니다: 주주자본 + 이연법인세 − 우선주. 영업이익률과 자산성장률(투자)을 계산합니다.
-
CRSP-Compustat 연결 — CCM 링크 테이블을 사용하여 두 데이터셋을 병합합니다. 링크 유효기간을 확인하고 Primary 링크를 우선합니다.
-
6월 포트폴리오 구성 — 매년 6월, 각 주식의 시가총액과 가장 최근 장부가치(6개월 lag 규칙 적용)를 매칭합니다. B/M, OP, Inv를 계산하고 NYSE 기준점으로 3세트의 6개 포트폴리오를 구성합니다.
-
월별 팩터 수익률 — 7월부터 다음해 6월까지 각 포트폴리오의 시가총액 가중 수익률을 계산합니다. SMB, HML, RMW, CMA를 산출합니다. Kenneth French 데이터에서 무위험수익률을 매칭합니다.
-
출력 — 월별 팩터 수익률을
output/ff5_factors.csv에 저장합니다.
WRDS 계정이 필요합니다 (대부분의 대학에서 기관 접근권을 제공합니다).
pip install wrds pandas numpy pandas-datareader
cp env_example.txt .env
# .env 파일을 열고 WRDS 사용자명과 비밀번호를 입력하세요
python main.py --start 2000-07-01 --end 2023-12-31출력 파일에는 date, mkt_rf, smb, hml, rmw, cma, rf 컬럼이 포함됩니다.
- Fama, E.F. and French, K.R. (2015). "A five-factor asset pricing model." Journal of Financial Economics, 116(1), 1-22.
- Fama, E.F. and French, K.R. (1993). "Common risk factors in the returns on stocks and bonds." Journal of Financial Economics, 33(1), 3-56.
- Davis, J.L., Fama, E.F. and French, K.R. (2000). "Characteristics, Covariances, and Average Returns: 1929 to 1997." Journal of Finance, 55(1), 389-406.
- Kenneth French's Data Library: https://mba.tuck.dartmouth.edu/pages/faculty/ken.french/data_library.html
@software{jihwanw_ff5,
author = {jihwanw},
title = {Fama-French 5 Factor Model},
year = {2026},
publisher = {GitHub},
url = {https://github.com/jihwanw/fama-french-5factor},
doi = {10.5281/zenodo.18883752}
}