diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/scenarios.py | 7 | ||||
| -rw-r--r-- | python/exploration/swaption_calendar_spread.py | 270 |
2 files changed, 178 insertions, 99 deletions
diff --git a/python/analytics/scenarios.py b/python/analytics/scenarios.py index 334a27a1..1cc4fb7f 100644 --- a/python/analytics/scenarios.py +++ b/python/analytics/scenarios.py @@ -63,7 +63,7 @@ def MaybePool(nproc): yield Pool(nproc) if nproc > 0 else None def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, - vol_surface, params=["pnl"], nproc=-1): + vol_surface, params=["pnl"], nproc=-1, vol_time_roll=True): """computes the pnl of a portfolio for a range of scenarios Parameters @@ -80,13 +80,14 @@ def run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, """ portf = deepcopy(portf) spreads = np.hstack([index.spread * (1 + spread_shock) for index in portf.indices]) - + t = [swaption.T for swaption in portf.swaptions] r = [] with MaybePool(nproc) as pool: pmap = pool.map if pool else map for date in date_range: portf.trade_date = date.date() - t = [swaption.T for swaption in portf.swaptions] + if vol_time_roll: + t = [swaption.T for swaption in portf.swaptions] for s in spreads: portf.ref = s mon = [swaption.moneyness for swaption in portf.swaptions] diff --git a/python/exploration/swaption_calendar_spread.py b/python/exploration/swaption_calendar_spread.py index 8eaaad0a..cc548874 100644 --- a/python/exploration/swaption_calendar_spread.py +++ b/python/exploration/swaption_calendar_spread.py @@ -1,8 +1,8 @@ import sys #don't do this at home sys.path.append("..") -from analytics import Swaption, BlackSwaption, Index, VolatilitySurface -from analytics.scenarios import run_swaption_scenarios, run_index_scenarios +from analytics import Swaption, BlackSwaption, Index, VolatilitySurface, Portfolio +from analytics.scenarios import run_swaption_scenarios, run_index_scenarios, run_portfolio_scenarios from pandas.tseries.offsets import BDay import datetime import numpy as np @@ -18,6 +18,10 @@ import matplotlib import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import AxesGrid +import re +from db import dbengine +engine = dbengine('serenitasdb') + def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'): ''' Function to offset the "center" of a colormap. Useful for @@ -69,7 +73,7 @@ def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shiftedcmap'): return newcmap -def plot_df(df, spread_shock, vol_shock, attr="pv"): +def plot_df(df, spread_shock, vol_shock, attr="pnl"): val_date = df.index[0].date() fig = plt.figure() @@ -84,7 +88,7 @@ def plot_df(df, spread_shock, vol_shock, attr="pv"): ax.set_zlabel("PnL") ax.set_title('{} of Trade on {}'.format(attr.title(), val_date)) -def plot_color_map(df, spread_shock, vol_shock, attr="pv", path="."): +def plot_color_map(df, spread_shock, vol_shock, attr="pnl", path="."): val_date = df.index[0].date() #rows are spread, columns are volatility surface shift @@ -107,9 +111,9 @@ 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, "vol_spread_color_map"+ attr+ "_{}.png".format(val_date))) -def plot_time_color_map(df, spread_shock, attr="pv", path=".", color_map = cm.RdYlGn): +def plot_time_color_map(df, spread_shock, attr="pnl", path=".", color_map = cm.RdYlGn): val_date = df.index[0].date() df = df.reset_index() @@ -132,120 +136,194 @@ def plot_time_color_map(df, spread_shock, attr="pv", path=".", color_map = cm.Rd ax.set_title('{} of Trade'.format(attr.title())) fig.colorbar(chart, shrink=.8) - #fig.savefig(os.path.join(path, "payer_swap_", attr, "_{}.png".format(val_date))) + #fig.savefig(os.path.join(path, "spread_time_color_map_"+ attr+ "_{}.png".format(val_date))) + +def dec_jan_2017_trade(): + option_delta = Index.from_tradeid(864) + option1 = BlackSwaption.from_tradeid(3, option_delta) + option2 = BlackSwaption.from_tradeid(4, option_delta) + + portf = Portfolio([option1, option2, option_delta]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-01-18') - BDay(), freq = '2B') + 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_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] + + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') + 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.5) - payer1.sigma = .348 - payer2.sigma = .466 - payer1.notional = 100_000_000 - payer2.notional = 100_000_000 + option1 = BlackSwaption.from_tradeid(5, option_delta) + option2 = BlackSwaption.from_tradeid(6, option_delta) - cost = 5000 + portf = Portfolio([option1, option2, option_delta]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-04-19') - BDay(), freq = '2B') + 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_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] + + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') + + +def april_may_2017_trade(): + option_delta = Index.from_tradeid(870) + option1 = BlackSwaption.from_tradeid(5, option_delta) + option2 = BlackSwaption.from_tradeid(6, option_delta) - date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-04-19') - BDay(), freq = '5B') + portf = Portfolio([option1, option2, option_delta]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-04-19') - BDay(), freq = '2B') 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, ['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) + 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] + + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') - # #plot it - week = -1 - df = df1.reset_index() - 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-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 may_june_2017_trade(): + option_delta = Index.from_tradeid(874) + option1 = BlackSwaption.from_tradeid(7, option_delta) + option2 = BlackSwaption.from_tradeid(8, option_delta) + portf = Portfolio([option1, option2, option_delta]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-17') - BDay(), freq = '2B') + 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] + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) -option_delta = Index.from_name('ig', 28, '5yr') -option_delta.spread = 68 + #plot it + period = -4 + #plot_df(df.loc[date_range[period]], spread_plot_range, vol_shock_range) + #plot_color_map(df.loc[date_range[period]], option_delta.spread * (1 + spread_shock), vol_shock, 'pnl') + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') + #plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta', color_map = cm.coolwarm_r) -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 +def portfolio_scenario_2(): -ref = option_delta.spread + #Manually Load trades + option_delta = Index.from_name('ig', 28, '5yr') + option_delta.spread = 67 + option1 = BlackSwaption(option_delta, datetime.date(2017, 6, 21), 65, option_type="receiver") + option2 = BlackSwaption(option_delta, datetime.date(2017, 5, 17), 65, option_type="receiver") + option1.sigma = .39 + option2.sigma = .424 + option1.notional = 100_000_000 + option2.notional = -100_000_000 + option_delta.notional = -(option1.delta * option1.notional + option2.delta*option2.notional) + if option_delta.notional < 0: + option_delta.direction = 'Seller' + option_delta.notional = abs(option_delta.notional) + #setting original pvs for pnl calc + option1._original_pv = option1.pv + option2._original_pv = option2.pv + option_delta._original_clean_pv = option_delta._clean_pv + option_delta._original_trade_date = option_delta._trade_date -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 + portf = Portfolio([option1, option2, option_delta]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-17') - BDay(), freq = '2B') + 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] -#option_delta.notional = -100_000_000 -if option_delta.notional > 0: option_delta.direction = 'Seller' + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) -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 + payer3.pv + #plot it + period = -4 + #plot_df(df.loc[date_range[period]], spread_plot_range, vol_shock_range) + #plot_color_map(df.loc[date_range[period]], option_delta.spread * (1 + spread_shock), vol_shock, 'pnl') + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') + #Delta in protection terms: Blue = going short, red = going long + plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta', color_map = cm.coolwarm_r) -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] -# # +def portfolio(): + option_delta = Index.from_tradeid(874) + option1 = BlackSwaption.from_tradeid(7, option_delta) + option2 = BlackSwaption.from_tradeid(8, option_delta) -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) + portf = Portfolio([option1, option2, option3, option_delta, option_delta1, option_delta2, option_delta3]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-17') - BDay(), freq = '2B') + 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] + + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) + + #plot it + period = -4 + #plot_df(df.loc[date_range[period]], spread_plot_range, vol_shock_range) + plot_color_map(df.loc[date_range[period]], option_delta.spread * (1 + spread_shock), vol_shock, 'pnl') + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') + plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta', color_map = cm.coolwarm_r) + +def portfolio_today(): + option_deltas = {} + options = {} + for trade_id in [870,872,873]: + option_deltas[trade_id] = Index.from_tradeid(trade_id) + option_deltas[trade_id].trade_date = datetime.date.today() + index_type = re.search('CDX (\w+) ', option_deltas[trade_id].name).group(1) + series = re.search('\d+', option_deltas[trade_id].name).group(0) + spread = pd.read_sql_query( + "SELECT closespread FROM index_quotes " \ + "WHERE date <= %s and index= %s and series = %s and tenor = '5yr'" \ + "ORDER BY date DESC limit 1", + engine, + params=(option_deltas[trade_id].trade_date, index_type, series)) + option_deltas[trade_id].spread = spread.iloc[0][0] + option_deltas[trade_id].set_original_pv() + + for trade_id in [6]: + options[trade_id] = BlackSwaption.from_tradeid(trade_id, option_deltas[870]) + #options[trade_id].trade_date = datetime.date.today() + options[trade_id].sigma = .5 + options[trade_id].set_original_pv() + #index_type = re.search('CDX (\w+) ', options[trade_id].index.name).group(1) + #series = re.search('\d+', options[trade_id].index.name).group(0) + #import pdb; pdb.set_trace() + + portf = Portfolio([*option_deltas, *options]) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-17') - BDay(), freq = '2B') + 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] -dfdelta = run_index_scenarios(option_delta, date_range, spread_shock) + df = run_portfolio_scenarios(portf, date_range, spread_shock, vol_shock, vol_surface, params=["pnl", "delta"], vol_time_roll=False) -# #plot it -week = -4 -df = df1.reset_index() -dfdelta = dfdelta.reset_index() -df = df.merge(dfdelta, on=['date','spread_shock']) -df = df.set_index('date') + #plot it + plot_time_color_map(df[round(df.vol_shock,2)==0], option_delta.spread * (1 + spread_shock), 'pnl') -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) +def probabilities(): + from scipy.stats import lognorm -spread_plot_range = ref * (1 + np.arange(-0.2, 0.3, 0.001)) -vol_shock_range = np.arange(-0.15, 0.3, 0.001) + option_delta = Index.from_tradeid(874) + 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] + t = .1 + mon = 1 -#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), 'pv') -plot_time_color_map(df[round(df.vol_shock,2)==0], ref * (1 + spread_shock), 'delta', color_map = cm.coolwarm) + date_range = pd.bdate_range(option_delta.trade_date, pd.Timestamp('2017-05-17') - BDay(), freq = 'B') -#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') + curr_vols = np.maximum(vol_surface.ev(t, mon), 0) + dist = lognorm(curr_vols, scale) + lognorm.ppf(.5, curr_vols, scale = np.exp(64)) |
