def strategy_capm(returns, start_date):
     """
     CAPM using lagged optimal market portfolio tracker to predict 
     company stock return. Positions are assigned as follows:
         - Buy when predicted return > expected return
         - Sell when predicted return < expected return
         - No transaction costs. For now.
     """
     mkt_return = pdr.get_data_famafrench(
         'F-F_Research_Data_Factors_daily',
         start='1-1-2010')[0]['Mkt-RF'] / 100
     rf = pdr.get_data_famafrench('F-F_Research_Data_Factors_daily',
                                  start='1-1-2010',
                                  end=start_date)[0]['RF']
     ols_capm = {
         'slope': None,
         'intercept': None,
         'r_value': None,
         'p_value': None,
         'std_err': None
     }
     returns = returns.shift(1)
     for ret in returns.columns:
         slope, intercept, r_value, p_value, std_err = linregress(
             mkt_return, y=returns[ret])
         ols_capm['slope'].add(slope)
         ols_capm['intercept'].add(intercept)
         ols_capm['r_value'].add(r_value)
         ols_capm['p_value'].add(p_value)
         ols_capm['std_err'].add(std_err)
     return ols_capm
Example #2
0
def load_industries():
    """Load industry portfolio returns from Ken French's website.

    Returns
    -------
    industries : dictionary of Pandas DataFrames
        Each key is a portfolio group.

    Example
    -------
    >>> from pyfinance import datasets
    >>> ind = datasets.load_industries()

    # Monthly returns to 5 industry portfolios
    >>> ind[5].head()
                Cnsmr  Manuf  HiTec  Hlth   Other
    Date
    1950-01-31   1.26   1.47   3.21   1.06   3.19
    1950-02-28   1.91   1.29   2.06   1.92   1.02
    1950-03-31   0.28   1.93   3.46  -2.90  -0.68
    1950-04-30   3.22   5.21   3.58   5.52   1.50
    1950-05-31   3.81   6.18   1.07   3.96   1.36
    """

    n = [5, 10, 12, 17, 30, 38, 48]
    port = ("%s_Industry_Portfolios" % i for i in n)
    rets = []
    for p in port:
        ret = pdr.get_data_famafrench(p, start=DSTART)[0]
        rets.append(ret.to_timestamp(how="end", copy=False))
    industries = dict(zip(n, rets))
    return industries
Example #3
0
import statsmodels.api as sm
from statsmodels.regression.rolling import RollingOLS

seaborn.set_style("darkgrid")
pd.plotting.register_matplotlib_converters()

# `pandas-datareader` is used to download data from
# [Ken French's website](https://mba.tuck.dartmouth.edu/pages/faculty/ken.
# french/data_library.html).
# The two data sets downloaded are the 3 Fama-French factors and the 10
# industry portfolios.
# Data is available from 1926.
#
# The data are monthly returns for the factors or industry portfolios.

factors = pdr.get_data_famafrench("F-F_Research_Data_Factors",
                                  start="1-1-1926")[0]
factors.head()

industries = pdr.get_data_famafrench("10_Industry_Portfolios",
                                     start="1-1-1926")[0]
industries.head()

# The first model estimated is a rolling version of the CAPM that
# regresses
# the excess return of Technology sector firms on the excess return of the
# market.
#
# The window is 60 months, and so results are available after the first 60
# (`window`)
# months. The first 59 (`window - 1`) estimates are all `nan` filled.
Example #4
0
                   linestyle='--',
                   linewidth=1.0)


# compare the return distribution of 3 firms visually...

grid = sns.pairplot(daily_pct_change, diag_kind='kde', kind="reg")
grid.map_offdiag(plot_unity)  # how cool is that!

###############################################################################
# get the factor loadings
###############################################################################

# get FF factors merged with the stock returns
ff = pdr.get_data_famafrench(
    'F-F_Research_Data_5_Factors_2x3_daily', start=2006
)[0]  # the [0] is because the imported obect is a dictionary, and key=0 is the dataframe
ff.rename(columns={"Mkt-RF": "mkt_excess"}, inplace=True)  # cleaner name
ff = ff.join(daily_pct_change, how='inner')  # merge with stock returns
for stock in ['MSFT', 'AAPL', 'VZ']:
    ff[stock] = ff[
        stock] * 100  # FF store variables as percents, so convert to that
    ff[stock + '_excess'] = ff[stock] - ff[
        'RF']  # convert to excess returns in prep for regressions
print(ff.describe())  # ugly...
pd.set_option('display.float_format',
              lambda x: '%.2f' % x)  # show fewer digits
pd.options.display.max_columns = ff.shape[1]  # show more columns
print(ff.describe(include='all'))  # better!

# run the models-
import pandas_datareader as pdr
import pandas as pd
import statsmodels.api as sm
from statsmodels.regression.rolling import RollingOLS
from statsmodels.api import OLS, add_constant
import matplotlib.pyplot as plt
import seaborn
seaborn.set_style('darkgrid')
pd.plotting.register_matplotlib_converters()

#%%
factors = pdr.get_data_famafrench('F-F_Research_Data_Factors', start='1-1-2020')[0]
# print(factors.head())
industries = pdr.get_data_famafrench('17_Industry_Portfolios', start='1-1-2020')[0]
# print(industries.head())

#%%
exog_vars = ['Mkt-RF', 'SMB', 'HML','RF']
exog = sm.add_constant(factors[exog_vars])
returns = industries.sub(factors.RF, axis=0)


#%%
betas = []
rsquared = []
#%%
for industry in returns.columns:
    # print(returns.loc[returns.index, industry])
    endog = returns.loc[returns.index, industry]
    rols = RollingOLS(endog, exog, window=12)
    rres = rols.fit()