aboutsummaryrefslogtreecommitdiffstats
path: root/python/option_trades_et.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/option_trades_et.py')
-rw-r--r--python/option_trades_et.py95
1 files changed, 64 insertions, 31 deletions
diff --git a/python/option_trades_et.py b/python/option_trades_et.py
index 9f27e4b3..8b64e7b7 100644
--- a/python/option_trades_et.py
+++ b/python/option_trades_et.py
@@ -59,27 +59,21 @@ def beta_calc():
ltvar = lr_var(resHY)
graphit = compute_allocation(all_tenors)
-def build_swaption(index = 'IG', series = 27, expiry = datetime.date(2017, 4, 19), strike = 65, ref = 62, trade_date = datetime.date(2017, 2, 23), t_range = None):
+def build_swaption(index, series, expiry, strike, ref, trade_date, t_range= None, spread_range = None):
index_obj = Index.from_name(index, series, '5yr', trade_date)
swap_obj = opt.Swaption(index_obj, expiry, strike, option_type="payer")
swap_obj.notional = 100000000
if t_range is None:
t_range = pd.bdate_range(trade_date, expiry- BDay(), freq = '5B')
+ if spread_range is None:
+ spread_range = pd.Series(np.arange(ref - 10, ref +19, 5))
+
vol_range = pd.Series(np.arange(25, 60, 5)) #not inclusive of end point
- spread_range = pd.Series(np.arange(ref - 10, ref +19, 5))
df = pd.DataFrame(index = pd.MultiIndex.from_product([t_range, spread_range, vol_range], names = ['date', 'spread', 'vol']), columns = ['pv'])
df = df.reset_index()
- def manual_index_update(index, date):
- index._yc = index._yc.expected_forward_curve(date)
- index._trade_date = date
- index._step_in_date = index.trade_date + datetime.timedelta(days=1)
- index._accrued = index._fee_leg.accrued(index._step_in_date)
- index._value_date = (pd.Timestamp(index._trade_date) + 3* BDay()).date()
- index._update()
-
def aux(row, index, swap):
index.spread = row.spread
manual_index_update(index, row.date.date())
@@ -91,7 +85,7 @@ def build_swaption(index = 'IG', series = 27, expiry = datetime.date(2017, 4, 19
#calculate mapped vol
df['moneyness'] = (strike- df.spread)/df.spread
- df['days_to_expiry'] = (expiry - df.date) / np.timedelta64(1,'D')
+ df['days_to_expiry'] = (expiry - df.date).dt.days
vol_surface = build_vol_surface_functions(trade_date, index, series)
df['mapped_vol'] = df.apply(vol_from_surface, axis = 1, args=(vol_surface[0], vol_surface[1]))
df['mapping_shift'] = pd.to_numeric(df.vol/100 - df.mapped_vol, errors = 'ignore')
@@ -99,12 +93,37 @@ def build_swaption(index = 'IG', series = 27, expiry = datetime.date(2017, 4, 19
return df
+def calc_delta_pnl(index, series, ref, trade_date, notional, t_range, spread_range):
+
+ index_obj = Index.from_name(index, series, '5yr', trade_date)
+ index_obj.spread = ref
+ index_obj.notional = notional
+ startingpv = -index_obj.clean_pv
+
+ index_pv = {}
+ for date in t_range:
+ for spread in spread_range:
+ index_obj.spread = spread
+ manual_index_update(index_obj, date)
+ #import pdb; pdb.set_trace()
+ index_pv[(date, spread)] = -index_obj.clean_pv + notional* (date.date()-trade_date).days/360* index_obj.fixed_rate/10000
+
+ df = pd.DataFrame.from_dict(index_pv, orient = 'index').reset_index()
+ df['date'] = df['index'].apply(lambda x: x[0])
+ df['spread'] = df['index'].apply(lambda x: x[1])
+ del df['index']
+ df = df.set_index(['date','spread']).sort_index()
+ df = (df - startingpv).unstack(-1)
+ df.columns = df.columns.droplevel()
+
+ return df
+
def find_mapped_pv(bought, sold, date):
sold = sold.xs(date).reset_index()
bought = bought.xs(date).reset_index()
- #Bivariate B-Spline, instead of interp2d. Interp2d doesn't behave well....
+ #Bivariate B-Spline, instead of interp2d. Interp2d doesn't behave well and complains a lot. annoying
x = bought.spread.unique()
y = sorted(bought.mapping_shift.unique())
grid = np.meshgrid(x,y)
@@ -112,7 +131,6 @@ def find_mapped_pv(bought, sold, date):
f_sold = SmoothBivariateSpline(sold.spread, sold.mapping_shift, sold.pv, kx = 4, ky = 4)
intp_buy = f_buy.ev(grid[0],grid[1])
intp_sold = f_sold.ev(grid[0],grid[1])
- #import pdb; pdb.set_trace()
df = pd.DataFrame(intp_buy, index = grid[1][0:,0], columns = grid[0][0])
df1 = pd.DataFrame(intp_sold, index = grid[1][0:,0], columns = grid[0][0])
@@ -151,8 +169,6 @@ def plot_color_map(df, val_date):
#rows are spread, columns are volatility surface shift
fig, ax = plt.subplots()
- #import pdb; pdb.set_trace()
-
#Different ways to do a colormap: imshow and pcolormesh. using imshow here
midpoint = 1 - df.max().max()/(df.max().max() + abs(df.min().min()))
shifted_cmap = shiftedColorMap(cm.RdYlGn, midpoint=midpoint, name='shifted')
@@ -166,8 +182,6 @@ def plot_color_map(df, val_date):
fig.colorbar(chart, shrink = .8)
- #import pdb; pdb.set_trace()
-
fig.savefig("/home/serenitas/edwin/PythonGraphs/payer_swap_" + str(val_date.date()) + ".png")
def build_vol_surface_functions(date = datetime.date(2017, 2, 23), index = 'IG', series = '27'):
@@ -187,7 +201,7 @@ def build_vol_surface_functions(date = datetime.date(2017, 2, 23), index = 'IG',
df1 = df1.groupby(df1.index).filter(lambda x: len(x) >= 2)
df1 = df1.reset_index()
#once the dates are in the columns you need the use .dt to access dates functions
- df1['days_to_expiry'] = (df1.expiry - df1.quotedate.dt.normalize().dt.tz_localize(None)) / np.timedelta64(1,'D')
+ df1['days_to_expiry'] = (df1.expiry - df1.quotedate.dt.normalize().dt.tz_localize(None)).dt.days
df1['moneyness'] = (df1.strike - df1.ref)/df1.ref
df1 = df1.groupby(['days_to_expiry','moneyness']).nth(-1).vol
df1 = df1.reset_index()
@@ -201,6 +215,21 @@ def vol_from_surface(row, f, g):
vol = g(row.days_to_expiry, row.moneyness)
return vol
+def calc_and_plot(bought, sold, traded_price, week, lowerbound, upperbound, deltaPNL=None):
+
+ if week > len(bought.index.get_level_values(0).unique()):
+ week = len(bought.index.get_level_values(0).unique())-1
+
+ date = bought.index.get_level_values(0).unique()[week]
+
+ PNL = find_mapped_pv(bought, sold, date) - traded_price + deltaPNL.loc[date.date()]
+
+ PNL = PNL[lowerbound:upperbound].sort_index(ascending = False)
+
+ plot_color_map(PNL, date)
+
+ return PNL
+
def full_analysis():
index = 'IG'
series = 27,
@@ -210,37 +239,41 @@ def full_analysis():
sell_strike = 72
ref = 62
trade_date = datetime.date(2017, 2, 23)
+ delta_notional = 13000000
t_range = pd.bdate_range(trade_date, buy_expiry- BDay(), freq = '5B')
+ spread_range = pd.Series(np.arange(ref - 10, ref +19, 5))
- bought = build_swaption(index, series, buy_expiry, buy_strike, ref, trade_date, t_range)
- sold = build_swaption(index, series, sell_expiry, sell_strike, ref, trade_date, t_range)
+ bought = build_swaption(index, series, buy_expiry, buy_strike, ref, trade_date, t_range, spread_range)
+ sold = build_swaption(index, series, sell_expiry, sell_strike, ref, trade_date, t_range, spread_range)
+
+ delta_PNL = calc_delta_pnl(index, series, ref, trade_date, delta_notional, t_range, spread_range)
#Calc PNL and Plot:
traded_price = 5000
lowerbound = -.05 #parallel shift down 5% vol
upperbound = .1 #parallel shift up 10% vol
- week = -3 #negative to count backwards
+ week = 1 #negative to count backwards
- PNL = calc_and_plot(bought, sold, traded_price, week, lowerbound, upperbound)
+ PNL = calc_and_plot(bought, sold, traded_price, week, lowerbound, upperbound, delta_PNL)
+
+ return (bought, sold, PNL, delta_PNL)
- return (bought, sold, PNL)
-def calc_and_plot(bought, sold, traded_price, week, lowerbound, upperbound):
- if week > len(bought.index.get_level_values(0).unique()):
- week = len(bought.index.get_level_values(0).unique())-1
- date = bought.index.get_level_values(0).unique()[week]
- PNL = find_mapped_pv(bought, sold, date) - traded_price
- PNL = PNL[lowerbound:upperbound].sort_index(ascending = False)
- plot_color_map(PNL, date)
- return PNL
+def manual_index_update(index, date): #index as Index Object
+ index._yc = index._yc.expected_forward_curve(date)
+ index._trade_date = date
+ index._step_in_date = index.trade_date + datetime.timedelta(days=1)
+ index._accrued = index._fee_leg.accrued(index._step_in_date)
+ index._value_date = (pd.Timestamp(index._trade_date) + 3* BDay()).date()
+ index._update()
import numpy as np