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.py94
1 files changed, 57 insertions, 37 deletions
diff --git a/python/analytics/option.py b/python/analytics/option.py
index 4fcc5023..e2177d6d 100644
--- a/python/analytics/option.py
+++ b/python/analytics/option.py
@@ -25,7 +25,10 @@ from scipy.optimize import brentq
from scipy.integrate import simps
from scipy.interpolate import SmoothBivariateSpline
from matplotlib import cm
+from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
+from joblib import Parallel, delayed
+from itertools import chain
def calib(S0, fp, exercise_date, exercise_date_settle,
index, rolled_curve, tilt, w):
@@ -364,24 +367,14 @@ 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
+def compute_vol(option, strike, mid, pv_type):
+ option.strike = strike
+ try:
+ setattr(option, pv_type, mid)
+ except ValueError as e:
+ return None
+ else:
+ return option.sigma
class VolatilitySurface(ForwardIndex):
def __init__(self, index_type, series, tenor='5yr', trade_date=datetime.date.today()):
@@ -394,23 +387,14 @@ class VolatilitySurface(ForwardIndex):
parse_dates = ['quotedate', 'expiry'],
params=(trade_date, index_type, series))
self._quotes['quotedate'] = (self._quotes['quotedate'].
- dt.tz_convert('America/New_York'))
+ dt.tz_convert('America/New_York').
+ dt.tz_localize(None))
+ self._quotes = self._quotes.sort_values('quotedate')
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
+ for surface_type in ["payer", "receiver", "payer_black", "receiver_black"]:
+ self._surfaces[(quotedate, source, surface_type)] = None
def vol(self, T, moneyness, surface_id):
"""computes the vol for a given moneyness and term."""
@@ -420,13 +404,49 @@ class VolatilitySurface(ForwardIndex):
"""returns list of vol surfaces"""
return list(self._surfaces.keys())
+ def __iter__(self):
+ return self._surfaces.items()
+
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),
+ xx, yy = np.meshgrid(np.arange(0.1, 0.5, 0.01),
+ np.arange(0.8, 1.7, 0.01))
+ surf = ax.plot_surface(xx, yy, self[surface_id].ev(xx, yy),
cmap = cm.viridis)
+ ax.set_xlabel("Year fraction")
+ ax.set_ylabel("Moneyness")
+ ax.set_zlabel("Volatility")
- def get(self, surface_id):
- return self._surfaces[surface_id]
+ def __getitem__(self, surface_id):
+ if self._surfaces[surface_id] is None:
+ quotedate, source, surface_type = surface_id
+ quotes = self._quotes[(self._quotes.quotedate == quotedate) &
+ (self._quotes.quote_source == source)]
+
+ self._index.ref = quotes.ref.iat[0]
+ if "_" in surface_type:
+ option_type, _ = surface_type.split("_")
+ pv_type = "pv_black"
+ else:
+ option_type = surface_type
+ pv_type = "pv"
+ moneyness, T, r = [], [], []
+ if option_type == "payer":
+ quotes = quotes.assign(mid = quotes[['pay_bid','pay_offer']].mean(1) * 1e-4)
+ else:
+ quotes = quotes.assign(mid = quotes[['rec_bid','rec_offer']].mean(1) * 1e-4)
+ for expiry, df in quotes.groupby(['expiry']):
+ atm_strike = ATMstrike(self._index, expiry.date())
+ option = Swaption(self._index, expiry.date(), 100, option_type)
+ T.append(option.T * np.ones(df.shape[0]))
+ moneyness.append(df.strike.values / atm_strike)
+ r.append(Parallel(n_jobs=4)(
+ delayed(compute_vol)(option, strike, mid, pv_type) for strike, mid in
+ df[['strike', 'mid']].values))
+ r = np.fromiter(chain(*r), np.float, quotes.shape[0])
+ f = SmoothBivariateSpline(np.hstack(T), np.hstack(moneyness), r)
+ self._surfaces[surface_id] = f
+ return f
+ else:
+ return self._surfaces[surface_id]