aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/mark_backtest.py78
-rw-r--r--python/mark_backtest_underpar.py94
-rw-r--r--python/marks_to_HY.py26
3 files changed, 79 insertions, 119 deletions
diff --git a/python/mark_backtest.py b/python/mark_backtest.py
deleted file mode 100644
index 970e8b6f..00000000
--- a/python/mark_backtest.py
+++ /dev/null
@@ -1,78 +0,0 @@
-import pandas as pd
-from db import dbengine
-import matplotlib
-import numpy as np
-import matplotlib.pyplot as plt
-import statsmodels.api as sm
-from statsmodels.formula.api import gls
-
-df = (pd.read_sql_table('external_marks_mapped',dbengine('dawndb'),
- parse_dates=['date']).
- sort_values('date'))
-df1 = pd.read_sql_query("select trade_date, cusip as identifier, principal_payment, price from bonds where buysell = 'f'"
- ,dbengine('dawndb'),
- parse_dates=[
- 'trade_date'
- ])
-df1 = df1.sort_values('trade_date')
-d = {}
-for source, g in df.groupby('source'):
- d[source] = pd.merge_asof(df1, g, left_on='trade_date', right_on= 'date', by='identifier')
-df2 = pd.concat(d, join='inner')
-df3 = df2.dropna(axis=0, subset=['mark'])
-df3 = df3.reset_index(level=1, drop=True)
-df4 = df3.set_index(['trade_date','identifier', 'source', 'principal_payment'])
-df4 = df4.groupby(level=['trade_date', 'identifier','source', 'principal_payment']).mean()
-df4 = df4.set_index('price', append=True)
-df5 = df4.unstack(-3)
-df5.columns = df5.columns.droplevel()
-#df6 = df5.reset_index(col_level=1, drop=True)
-df6 = df5.sortlevel(0, ascending = False)
-df6 = df6.reset_index()
-
-r2 = {}
-stderr = {}
-parameters = {}
-#for g in df5['mark']:
-for col in df6.columns[4:]:
- regmodel = gls(formula= "df6['price'] ~df6[col]", data = df6).fit()
- r2[col] = regmodel.rsquared
- stderr[col] = regmodel.bse
- parameters[col] = regmodel.params
-
-r2 = pd.Series(r2, name= 'R2')
-r2.index.name = 'Source'
-r2.reset_index
-r2 = pd.DataFrame(r2)
-stderr = pd.DataFrame(stderr)
-parameters = pd.DataFrame(parameters)
-
-df7 = df6
-for col in df7.columns[4:]:
- df7[col] = (df7.price - df7[col])/df7[col]
-
-filter = 2
-begindate = '2015-01-01'
-enddate = '2017-01-01'
-df8 = df7[(df7['trade_date']>begindate) & (df7['trade_date']<enddate)]
-difference= pd.DataFrame(df8[df8<filter].mean(), columns=['Average'])
-difference['Std Dev'] = df8[df8<filter].std()
-difference.reset_index()
-
-writer = pd.ExcelWriter('/home/serenitas/edwin/Subprime_ModelandBacktest_outputonly.xlsx')
-df6.to_excel(writer, sheet_name = 'BackTesting', header = True, na_rep = '', startrow= 1, startcol= 1)
-r2.to_excel(writer, sheet_name = 'regression', header = True)
-parameters.to_excel(writer, sheet_name = 'regression', header = True, startrow= 0, startcol= 5)
-difference[2:].to_excel(writer, sheet_name = 'Diff', header = True, startrow= 1, startcol= 1)
-df7.to_excel(writer, sheet_name = 'Diff', header = True, startrow= 15, startcol= 1)
-writer.save()
-
-#fig = plt.plot(figsize=(12,8))
-#fig = sm.graphics.plot_partregress_grid(regmodel,fig=fig)
-
-
-#df6 = pd.DataFrame()
-#for g in df5['mark']:
-# d[g] = (df5['price'] - df5['mark'][g])/df5['mark'][g]
-#df6.from_dict(d)
-
diff --git a/python/mark_backtest_underpar.py b/python/mark_backtest_underpar.py
index 3d1239a2..c6128b13 100644
--- a/python/mark_backtest_underpar.py
+++ b/python/mark_backtest_underpar.py
@@ -7,59 +7,95 @@ import statsmodels.api as sm
from statsmodels.formula.api import gls
import seaborn as sb
-df = pd.read_sql_table('external_marks_mapped',dbengine('dawndb'),
+df = pd.read_sql_table('external_marks_mapped', dbengine('dawndb'),
parse_dates=['date'])
df = df[df.source.notnull()]
df_wide = (pd.pivot_table(df, 'mark', ['identifier', 'date'], 'source').
reset_index().
sort_values('date'))
-df_trades = pd.read_sql_query("select trade_date, identifier, principal_payment, price " \
+
+df_trades = {}
+df_trades['sell'] = pd.read_sql_query("select trade_date, identifier, faceamount, principal_payment, price " \
"from bonds where buysell = 'f'"
- ,dbengine('dawndb'),
- parse_dates=['trade_date'])
-df_trades = df_trades.sort_values('trade_date')
-df_wide = pd.merge_asof(df_trades, df_wide, left_on='trade_date', right_on='date', by='identifier')
-d = {}
+ , dbengine('dawndb'),
+ parse_dates=['trade_date'])
+df_trades['buy'] = pd.read_sql_query("select trade_date, identifier, faceamount, principal_payment, price " \
+ "from bonds where buysell = 't'"
+ , dbengine('dawndb'),
+ parse_dates=['trade_date'])
+for direction, trades in df_trades.items():
+ df_trades[direction] = trades.sort_values('trade_date')
+
+df_sell_wide = pd.merge_asof(df_trades['sell'], df_wide, left_on='trade_date', right_on='date', by='identifier')
+df_wide_temp = df_wide.set_index('date').shift(periods = -1, freq= 'M', axis = 1).reset_index()
+df_buy_wide = pd.merge_asof(df_trades['buy'], df_wide_temp
+ , left_on='trade_date', right_on='date', by='identifier')
+
+d_sell = {}
+d_buy = {}
+df_long = {}
+
for source, g in df.groupby('source'):
- d[source] = pd.merge_asof(df_trades, g, left_on='trade_date', right_on='date', by='identifier')
-df_long = pd.concat(d, join='inner')
-df_long = df_long.reset_index()
-df_long = df_long.dropna(subset=['price','mark'])
+ d_sell[source] = pd.merge_asof(df_trades['sell'], g, left_on='trade_date', right_on='date', by='identifier')
+ d_sell[source]['dir'] = 'sell'
+ d_buy[source] = pd.merge_asof(df_trades['buy'], g.set_index('date').shift(periods = -1, freq= 'BM', axis = 1).reset_index(), left_on='trade_date', right_on='date', by='identifier')
+ d_buy[source]['dir'] = 'buy'
+
+#add a column saying it is buy or sell
+
+df_long = pd.concat(d_sell, join='inner')
+df_long = df_long.append(pd.concat(d_buy, join='inner'))
+df_long = df_long.reset_index().dropna(subset=['price','mark'])
+df_long['difference'] = (df_long['price'] - df_long['mark'])/df_long['mark']
#filtering
diff_threshold = 5
begindate = '2013-01-01'
enddate = '2018-01-01'
+
df_long = df_long[df_long.identifier.str.len() == 9]
df_long = df_long[(df_long['trade_date'] > begindate) & (df_long['trade_date'] < enddate)]
-#difference= df_long[df_long['<filter].groupby('level_0').[.mean(), columns=['Average'])
+
#difference['Std Dev'] = df_long[df_long<filter].std()
#pretty plot
-#dotsize = pd.Series.tolist(df_long['level_0'].apply(lambda x: 400 if x == 'MANAGER' else 20))
#df_long['dotsize'] = df_long['level_0'].apply(lambda x: 400 if x == 'MANAGER' else 20)
-df_long['dotsize'] = df_long['level_0'].apply(lambda x: 400 if x == 'MANAGER' else 20)
+
plt.switch_backend('Agg')
sb.set_style("whitegrid")
sb.set_context("notebook")
-regplot = sb.lmplot(x='mark', y='price', hue = 'source', data=df_long, fit_reg=False, legend_out=True, aspect = 2.1, size = 4, scatter_kws={"s": df_long['dotsize']})
-regplot.set(ylim=(0, 105), xlim=(0, 105))
-#plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
-#regplot.fig.savefig("/home/serenitas/edwin/fig1.png")
-
#plt.switch_backend('Qt4Agg')
order = ['MANAGER','BROKER','BVAL','IDC','MARKIT','PB','PRICESERVE','PRICINGDIRECT','REUTERS','S&P']
sb.set_palette(sb.hls_palette(10, l=.4, s=.8))
-g = sb.FacetGrid(df_long, hue='source', hue_kws={'s':[50] + [20]*9, 'marker': ["o"]+["s"]*9, 'alpha': [1]+[.4]*9}, legend_out=True, aspect = 2.1, size = 4, hue_order = order)
-g.set(ylim=(0, 105), xlim=(0, 105))
-ax = g.map(plt.scatter, 'mark', 'price').add_legend()
-ax.fig.savefig("/home/serenitas/edwin/fig2.png")
+
+g_sell = sb.FacetGrid(df_long[df_long.dir == 'sell'], hue='source', hue_kws={'s':[50] + [20]*9, 'marker': ["o"]+["s"]*9, 'alpha': [1]+[.4]*9}, legend_out=True, aspect = 2.1, size = 4, hue_order = order)
+g_sell.set(ylim=(0, 105), xlim=(0, 105))
+ax_sell = g_sell.map(plt.scatter, 'mark', 'price').add_legend()
+
+g_buy = sb.FacetGrid(df_long[df_long.dir == 'buy'], hue='source', hue_kws={'s':[50] + [20]*9, 'marker': ["o"]+["s"]*9, 'alpha': [1]+[.4]*9}, legend_out=True, aspect = 2.1, size = 4, hue_order = order)
+g_buy.set(ylim=(0, 105), xlim=(0, 105))
+ax_buy = g_buy.map(plt.scatter, 'mark', 'price').add_legend()
+
+ax_sell.fig.savefig("/home/serenitas/edwin/backtest_sales.png")
+ax_buy.fig.savefig("/home/serenitas/edwin/backtest_buys.png")
+
+params = {}
+error = {}
+trade_PNL = {}
+trade_PNL_stat = {}
#fit all the models at once
-params = (df_long.
- groupby('source').
- apply(lambda df: gls('price~mark', df).fit().params))
-df_long['diff'] = (df_long['price'] - df_long['mark'])/df_long['mark']
-error = [df_long[df_long['diff'] < diff_threshold].groupby('source').mean()['diff'],
- df_long[df_long['diff'] < diff_threshold].groupby('source').std()['diff']]
+for direction, df_temp in df_long[(df_long.difference < diff_threshold)].groupby('dir'):
+ params[direction] = (df_temp.
+ groupby('source').
+ apply(lambda df: gls('price~mark', df).fit().params))
+ error[direction] = [df_temp.groupby('source').mean()['difference'],
+ df_temp.groupby('source').std()['difference']]
+ trade_PNL[direction] = df_temp.groupby(['date', 'source']).apply(
+ lambda df: sum(df.principal_payment * df.difference)/
+ sum(df.principal_payment))
+ trade_PNL_stat[direction] = [trade_PNL[direction].groupby(level = 'source').mean(),
+ trade_PNL[direction].groupby(level = 'source').std()]
+
+buychart = trade_PNL['buy'].unstack(-1).plot()
diff --git a/python/marks_to_HY.py b/python/marks_to_HY.py
index ff4e72ea..f20f7711 100644
--- a/python/marks_to_HY.py
+++ b/python/marks_to_HY.py
@@ -4,6 +4,7 @@ import numpy as np
import statsmodels.api as sm
from statsmodels.formula.api import ols
from pandas.tseries.offsets import MonthEnd
+from scipy.interpolate import interp1d
import datetime
from pandas.tseries.offsets import *
import bbg_helpers
@@ -12,14 +13,15 @@ import bbg_helpers
#import matplotlib
#matplotlib.use("Q4Agg") #to prevent conflict with PyQT4
-def monthlySpreadDiff(index="IG", tenor="5yr", period="1yr"):
+def monthlySpreadDiff(index="IG", tenor="5yr"):
date = (pd.Timestamp.now() - pd.DateOffset(years=4)).date()
- sql_str = "SELECT date, series, closespread AS spread FROM index_quotes " \
+ sql_str = "SELECT date, series, version, closespread AS spread FROM index_quotes " \
"WHERE index=%s and date>=%s and tenor = %s"
df = pd.read_sql_query(sql_str, dbengine('serenitasdb'), parse_dates=['date'], index_col=['date', 'series'],
params=(index.upper(), date, "5yr"))
- df1 = df.unstack(level=1).resample('1m').last().diff(periods = period)
- df1 = df1.stack(level = 1).groupby(level = 'date').last()
+ df1 = df.groupby(level = ['date','series']).last()
+ df1 = df1.unstack(level = 1).resample('1m').last().diff()
+ df1 = df1.stack(level = 1).groupby(level = 'date').last()['spread']
return df1
def nearestDate(base, dates):
@@ -115,7 +117,6 @@ df1.adjpv= df1.adjpv.where(df1.adjpv.notnull(), df1.pv)
df1['spread'] = (df1['adjpv']*100-df1['mark'])/df1['moddur']*100
df1 = df1.set_index(['monthend_date','identifier','source'])
-return df1
#difference = difference in spread
#Filter
@@ -125,7 +126,7 @@ DurationFilter = 1.5
begindate = '2014-01-01'
enddate = '2017-01-01'
interval = 1
-HYDifference = monthlySpreadDiff(index = 'HY', period = interval)
+HYDifference = monthlySpreadDiff(index = 'HY')
difference = df1[abs(df1['spread'])<SpreadFilter].groupby(level=['identifier','source'])['pv','moddur','spread'].diff(periods = interval)
difference = difference[abs(difference['spread'])<SpreadDiffFilter]
difference = difference[abs(difference['moddur'])<DurationFilter]
@@ -133,15 +134,15 @@ difference.spread = difference.spread.astype(np.float64)
#method 1: for all sources - average through Time
avgchange1 = pd.DataFrame(difference.groupby(level=['monthend_date']).mean()['spread'])
-avgchange1 = avgchange1.merge(HYDifference, left_index = True, right_index= True)
-avgchange1 = avgchange1.rename(columns={'spread_x': 'marks', 'spread_y':'HY'})
+avgchange1 = avgchange1.join(HYDifference, rsuffix = 'HY')
avgchange1 = avgchange1[begindate:enddate]
-regmodel1 = sm.OLS(avgchange1['marks'],avgchange1['HY']).fit()
-ratio1 = (avgchange1['HY']/avgchange1['marks']).mean()
+regmodel1 = sm.OLS(avgchange1['spread'],avgchange1['spreadHY']).fit()
+ratio1 = (avgchange1['spreadHY']/avgchange1['spread']).mean()
#method 2: look at it source by source
avgchange2 = pd.DataFrame(difference.groupby(level=['monthend_date','source']).mean()['spread'])
avgchange2 = avgchange2.unstack(level =1)
+HYDifference = HYDifference.to_frame()
HYDifference.columns = pd.MultiIndex.from_arrays([['Index'],['HY']])
avgchange2 = avgchange2.merge(HYDifference, left_index = True, right_index= True)
regmodel2 ={}
@@ -161,12 +162,13 @@ for source in regmodel2:
difference1 = difference.reset_index().set_index('monthend_date')
#difference1 = difference1.loc[difference1['source'].isin(['PRICINGDIRECT','PRICESERVE'])]
#difference1 = difference1[(difference1['source'] == 'PRICESERVE')]
+HYDifference.columns = pd.MultiIndex.from_arrays([('HY',)])
difference1 = difference1.merge(HYDifference, left_index = True, right_index= True)
regmodel3 = {}
Rsquared3 = {}
params3 = {}
for source, g in difference1.groupby('source'):
- regmodel3[source] = sm.OLS(g['spread'],g[('Index', 'HY')], missing = 'drop').fit()
+ regmodel3[source] = sm.OLS(g['spread'],g['HY'], missing = 'drop').fit()
Rsquared3[source] = regmodel3[source].rsquared
params3[source] = regmodel3[source].params
#regmodel3.summary()
@@ -174,7 +176,7 @@ for source, g in difference1.groupby('source'):
#method 4: Let's just look at how spread changes within each source (i.e. see if spread widening ==> lower marks for most/all bonds?)
#difference.xs('PRICESERVE', level = 'source', drop_level=False)
#difference2[difference2['source']=='BVAL'].to_clipboard()
-difference4 = difference1.rename(columns = {('Index', 'HY'): "HY Spread"})
+difference4 = difference1.rename(columns = {('HY'): "HY Spread"})
difference4['HY vs mark'] = difference4['spread'] - difference4['HY Spread']
difference4.index = difference4.index.rename('monthend_date')
difference4 = difference4.set_index('source', append = True)