import math import os import pandas as pd import feather from index_data import index_returns, get_index_quotes from arch import arch_model from math import log, exp, sqrt import numpy as np from scipy.optimize import minimize_scalar from statsmodels.tsa.ar_model import AR import matplotlib.pyplot as plt def calc_returns(): returns = index_returns(index=['IG', 'HY'], tenor='5yr') returns_hy = (returns. xs('HY', level=1). dropna(). reset_index(level='series'). groupby(level=['date']). nth(-1)) returns_hy = returns_hy.set_index('series', append=True) returns_ig = returns.xs('IG', level=1).reset_index('tenor', drop=True) # hy starts trading later than ig, so we line it up based on hy series df = pd.merge(returns_hy, returns_ig, left_index=True, right_index=True, suffixes=('_hy','_ig')) returns = df[['price_return_hy', 'price_return_ig']] returns.columns = ['hy', 'ig'] #feather.write_dataframe(returns.reset_index(), # os.path.join(os.environ["DATA_DIR"], "index_returns.fth")) return returns.reset_index('series', drop=True) def calc_betas(returns=None, spans=[5, 20]): if returns is None: returns = calc_returns() return [(returns. ewm(span=span). cov(). groupby(level='date'). apply(lambda df: df.values[0,1]/df.values[1,1])) for span in spans] def plot_betas(betas=None): spans = [5, 20] if betas is None: betas = calc_betas(spans) for beta, span in zip(betas, spans): plt.plot(beta, label = 'EWMA'+str(span)) plt.xlabel('date') plt.ylabel('beta') plt.legend() def calc_realized_vol(returns=None): # three ways of computing the volatility # 1) 20 days simple moving average # 2) exponentially weighted moving average # 3) GARCH(1,1), we scale returns by 10 to help with the fitting if returns is None: returns = calc_returns() vol_sma = returns.rolling(20).std() * math.sqrt(252) vol_ewma = returns.ewm(span=20).std() * math.sqrt(252) scale = 10 vol_garch = pd.DataFrame() for index in returns: am = arch_model(scale * returns[index].dropna()) res = am.fit() vol_garch[index] = res.conditional_volatility * math.sqrt(252)/scale vol = pd.concat([vol_sma, vol_ewma, vol_garch], axis=1, keys=['sma', 'ewma', 'garch']) return vol #feather.write_dataframe(beta_ewma.to_frame('beta'), # os.path.join(os.environ['DATA_DIR'], "beta.fth")) def spreads_ratio(series=list(range(22, 29)), index=['IG', 'HY'], tenor='5yr'): df = get_index_quotes(series=series, index=index, tenor=tenor) df = df['modelspread'].groupby(['date', 'index']).last().unstack() df['ratio'] = df.HY / df.IG return df def loglik(beta, returns): x = (returns.hy - beta*returns.ig) model = AR(x, missing='drop') fit = model.fit(maxlag=1) return - fit.llf if __name__ == "__main__": returns = calc_returns() betas = calc_betas(returns) plot_betas(betas) vol = calc_realized_vol(returns) ratios = spreads_ratio() prog = minimize_scalar(loglik, bracket=(3, 5), args=(returns,))