aboutsummaryrefslogtreecommitdiffstats
path: root/python/exploration/tranches.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/exploration/tranches.py')
-rw-r--r--python/exploration/tranches.py151
1 files changed, 54 insertions, 97 deletions
diff --git a/python/exploration/tranches.py b/python/exploration/tranches.py
index 028d41b1..7b475821 100644
--- a/python/exploration/tranches.py
+++ b/python/exploration/tranches.py
@@ -8,7 +8,7 @@ import numpy as np
import pandas as pd
from analytics import Swaption, BlackSwaption, Index, BlackSwaptionVolSurface, Portfolio
-from analytics.scenarios import run_swaption_scenarios, run_index_scenarios, run_portfolio_scenarios
+from analytics.scenarios import run_swaption_scenarios, run_index_scenarios, run_portfolio_scenarios, run_tranche_scenarios
import exploration.swaption_calendar_spread as spread
from scipy.interpolate import interp1d
@@ -59,10 +59,10 @@ def rv_calc1():
pv = tranche.tranche_pvs(shortened=4).bond_price
pv_prev_index.append(pv)
- temp1 = pd.DataFrame(rho_tlp, index=df.date, columns=['3_rho_tlp','7_rho_tlp','15_rho_tlp'])
- temp2 = pd.DataFrame(pv_tlp, index=df.date, columns=['03_pv_tlp','37_pv_tlp','715_pv_tlp','15100_pv_tlp'])
- temp3 = pd.DataFrame(rho_prev_index, index=df.date, columns=['3_rho_ig27','7_rho_ig27','15_rho_ig27'])
- temp4 = pd.DataFrame(pv_prev_index, index=df.date, columns=['03_pv_ig27','37_pv_ig27','715_pv_ig27','15100_pv_ig27'])
+ temp1 = pd.DataFrame(rho_tlp, index=df.date, columns=['3_rho_tlp', '7_rho_tlp', '15_rho_tlp'])
+ temp2 = pd.DataFrame(pv_tlp, index=df.date, columns=['03_pv_tlp', '37_pv_tlp', '715_pv_tlp', '15100_pv_tlp'])
+ temp3 = pd.DataFrame(rho_prev_index, index=df.date, columns=['3_rho_ig27', '7_rho_ig27', '15_rho_ig27'])
+ temp4 = pd.DataFrame(pv_prev_index, index=df.date, columns=['03_pv_ig27', '37_pv_ig27', '715_pv_ig27', '15100_pv_ig27'])
results = results.append(pd.concat([temp1, temp2, temp3, temp4], axis=1))
@@ -96,113 +96,70 @@ def dispersion():
curve_df.groupby(['series', 'maturity']).mean()
curve_df.groupby(['series', 'maturity']).std()
-def scenarios(tranche, shock_range=None, roll_corr=False):
+def run_scen(portf, tranche, spread_shock):
- from copy import deepcopy
-
- tranche.build_skew()
- orig_tranche_cl, _, orig_tranche_pv = tranche.tranche_pvs()
+ #Start with swaptions
+ earliest_expiry = min(portf.swaptions, key=lambda x: x.exercise_date).exercise_date
+ date_range = pd.bdate_range(portf.indices[0].trade_date,
+ earliest_expiry - pd.offsets.BDay(), freq='5B')
+ vs = BlackSwaptionVolSurface(portf.indices[0].index_type,
+ portf.indices[0].series, trade_date=portf.indices[0].trade_date)
+ vol_surface = vs[vs.list(option_type='payer')[-1]]
+ df = run_portfolio_scenarios(portf, date_range, spread_shock, np.array([0]),
+ vol_surface, params=["pnl", "delta"])
- if shock_range is None:
- shock, step = 1, 10
- shock_range = (1 + np.linspace(-.3, shock, step)) * tranche.tranche_quotes.indexrefspread[0]
+ #now do the tranches
+ spread_range = (1+ spread_shock) * portf.indices[0].spread
+ results = run_tranche_scenarios(tranche, spread_range, date_range)
+ results.date = pd.to_datetime(results.date)
+ notional = 10000000
+ results['delta_tranche'] = -notional * (results['0-3_delta'] - 6* results['7-15_delta'])
+ results['pnl_tranche'] = notional * (results['0-3_pnl'] + results['0-3_carry'] -
+ 6* (results['7-15_pnl'] + results['7-15_carry']))
+ results.index.name = 'spread'
- #create empty lists
- shock_index_pv_calc = np.empty(len(shock_range))
- shock_tranche_pv = np.empty((len(shock_range), tranche.K.size - 1))
- shock_tranche_delta = np.empty((len(shock_range), tranche.K.size - 1))
- shock_tranche_cl = np.empty((len(shock_range), tranche.K.size - 1))
- shock_tranche_carry = np.empty((len(shock_range), tranche.K.size - 1))
- results = pd.DataFrame()
+ #combine
+ df = df.reset_index().merge(results.reset_index(), on=['date', 'spread'])
+ df['final_pnl'] = df.pnl_tranche + df.pnl
+ df['final_delta'] = df.delta_tranche + df.delta
- for shortened in [0,1,2]:
- temp_tranche = deepcopy(tranche)
- if shortened > 0:
- temp_tranche.cs = temp_tranche.cs[:-shortened]
- for i, shock in enumerate(shock_range):
- temp_tranche.tweak(shock)
- if roll_corr is True:
- temp_tranche.rho = tranche.map_skew(temp_tranche, 'TLP')
- shock_index_pv_calc[i] = temp_tranche._snacpv(shock * 1e-4, temp_tranche.coupon(temp_tranche.maturity), temp_tranche.recovery)
- shock_tranche_cl[i], _, shock_tranche_pv[i] = temp_tranche.tranche_pvs()
- shock_tranche_delta[i] = temp_tranche.tranche_deltas()['delta']
- shock_tranche_carry[i] = temp_tranche.tranche_quotes.running
- temp1 = pd.DataFrame(shock_tranche_pv, index=shock_range, columns=[s + "_pv" for s in tranche._row_names])
- temp2 = pd.DataFrame(shock_tranche_delta, index=shock_range, columns=[s + "_delta" for s in tranche._row_names])
- temp3 = pd.DataFrame(np.subtract(shock_tranche_pv, orig_tranche_pv), index=shock_range, columns=[s + "_pnl" for s in tranche._row_names])
- temp4 = pd.DataFrame(shock_index_pv_calc, index=shock_range, columns=['index_price_snacpv'])
- temp5 = pd.DataFrame(shock_tranche_carry, index=shock_range, columns=[s + "_carry" for s in tranche._row_names])
- #temp5 = pd.DataFrame(np.subtract(shock_tranche_cl, orig_tranche_cl), index=shock_range, columns=[s + "_coupon_pnl" for s in tranche._row_names])
- df = pd.concat([temp1, temp2, temp3, temp4, temp5], axis=1)
- if shortened > 0:
- df['days'] = ((tranche.cs.index[-1] - tranche.cs.index[-shortened-1])/ np.timedelta64(1, 'D')).astype(int)
- else:
- df['days'] = 0
- for column in [s + "_carry" for s in tranche._row_names]:
- df[column] *= df['days']/365
+ return df
- results = results.append(df)
+def set_port():
- return results
+ #Construct Portfolio
+ option_delta = Index.from_name('IG', 30, '5yr')
+ option_delta.spread = 59
-def run_scen(trade_date = pd.Timestamp.today().normalize()- pd.offsets.BDay()):
+ option1 = BlackSwaption(option_delta, date(2018, 6, 20), 80, option_type="payer")
+ option1.sigma = .621
+ option1.direction = 'Short'
- option_delta = Index.from_tradeid(910)
- option1 = BlackSwaption.from_tradeid(13, option_delta)
- option2 = BlackSwaption.from_tradeid(12, option_delta)
- portf = Portfolio([option1, option2, option_delta])
+ option1.notional = 150_000_000
+ option_delta.notional = 1
- #Start with swaptions
+ portf = Portfolio([option1, option_delta])
portf.reset_pv()
- portf.mark()
- earliest_date = min(portf.swaptions, key=lambda x: x.exercise_date).exercise_date
- #date_range = pd.bdate_range(portf.indices[0].trade_date, earliest_date - BDay(), freq = '3B')
- date_range = pd.date_range(trade_date, periods=4, freq = '5B')
- vol_shock = np.arange(-0.01, 0.01, 0.01)
- shock_min=-.3
- shock_max=.8
- spread_shock = np.arange(shock_min, shock_max, 0.05)
- index = portf.indices[0].name.split()[1]
- series = portf.indices[0].name.split()[3][1:]
- vs = BlackSwaptionVolaSurface(index, series, trade_date=trade_date)
- vol_surface = vs[vs.list(option_type='payer')[-1]]
-
- df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface,
- params=["pnl","delta"])
- df = df[df.vol_shock == 0]
- df['days'] = ((df.index - trade_date)/ np.timedelta64(1, 'D')).astype(int)
-
- #now do the tranches
+ trade_date = (pd.datetime.today() - pd.offsets.BDay(1)).normalize()
tranche = bkt.TrancheBasket('IG', 29, '5yr', trade_date=trade_date)
- shock_range = (1 + spread_shock) * portf.indices[0].spread
- results = scenarios(tranche, shock_range, date_range)
- results.set_index('days', append=True)
+ return portf, tranche
- notional = 10000000
- results['delta'] = -notional * (results['0-3_delta'] - 6* results['7-15_delta'])
- results['pnl'] = notional* (results['0-3_pnl'] + results['0-3_carry'] - 6* (results['7-15_pnl'] + results['7-15_carry']))
- results['date'] = tranche.trade_date + results.days * pd.offsets.Day()
- results.index.name = 'spread'
+def set_df():
- #now combine the results
- f = {}
- for i, g in results.groupby('spread'):
- f[i] = interp1d(g.days, g.pnl)
+ portf, tranche = set_port()
- df['total_pnl'] = df.apply(lambda df: f[df.spread](df.days), axis = 1)
- df.total_pnl = df.total_pnl.astype(float)
+ shock_min = -.3
+ shock_max = .8
+ spread_shock = np.arange(shock_min, shock_max, 0.05)
+ shock_range = (1+ spread_shock) * portf.indices[0].spread
- return results, df, shock_range
+ results = run_scen(portf, tranche, spread_shock)
+ results = results.set_index('date')
+ return results, shock_range
-def plot_pnl():
+def plot_scenarios():
- a, b, shock_range = run_scen()
- a.reset_index(inplace=True)
- a.set_index('date', inplace=True)
- #plot Tranche only PNL
- plot_time_color_map(a, shock_range, attr="pnl")
- #plot swaption only PNL
- plot_time_color_map(b, shock_range, attr="pnl")
- #plot Tranche and Swaption PNL
- plot_time_color_map(b, shock_range, attr="total_pnl")
+ df, shock_range = set_df()
+ plot_time_color_map(df, shock_range, attr="final_pnl")
+ plot_time_color_map(df, shock_range, attr="final_delta", color_map= 'rainbow', centered = False)