diff options
| -rw-r--r-- | python/analytics/scenarios.py | 5 | ||||
| -rw-r--r-- | python/exploration/swaption_calendar_spread.py | 111 |
2 files changed, 79 insertions, 37 deletions
diff --git a/python/analytics/scenarios.py b/python/analytics/scenarios.py index 0c132076..ab0cdde3 100644 --- a/python/analytics/scenarios.py +++ b/python/analytics/scenarios.py @@ -9,7 +9,7 @@ from functools import partial from multiprocessing import Pool def run_swaption_scenarios(swaption, date_range, spread_shock, vol_shock, - vol_surface, params=["pv"]): + vol_surface, params=["pv"], vol_time_roll=True): """computes the pv of a swaption for a range of scenarios Parameters @@ -24,11 +24,12 @@ def run_swaption_scenarios(swaption, date_range, spread_shock, vol_shock, """ swaption = deepcopy(swaption) spreads = swaption.ref * (1 + spread_shock) + T = swaption.T r = [] for date in date_range: swaption.index.trade_date = date.date() - T = swaption.T + if vol_time_roll: T = swaption.T for s in spreads: swaption.ref = s curr_vol = max(0, float(vol_surface(T, swaption.moneyness))) diff --git a/python/exploration/swaption_calendar_spread.py b/python/exploration/swaption_calendar_spread.py index f399a931..8eaaad0a 100644 --- a/python/exploration/swaption_calendar_spread.py +++ b/python/exploration/swaption_calendar_spread.py @@ -89,8 +89,11 @@ def plot_color_map(df, spread_shock, vol_shock, attr="pv", path="."): val_date = df.index[0].date() #rows are spread, columns are volatility surface shift fig, ax = plt.subplots() + #We are plotting an image, so we have to sort from high to low on the Y axis + df.sort_values(by=['spread_shock','vol_shock'], ascending = [True,False], inplace = True) series = df[attr] - #Different ways to do a colormap: imshow and pcolormesh. using imshow here + + #import pdb; pdb.set_trace() midpoint = 1 - series.max() / (series.max() + abs(series.min())) shifted_cmap = shiftedColorMap(cm.RdYlGn, midpoint=midpoint, name='shifted') @@ -104,22 +107,20 @@ def plot_color_map(df, spread_shock, vol_shock, attr="pv", path="."): ax.set_title('{} of Trade on {}'.format(attr.title(), val_date)) fig.colorbar(chart, shrink=.8) - #fig.savefig(os.path.join(path, "payer_swap_", attr, "_{}.png".format(val_date))) + fig.savefig(os.path.join(path, "payer_swap_", attr, "_{}.png".format(val_date))) -def plot_time_color_map(df, spread_shock, attr="pv", path="."): +def plot_time_color_map(df, spread_shock, attr="pv", path=".", color_map = cm.RdYlGn): val_date = df.index[0].date() - dftemp = df.reset_index() - dftemp['days'] = (dftemp['date'] - val_date).dt.days - date_range = dftemp.days.unique() + df = df.reset_index() + df['days'] = (df['date'] - val_date).dt.days + df.sort_values(by=['date','spread_shock'], ascending = [True,False], inplace = True) + date_range = df.days.unique() - #rows are spread, columns are volatility surface shift fig, ax = plt.subplots() series = df[attr] - #Different ways to do a colormap: imshow and pcolormesh. using imshow here midpoint = 1 - series.max() / (series.max() + abs(series.min())) - #import pdb; pdb.set_trace() - shifted_cmap = shiftedColorMap(cm.RdYlGn, midpoint=midpoint, name='shifted') + shifted_cmap = shiftedColorMap(color_map, midpoint=midpoint, name='shifted') chart = ax.imshow(series.values.reshape(date_range.size, spread_shock.size).T, extent=(date_range.min(), date_range.max(), @@ -137,17 +138,22 @@ def april_may_2017_trade(): option_delta = Index.from_tradeid(870) ref = option_delta.spread payer1 = BlackSwaption(option_delta, datetime.date(2017, 4, 19), 65) - payer2 = BlackSwaption(option_delta, datetime.date(2017, 5, 17), 72) + payer2 = BlackSwaption(option_delta, datetime.date(2017, 5, 17), 72.5) + payer1.sigma = .348 + payer2.sigma = .466 payer1.notional = 100_000_000 payer2.notional = 100_000_000 + + cost = 5000 + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-04-19') - BDay(), freq = '5B') vol_shock = np.arange(-0.15, 0.3, 0.01) spread_shock = np.arange(-0.2, 0.3, 0.01) vs = VolatilitySurface("IG", 27, trade_date=option_delta.trade_date) vol_surface = vs[vs.list()[-1]] # # - df1 = run_swaption_scenarios(payer1, date_range, spread_shock, vol_shock, vol_surface) - df2 = run_swaption_scenarios(payer2, date_range, spread_shock, vol_shock, vol_surface) + df1 = run_swaption_scenarios(payer1, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta']) + df2 = run_swaption_scenarios(payer2, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta']) df3 = run_index_scenarios(option_delta, date_range, spread_shock) # #plot it @@ -156,55 +162,90 @@ def april_may_2017_trade(): df3 = df3.reset_index() df = df.merge(df3, on=['date','spread_shock']) df = df.set_index('date') - df = df.assign(pv=df1.pv-df2.pv+df.pnl) + df = df.assign(pv=df1.pv-df2.pv+df.pnl-cost) + df = df.assign(delta=df1.delta*payer1.notional-df2.delta*payer2.notional+option_delta.notional) spread_plot_range = ref * (1 + np.arange(-0.2, 0.3, 0.001)) vol_shock_range = np.arange(-0.15, 0.3, 0.001) plot_df(df.loc[date_range[week]], spread_plot_range, vol_shock_range) plot_color_map(df.loc[date_range[week]], ref * (1 + spread_shock), vol_shock) + plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta') + plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'pv') + -#def june_july_2017_trade(): option_delta = Index.from_name('ig', 28, '5yr') -option_delta.spread = 67 -payer1 = BlackSwaption(option_delta, datetime.date(2017, 7, 19), 80) -payer2 = BlackSwaption(option_delta, datetime.date(2017, 5, 17), 80) -payer1.sigma = .438 -payer2.sigma = .479 -payer1.notional = 100_000_000 -payer2.notional = 100_000_000 +option_delta.spread = 68 + +payer1 = BlackSwaption(option_delta, datetime.date(2017, 6, 21), 65) +payer2 = BlackSwaption(option_delta, datetime.date(2017, 5, 17), 75) +payer3 = BlackSwaption(option_delta, datetime.date(2017, 7, 19), 75) +payer1.sigma = .388 +payer2.sigma = .503 +payer3.sigma = .43 +payer1.notional = 150_000_000 +payer2.notional = -100_000_000 +payer3.notional = 100_000_000 *0 +vol_time_roll = False +no_delta = False ref = option_delta.spread -option_delta.notional = payer1.notional * payer1.delta - payer2.notional * payer2.delta + +if payer2.notional == 0: + option_delta.notional = payer1.notional * payer1.delta +elif payer3.notional == 0: + option_delta.notional = payer1.notional * payer1.delta + payer2.notional * payer2.delta +else: + option_delta.notional = payer1.notional * payer1.delta + payer2.notional * payer2.delta + payer3.notional * payer3.delta + +#option_delta.notional = -100_000_000 if option_delta.notional > 0: option_delta.direction = 'Seller' + +if no_delta: option_delta.notional = 0.01 option_delta._original_clean_pv = option_delta._clean_pv option_delta._original_trade_date = option_delta.trade_date -cost = payer1.pv - payer2.pv +cost = payer1.pv + payer2.pv + payer3.pv -date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-17') - BDay(), freq = '3B') +date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-16') - BDay(), freq = '3B') vol_shock = np.arange(-0.15, 0.3, 0.01) spread_shock = np.arange(-0.2, 0.3, 0.01) vs = VolatilitySurface("IG", 28, trade_date=option_delta.trade_date) vol_select = max([t for t in vs.list() if t[1] == 'BAML' and t[2] == 'payer' and t[3] == 'black']) vol_surface = vs[vol_select] # # -df1 = run_swaption_scenarios(payer1, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta']) -df2 = run_swaption_scenarios(payer2, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta']) -df3 = run_index_scenarios(option_delta, date_range, spread_shock) + +df1 = run_swaption_scenarios(payer1, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta'], vol_time_roll) +if payer2.notional != 0: df2 = run_swaption_scenarios(payer2, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta'], vol_time_roll) +if payer3.notional != 0: df3 = run_swaption_scenarios(payer3, date_range, spread_shock, vol_shock, vol_surface, ['pv','delta'], vol_time_roll) + +dfdelta = run_index_scenarios(option_delta, date_range, spread_shock) # #plot it -week = -2 +week = -4 df = df1.reset_index() -df3 = df3.reset_index() -df = df.merge(df3, on=['date','spread_shock']) +dfdelta = dfdelta.reset_index() +df = df.merge(dfdelta, on=['date','spread_shock']) df = df.set_index('date') -df = df.assign(pv=df1.pv-df2.pv+df.pnl-cost) -df = df.assign(delta=df1.delta*payer1.notional-df2.delta*payer2.notional+option_delta.notional) + +if payer2.notional == 0: + df = df.assign(pv=df1.pv+df.pnl-cost) + df = df.assign(delta=df1.delta*payer1.notional+option_delta.notional) +elif payer3.notional == 0: + df = df.assign(pv=df1.pv+df2.pv+df.pnl-cost) + df = df.assign(delta=df1.delta*payer1.notional+df2.delta*payer2.notional+option_delta.notional) +else: + df = df.assign(pv=df1.pv+df2.pv+df3.pv+df.pnl-cost) + df = df.assign(delta=df1.delta*payer1.notional+df2.delta*payer2.notional+df3.delta*payer3.notional+option_delta.notional) spread_plot_range = ref * (1 + np.arange(-0.2, 0.3, 0.001)) vol_shock_range = np.arange(-0.15, 0.3, 0.001) #plot_df(df.loc[date_range[week]], spread_plot_range, vol_shock_range) -plot_color_map(df.loc[date_range[week]], ref * (1 + spread_shock), vol_shock) -plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta') +#plot_color_map(df.loc[date_range[week]], ref * (1 + spread_shock), vol_shock) plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'pv') +plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta', color_map = cm.coolwarm) + +#down 10% vol +#plot_time_color_map(df[round(df.vol_shock,2)==-.1], ref * (1 + spread_shock), 'pv') +#plot_time_color_map(df[round(df.vol_shock,2)==-.1], ref * (1 + spread_shock), 'delta') + |
