<jupyter_start><jupyter_text>Risk analysisBy <NAME>" Nitishinskaya and <NAME>Notebook released under the Creative Commons Attribution 4.0 License.---We can use factor models to analyze the sources of risks and returns in portfolios. Recall that a factor model expresses the returns as$$R_i = a_i + b_{i1} F_1 + b_{i2} F_2 + \ldots + b_{iK} F_K + \epsilon_i$$By modelling the historical returns, we can see how much of them is due to speculation on different factors and how much to asset-specific fluctuations ($\epsilon_p$). We can also examine what sources of risk the portfolio is exposed to. In risk analysis, we often model active returns (returns relative to a benchmark) and active risk (standard deviation of active returns, also known as tracking error or tracking risk).For instance, we can find a factor's marginal contribution to active risk squared (FMCAR). For factor $j$, this is$$ \text{FMCAR}_j = \frac{b_j^a \sum_{i=1}^K b_i^a Cov(F_j, F_i)}{(\text{Active risk})^2} $$where $b_i^a$ is the portfolio's active exposure (exposure different from the benchmark's) to factor $i$. This tells us how much risk we incur by being exposed to factor $j$, given all the other factors we're already exposed to.Fundamental factor models are often used to evaluate portfolios because they correspond directly to investment choices (e.g. whether we invest in small-cap or large-cap stocks, etc.). Below, we construct a model to evaluate a single asset; for more information on the model construction, check out the fundamental factor models notebook.<jupyter_code># Import the libraries we'll be using
import numpy as np
import statsmodels.api as sm
from statsmodels import regression
import matplotlib.pyplot as plt

# Get market cap and book-to-price for all assets in universe
fundamentals = init_fundamentals()
data = get_fundamentals(query(fundamentals.valuation.market_cap,
                              fundamentals.valuation_ratios.book_value_yield), '2015-07-31').T

# Drop missing data
data.dropna(inplace=True)

# Following the Fama-French model, ignore assets with negative book-to-price
data = data.loc[data['book_value_yield'] > 0]
# As per Fama-French, get the top 30% and bottom 30% of stocks by market cap
market_cap_top = data.sort('market_cap')[7*len(data)/10:]
market_cap_bottom = data.sort('market_cap')[:3*len(data)/10]

# Factor 1 is returns on portfolio that is long the top stocks and short the bottom stocks
f1 = (np.mean(get_pricing(market_cap_top.index, fields='price',
                          start_date='2014-07-31', end_date='2015-07-31').pct_change()[1:].T.dropna()) -
      np.mean(get_pricing(market_cap_bottom.index, fields='price',
                          start_date='2014-07-31', end_date='2015-07-31').pct_change()[1:].T.dropna()))

# Repeat above procedure for book-to-price
bp_top = data.sort('book_value_yield')[7*len(data)/10:]
bp_bottom = data.sort('book_value_yield')[:3*len(data)/10]

f2 = (np.mean(get_pricing(bp_top.index, fields='price',
                          start_date='2014-07-31', end_date='2015-07-31').pct_change()[1:].T.dropna()) -
      np.mean(get_pricing(bp_bottom.index, fields='price',
                          start_date='2014-07-31', end_date='2015-07-31').pct_change()[1:].T.dropna()))<jupyter_output><empty_output><jupyter_text>Now that we have our factors, we will use them to model active returns (that is, asset returns less benchmark returns):<jupyter_code># Get returns data for our asset
asset = get_pricing('HSC', fields='price', start_date='2014-07-31', end_date='2015-07-31').pct_change()[1:]
bench = get_pricing('SPY', fields='price', start_date='2014-07-31', end_date='2015-07-31').pct_change()[1:]
active = asset - bench
# Perform linear regression to get the coefficients in the model
b1, b2 = regression.linear_model.OLS(active, sm.add_constant(np.column_stack((f1, f2)))).fit().params[1:]

# Print the coefficients from the linear regression
print 'Sensitivities of active returns to factors:\nMarket cap: %f\nB/P: %f' %  (b1, b2)<jupyter_output>Sensitivities of active returns to factors:
Market cap: 0.031546
B/P: 0.764279<jupyter_text>Using the formula above, we compute the factors' marginal contributions to active risk squared:<jupyter_code>cov = np.cov(f1, f2)
ar_squared = (active.std())**2
fmcar1 = (b1*(b2*cov[0,1] + b1*cov[0,0]))/ar_squared
fmcar2 = (b2*(b1*cov[0,1] + b2*cov[1,1]))/ar_squared
print 'FMCAR_1:', fmcar1
print 'FMCAR_2:', fmcar2<jupyter_output>FMCAR_1: -0.000743366226964
FMCAR_2: 0.0622232250229
{'fraction_non_alphanumeric': 0.1201507426291288, 'fraction_numerical': 0.04743959210818, 'mean_word_length': 4.844559585492228, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '3', 'dir': 'jupyter-structured-clean-dedup', 'id': '334377', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 1592, 'n_tokens_neox': 1437, 'n_words': 457, 'path': 'lectures/drafts/Risk analysis.ipynb', 'repo_name': 'aignas/research_public', 'size': '4538'}