aboutsummaryrefslogtreecommitdiffstats
path: root/python/exploration/swaption_calendar_spread.py
blob: e21ffd66899cac504fc603fdaa285098320fda5c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
import sys
#don't do this at home
sys.path.append("..")
from analytics import (Swaption, BlackSwaption, BlackSwaptionVolSurface,
                       Index, ProbSurface, 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
import pandas as pd
from scipy.interpolate import SmoothBivariateSpline

import os
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from graphics import plot_time_color_map, plot_color_map

from db import dbengine
engine  = dbengine('serenitasdb')

def plot_df(df, spread_shock, vol_shock, attr="pnl"):
    val_date = df.index[0].date()
    fig = plt.figure()

    ax = fig.gca(projection='3d')
    ## use smoothing spline on a finer grid
    series = df[attr]
    f = SmoothBivariateSpline(df.vol_shock.values, df.spread_shock.values, series.values)
    xx, yy = np.meshgrid(vol_shock, spread_shock)
    surf = ax.plot_surface(xx, yy, f(vol_shock, spread_shock).T, cmap=cm.viridis)
    ax.set_xlabel("Volatility shock")
    ax.set_ylabel("Spread")
    ax.set_zlabel("PnL")
    ax.set_title('{} of Trade on {}'.format(attr.title(), val_date))

def plot_trade_scenarios(portf, shock_min=-.15, shock_max=.2, period=-1, vol_time_roll=True):
    portf.reset_pv()
    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')
    vol_shock = np.arange(-0.15, 0.3, 0.01)
    spread_shock = np.arange(shock_min, shock_max, 0.01)
    index = portf.indices[0].name.split()[1]
    series = portf.indices[0].name.split()[3][1:]
    vs = BlackSwaptionVolSurface(index, 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, vol_shock, vol_surface,
                                 params=["pnl","delta"])

    hy_plot_range = 100 + (500 - portf.indices[0].spread * (1 + spread_shock)) * \
                    abs(portf.indices[0].DV01) / portf.indices[0].notional * 100

    shock =  hy_plot_range if index == 'HY' else portf.indices[0].spread * (1 + spread_shock)

    plot_time_color_map(df[round(df.vol_shock,2)==0], shock, 'pnl', index=index)
    plot_time_color_map(df[round(df.vol_shock,2)==.2], shock, 'pnl', index=index)
    plot_color_map(df.loc[date_range[period]], shock, vol_shock, 'pnl', index=index)
    return df

def exercise_probability():
    engine  = dbengine('serenitasdb')
    #Ad hoc
    option_delta = Index.from_name('HY', 29, '5yr')
    option_delta.price = 107.875
    option1 = BlackSwaption(option_delta, datetime.date(2017, 12, 20), 107, option_type="payer")
    option2 = BlackSwaption(option_delta, datetime.date(2017, 12, 20), 105, option_type="payer")
    option1.sigma = .280
    option2.sigma = .371
    option1.notional = 20_000_000
    option2.notional = 40_000_000
    option1.direction = 'Long'
    option2.direction = 'Short'
    option_delta.notional = option1.notional * option1.delta + option2.notional * option2.delta
    option_delta.direction = 'Seller' if option_delta.notional > 0 else 'Buyer'
    option_delta.notional = abs(option_delta.notional)
    portf = Portfolio([option1, option2, option_delta])

    portf.reset_pv()
    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='5B')
    vol_shock = np.arange(-0.15, 0.3, 0.01)
    spread_shock = np.arange(-0.15, 0.35, 0.01)
    index = portf.indices[0].name.split()[1]
    series = portf.indices[0].name.split()[3][1:]

    vs = ProbSurface(index, series, trade_date=portf.indices[0].trade_date)
    vs.plot(vs.list()[-1])