aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics/option.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics/option.py')
-rw-r--r--python/analytics/option.py73
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]