Fama-French 3-factor model

Build on CAPM by incorporating additional independent variables.

Table of contents

Factors that Fama-French utilizes

  • Market risk (just like in CAPM)
  • SMB : Outperformance of small-cap stocks vs large-cap
  • HML : Outperformance of high book-to-market stocks vs small book-to-market

Fama-French model:

  • $r = R_f + \beta(R_m - R_f) + b_s\cdot SMB + b_v\cdot HML + \alpha$
  • $\beta$ will not be equal to the CAPM $\beta$ since there are additional factors
  • The $b_s$ and $b_v$ coefficients can be positive or negative
  • Explains ~90% of a diversified portfolio's returns
    • CAPM usually explains ~70%

Conduct a factor analysis using a Fama-French model on industry returns from 1970 to 2015

In [1]:
import numpy as np
import pandas as pd
import edhec_risk_kit as erk
import statsmodels.api as sm

Which industry portfolio learned most towards small-cap stocks vs large-cap?

In [2]:
ind_rets = erk.get_ind_returns(n_inds=49)
fff = erk.get_fff_returns()
ind_excess = ind_rets['1970':'2015'] - fff.loc['1970':'2015', ['RF']].values
mkt_excess = fff.loc['1970':'2015', ['Mkt-RF']]
exp_var = mkt_excess.copy()
exp_var['SMB'] = fff.loc['1970':'2015', ['SMB']]
exp_var['HML'] = fff.loc['1970':'2015', ['HML']]
exp_var['Constant'] = 1

lm = sm.OLS(ind_excess, exp_var).fit()
result = erk.regress(ind_excess, exp_var)
In [3]:
smb_idx_max = result.params.loc['SMB', :].idxmax()
ind_rets.columns[smb_idx_max]
Out[3]:
'RlEst'

Industry with highest tilt toward large-cap stocks?

In [4]:
smb_idx_min = result.params.loc['SMB', :].idxmin()
ind_rets.columns[smb_idx_min]
Out[4]:
'Drugs'

Industry with highest tilt toward high-value stocks?

In [5]:
hml_idx_max = result.params.loc['HML', :].idxmax()
ind_rets.columns[hml_idx_max]
Out[5]:
'RlEst'

Industry with highest tilt toward low-value stocks?

In [6]:
hml_idx_min = result.params.loc['HML', :].idxmin()
ind_rets.columns[hml_idx_min]
Out[6]:
'Softw'

Conduct a factor analysis using a Fama-French model with erk.ff_analysis()

Get the tilts of software returns from 1980 to 2018

In [7]:
ind_rets = erk.get_ind_returns(n_inds=49)['1980':'2018']
fff = erk.get_fff_returns()['1980':'2018']
softw_rets = ind_rets.loc[:, ['Softw']]

erk.ff_analysis(r=softw_rets, factors=fff[['Mkt-RF', 'SMB', 'HML']])
Out[7]:
Softw
Mkt-RF 1.244071
SMB 0.181616
HML -0.940287
Alpha 0.008804

Get the tilts of the Emerging Market returns from the EDHEC hedge fund returns dataset over the same period

In [8]:
hfi_rets = erk.get_hfi_returns()['1980':'2018']
emr_market_rets = hfi_rets['Emerging Markets']
erk.ff_analysis(r=emr_market_rets, factors=fff[['Mkt-RF', 'SMB', 'HML']])
Out[8]:
Mkt-RF    0.486529
SMB       0.138631
HML      -0.012655
Alpha     0.003075
dtype: float64