diff options
Diffstat (limited to 'python/exploration/curve_trades.py')
| -rw-r--r-- | python/exploration/curve_trades.py | 157 |
1 files changed, 82 insertions, 75 deletions
diff --git a/python/exploration/curve_trades.py b/python/exploration/curve_trades.py index aee30dcd..89149306 100644 --- a/python/exploration/curve_trades.py +++ b/python/exploration/curve_trades.py @@ -1,16 +1,23 @@ -from index_data import get_index_quotes, index_returns +from index_data import get_index_quotes, index_returns, _serenitas_engine import pandas as pd import math -from scipy.stats.mstats import zscore -import datetime import statsmodels.formula.api as smf -from statsmodels.sandbox.regression.predstd import wls_prediction_std import numpy as np +from statsmodels.sandbox.regression.predstd import wls_prediction_std + import matplotlib.pyplot as plt -def curve_spread_diff(index = 'IG', on_the_run = 28): +def on_the_run(index): + r = _serenitas_engine.execute("SELECT max(series) FROM index_version WHERE index=%s", + (index,)) + series, = r.fetchone() + return series + +def curve_spread_diff(index='IG', rolling=6): + otr = on_the_run(index) ## look at spreads - df = get_index_quotes(index, list(range(on_the_run-6,on_the_run+1)), tenor=['3yr', '5yr', '7yr', '10yr']) + df = get_index_quotes(index, list(range(otr - rolling, otr + 1)), + tenor=['3yr', '5yr', '7yr', '10yr']) spreads = df.groupby(level=['date', 'tenor']).nth(-1)['closespread'].unstack(-1) # remove 'yr' spreads.columns = [int(col[:-2]) for col in spreads.columns] @@ -22,34 +29,38 @@ def curve_spread_diff(index = 'IG', on_the_run = 28): return spreads_diff def spreads_diff_table(spreads_diff): - df = pd.DataFrame() - df['min'] = spreads_diff.min() - df['max'] = spreads_diff.max() - df['average'] = spreads_diff.mean() - df['current'] = spreads_diff.iloc[-1] - df['zscore'] = pd.Series(zscore(spreads_diff)[-1], index = df.index) - pd.DataFrame(zscore(spreads_diff), index=spreads_diff.index, columns=spreads_diff.columns).plot() + def current(s): + return s.iat[-1] + def zscore(s): + return (s.iat[-1] - s.mean()) / s.std() + df = spreads_diff.agg(['min', 'max','mean', current, zscore]) + ((spreads_diff - spreads_diff.mean())/spreads_diff.std()).plot() return df -def theta_matrix_by_series(index = 'IG', on_the_run = 28): - df = get_index_quotes(index, list(range(on_the_run-6,on_the_run+1)), tenor=['3yr', '5yr', '7yr', '10yr']) - df['theta_per_dur'] = df.theta2/df.duration2 +def theta_matrix_by_series(index='IG', rolling=6): + otr = on_the_run(index) + df = get_index_quotes(index, list(range(otr - rolling, otr + 1)), + tenor=['3yr', '5yr', '7yr', '10yr']) + df['theta_per_dur'] = df.theta2 / df.duration2 theta_matrix = df.groupby(level=['date', 'tenor','series']).nth(-1)['theta_per_dur'] - theta_matrix_1 = theta_matrix.xs(theta_matrix.index.max()[0], level = 0).unstack(0) - return theta_matrix_1[['3yr', '5yr', '7yr', '10yr']] + theta_matrix = theta_matrix.loc[theta_matrix.index[-1][0]].unstack(0) + return theta_matrix[['3yr', '5yr', '7yr', '10yr']] -def ratio_within_series(index = 'IG', on_the_run = 28, param = 'duration', groupby_level = ['date', 'series']): - df = get_index_quotes(index, list(range(on_the_run-6,on_the_run+1)), tenor=['3yr', '5yr', '7yr', '10yr']) - r = {} - for i,g in df.groupby(level=groupby_level): - five_yr = g.xs('5yr', level = 'tenor')[param] - r[i] = g[param]/five_yr[-1] - df1 = pd.concat(r) - dftemp= pd.DataFrame(df1.groupby(level=['date', 'tenor','series']).nth(-1).rename(param+'_ratio_to_5yr')) - df2 = df.groupby(level=['date', 'tenor','series']).nth(-1).merge(dftemp, left_index=True, right_index=True) - return df2.unstack(-2) +def ratio_within_series(index='IG', rolling=6, param='duration'): + otr = on_the_run(index) + df = get_index_quotes(index, list(range(otr - rolling, otr + 1)), + tenor=['3yr', '5yr', '7yr', '10yr']).unstack() + ratio = (df[param]. + apply(lambda s: s / df[param]['5yr'].values, raw=True)) + ratio.columns = pd.MultiIndex.from_product([[param + '_ratio_to_5yr'], ratio.columns]) + df = df.join(ratio) + return df.groupby(['date', 'index']).nth(-1) def curve_3_5_10(df): + """ + Parameters + ---------- + df: duration ratio within series""" #buy 3y, sell 5y, buy 10y df['3_5_10'] = - df.theta2['3yr'] / df.duration_ratio_to_5yr['3yr'] \ + 2 * df.theta2['5yr'] \ @@ -61,72 +72,70 @@ def curve_5_10(df): df['5_10'] = df.theta2['5yr'] - df.theta2['10yr'] / df.duration_ratio_to_5yr['10yr'] df['5_10'].dropna().unstack(-1).plot() -def on_the_run_theta(index = 'IG', on_the_run = 28): - df = get_index_quotes(index, list(range(on_the_run-6,on_the_run+1)), tenor=['3yr', '5yr', '7yr', '10yr']) +def on_the_run_theta(index='IG', rolling=6): + otr = on_the_run(index) + df = get_index_quotes(index, list(range(otr - rolling, otr + 1)), + tenor=['3yr', '5yr', '7yr', '10yr']) df['theta_per_dur'] = df.theta2/df.duration2 theta_matrix = df.groupby(level=['date', 'tenor']).nth(-1)['theta_per_dur'] theta_matrix.unstack(-1).plot() -def curve_returns(index = 'IG', on_the_run = 28): +def curve_returns(index='IG', rolling=6): ## look at returns - df = index_returns(index= index, series=list(range(on_the_run-6,on_the_run+1)), tenor=['3yr', '5yr', '7yr', '10yr']) + otr = on_the_run(index) + df = index_returns(index= index, series=list(range(otr - rolling, otr + 1)), + tenor=['3yr', '5yr', '7yr', '10yr']) ## on-the-run returns returns = df.price_return.unstack(-1).dropna().groupby(level='date').nth(-1) strategy = ['510', '710', '3510'] + strategies_return = pd.DataFrame( + {'5-10': 1.78 * returns['5yr'] - returns['10yr'], + '7-10': 1.33 * returns['7yr'] - returns['10yr'], + '3-5-10': -2 * returns['3yr'] + 3 * returns['5yr'] - returns['10yr']}) + strategies_return_monthly = (strategies_return. + groupby(pd.TimeGrouper(freq='M')). + agg(lambda df: (1 + df).prod() - 1)) - strategies_return = pd.DataFrame() - strategies_return[strategy[0]] = 1.78 * returns['5yr'] - returns['10yr'] - strategies_return[strategy[1]] = 1.33 * returns['7yr'] - returns['10yr'] - strategies_return[strategy[2]] = -2 * returns['3yr']+ 3 * returns['5yr'] - 1 * returns['10yr'] - - strategies_return_monthly = pd.DataFrame() - for strat in strategy: - strategies_return_monthly[strat] = strategies_return[strat].groupby(pd.TimeGrouper(freq='M')).agg(lambda df:(1+df).prod()-1) - - results = pd.DataFrame() - sharpe = {} - monthly_sharpe = {} - for strat in strategy: - sharpe[strat] = strategies_return[strat].mean()/strategies_return[strat].std()*math.sqrt(252) - monthly_sharpe[strat] = strategies_return_monthly[strat].mean()/strategies_return_monthly[strat].std()*math.sqrt(12) + def sharpe(df, period="daily"): + if period == "daily": + return df.mean() / df.std() * math.sqrt(252) + else: + return df.mean() / df.std() * math.sqrt(12) - worst_drawdown = {} - for strat in strategy: - worst_drawdown[strat] = strategies_return[strat].nsmallest(10).mean() + results = strategies_return.agg([sharpe, lambda df: df.nsmallest(10).mean()]) + sharpe_monthly = strategies_return_monthly.agg(sharpe, period="monthly") + sharpe_monthly.name = 'Monthly Sharpe' + results.index=['Sharpe', 'Mean Worst 10 Days DrawDown'] + return results.append(sharpe_monthly) - results = results.append(sharpe, ignore_index=True) - results = results.append(monthly_sharpe, ignore_index=True) - results = results.append(worst_drawdown, ignore_index=True) - results['results'] = ['Sharpe','Monthly Sharpe','Mean Worst 10 Days Drawdown'] - - return results.set_index('results') - -def cross_series_curve(index = 'IG', on_the_run = 28): - - df = index_returns(index= index, series=list(range(on_the_run-6,on_the_run+1)), tenor=['3yr', '5yr', '7yr', '10yr']) +def cross_series_curve(index='IG', rolling=6): + otr = on_the_run(index) + df = index_returns(index= index, series=list(range(otr - rolling, otr + 1)), + tenor=['3yr', '5yr', '7yr', '10yr']) ## look cross series - 3y to 5y returns1 = df.xs(['5yr', index], level = ['tenor','index']).price_return.unstack(-1) price_diff = pd.DataFrame() - for ind in list(range(on_the_run-2, on_the_run+1)): - price_diff[ind] = returns1[ind] - 1.6* returns1[ind - 4] + for ind in list(range(otr - 2, otr + 1)): + price_diff[ind] = returns1[ind] - 1.6 * returns1[ind - 4] price_diff = price_diff.stack().groupby(level = 'date').nth(-1) - monthly_returns_cross_series = price_diff.groupby(pd.TimeGrouper(freq='M')).agg(lambda df:(1+df).prod()-1) + monthly_returns_cross_series = (price_diff. + groupby(pd.TimeGrouper(freq='M')). + agg(lambda df: (1 + df).prod() - 1)) plt.plot(monthly_returns_cross_series) -def forward_loss(): - from db import dbengine, dbconn - serenitasdb = dbengine('serenitasdb') - index = 'IG' +def forward_loss(index='IG'): start_date = (pd.Timestamp.now() - pd.DateOffset(years=3)).date() - df = pd.read_sql_query("SELECT date, index, series, tenor, duration, closespread, closespread*duration/100 as indexel " \ + df = pd.read_sql_query("SELECT date, index, series, tenor, duration, closespread, "\ + "closespread*duration / 100 AS indexel " \ "FROM index_quotes WHERE index=%s AND date >= %s " \ "ORDER BY date DESC, series ASC, duration ASC", serenitasdb, parse_dates=['date'], params=[index, start_date]) - df1 = pd.read_sql_query("select index, series, tenor, maturity from index_maturity", serenitasdb, parse_dates=['maturity']) + df1 = pd.read_sql_query("SELECT index, series, tenor, maturity FROM index_maturity", + serenitasdb, parse_dates=['maturity']) df = df.merge(df1, on=['index','series','tenor']) df = df.set_index(['date','index', 'maturity']).dropna() @@ -142,12 +151,12 @@ def read_IG_curve_pos(): portf = Portfolio([trade_1, trade_2, trade_3]) def curve_model(): - #OLS model - df = ratio_within_series(param = 'closespread', groupby_level = ['date', 'series']) + df = ratio_within_series(param='closespread') df = df.groupby(level='date').last() - df = pd.concat([df.duration['5yr'],df.closespread['5yr'], df.closespread_ratio_to_5yr['10yr']], axis = 1, keys=['duration', 'closespread', 'ratio']) + df = pd.concat([df.duration['5yr'], df.closespread['5yr'], df.closespread_ratio_to_5yr['10yr']], + axis=1, keys=['duration', 'closespread', 'ratio']) results = smf.ols('np.log(ratio) ~ np.log(duration) + np.log(closespread)', data=df).fit() df['predicted'] = np.exp(results.predict()) results.summary() @@ -155,10 +164,8 @@ def curve_model(): df['up_2_stdev'] = np.exp(iv_u) df['down_2_stdev'] = np.exp(iv_l) - #dr/dspread = exp(k) + spread_coeff * duration ^ dur_coeff * spread ^ (spread_coeff-1) + #dr/dspread = exp(k) * spread_coeff * duration ^ dur_coeff * spread ^ (spread_coeff-1) df['dr_dspread'] = np.exp(results.params[0]) * results.params[2] * df.duration ** results.params[1] * df.closespread ** (results.params[2] -1) df['beta'] = df.dr_dspread * df.closespread return df - - |
