diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/option.py | 73 |
1 files changed, 72 insertions, 1 deletions
diff --git a/python/analytics/option.py b/python/analytics/option.py index fbd88d4d..e931d626 100644 --- a/python/analytics/option.py +++ b/python/analytics/option.py @@ -8,7 +8,7 @@ import pandas as pd from .black import black from .utils import GHquad -from .index import g, ForwardIndex +from .index import g, ForwardIndex, Index, engine from yieldcurve import roll_yc from pandas.tseries.offsets import BDay try: @@ -20,8 +20,12 @@ from pickle import dumps from functools import wraps from pyisda.curve import SpreadCurve from pyisda.flat_hazard import pv_vec +import numpy as np from scipy.optimize import brentq from scipy.integrate import simps +from scipy.interpolate import SmoothBivariateSpline +from matplotlib import cm +import matplotlib.pyplot as plt def calib(S0, fp, exercise_date, exercise_date_settle, index, rolled_curve, tilt, w): @@ -361,3 +365,70 @@ class Swaption(ForwardIndex): "" ] return "\n".join(s) + +def compute_vols(quote, option): + option.strike = quote.strike + option.ref = quote.ref + r = [] + for pv_type in ['pv', 'pv_black']: + for option_type in ['pay', 'rec']: + mid = (getattr(quote, '{}_bid'.format(option_type)) + + getattr(quote, '{}_offer'.format(option_type))) / 2 * 1e-4 + option.option_type = 'payer' if option_type == 'pay' else 'receiver' + + try: + setattr(option, pv_type, mid) + except ValueError as e: + r.append(None) + print(e) + else: + r.append(option.sigma) + return r + +class VolatilitySurface(ForwardIndex): + def __init__(self, index_type, series, tenor='5yr', trade_date=datetime.date.today()): + self._index = Index.from_name(index_type, series, tenor, trade_date, notional=1.) + self._quotes = pd.read_sql_query( + "SELECT swaption_quotes.*, ref FROM swaption_quotes " \ + "JOIN swaption_ref_quotes USING (quotedate, index, series, expiry)" \ + "WHERE quotedate::date = %s and index= %s and series = %s", + engine, + parse_dates = ['quotedate', 'expiry'], + params=(trade_date, index_type, series)) + self._quotes['quotedate'] = (self._quotes['quotedate']. + dt.tz_convert('America/New_York')) + self._surfaces = {} + for k, g in self._quotes.groupby(['quotedate', 'quote_source']): + quotedate, source = k + self._index.spread = g.ref.iat[0] + moneyness, T, r = [], [], [] + for expiry, df in g.groupby(['expiry']): + atm_strike = ATMstrike(self._index, expiry.date(), index_type == "HY") + option = Swaption(self._index, expiry.date(), 100, + strike_is_price=index_type == "HY") + for quote in df.itertuples(index=False): + r.append(compute_vols(quote, option)) + moneyness.append(quote.strike/atm_strike) + T.append(option.T) + r = np.array(r) + f = SmoothBivariateSpline(T, moneyness, r[:,0], bbox=[0, 1, 0.5, 2]) + self._surfaces[(quotedate, source)] = f + + def vol(self, T, moneyness, surface_id): + """computes the vol for a given moneyness and term.""" + return self._surfaces[surface_id](T, moneyness) + + def list(self): + """returns list of vol surfaces""" + return list(self._surfaces.keys()) + + def plot(self, surface_id): + fig = plt.figure() + ax = fig.gca(projection='3d') + xx, yy = np.meshgrid(np.arange(0, 1, 0.01), + np.arange(0.5, 2, 0.01)) + surf = ax.plot_surface(xx, yy, self._surfaces[surface_id].ev(xx, yy), + cmap = cm.viridis) + + def get(self, surface_id): + return self._surfaces[surface_id] |
