aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics')
-rw-r--r--python/analytics/option.py76
1 files changed, 27 insertions, 49 deletions
diff --git a/python/analytics/option.py b/python/analytics/option.py
index 949ea224..7e4e40ec 100644
--- a/python/analytics/option.py
+++ b/python/analytics/option.py
@@ -527,7 +527,7 @@ def _compute_vol(option, strike, mid):
else:
return np.array([option.sigma, option.moneyness])
-def _calibrate(index, quotes, option_model, option_type):
+def _calibrate_model(index, quotes, option_type, option_model):
T, r = [], []
column = 'pay_mid' if option_type == 'payer' else 'rec_mid'
with Pool(4) as p:
@@ -545,6 +545,12 @@ def _calibrate(index, quotes, option_model, option_type):
moneyness = r[non_nan,1]
return SmoothBivariateSpline(time, moneyness, vol)
+def _calibrate(index, quotes, option_type, *, kwargs):
+ if 'option_model' in kwargs:
+ return _calibrate_model(index, quotes, option_type, **kwargs)
+ elif 'beta' in kwargs:
+ return _calibrate_sabr(index, quotes, option_type, **kwargs)
+
class ModelBasedVolSurface(VolSurface):
def __init__(self, index_type, series, tenor='5yr', trade_date=datetime.date.today()):
super().__init__(index_type, series, tenor, trade_date)
@@ -554,9 +560,11 @@ class ModelBasedVolSurface(VolSurface):
pay_mid=self._quotes[['pay_bid', 'pay_offer']].mean(1) * 1e-4,
rec_mid=self._quotes[['rec_bid', 'rec_offer']].mean(1) * 1e-4)
if type(self) is BlackSwaptionVolSurface:
- self._option_model = BlackSwaption
- elif type(self) == SwaptionVolSurface:
- self._option_model = Swaption
+ self._opts = {'option_model': BlackSwaption}
+ elif type(self) is SwaptionVolSurface:
+ self._opts = {'option_model': Swaption}
+ elif type(self) is SABRVolSurface:
+ self._opts = {'beta': 3.19 if index_type == "HY" else 1.84}
def list(self, source=None, option_type=None):
"""returns list of vol surfaces"""
@@ -578,7 +586,7 @@ class ModelBasedVolSurface(VolSurface):
self._index.ref = quotes.ref.iat[0]
self._surfaces[surface_id] = _calibrate(self._index, quotes,
self._option_model,
- option_type)
+ **self._opts)
return self._surfaces[surface_id]
else:
return self._surfaces[surface_id]
@@ -602,6 +610,9 @@ class BlackSwaptionVolSurface(ModelBasedVolSurface):
class SwaptionVolSurface(ModelBasedVolSurface):
pass
+class SABRVolSurface(ModelBasedVolSurface):
+ pass
+
@lru_cache(maxsize=32)
def _forward_annuity(expiry, index):
step_in_date = expiry + datetime.timedelta(days=1)
@@ -701,47 +712,14 @@ def calib_sabr(x, option, strikes, pv, beta):
r[i] = option.pv - pv[i]
return r
-class SABRVolSurface(VolSurface):
- def __init__(self, index_type, series, tenor='5yr',
- trade_date=datetime.date.today(), beta=None):
- VolSurface.__init__(self, index_type, series, tenor='5yr',
- trade_date=datetime.date.today())
- if index_type == "HY":
- self.beta = 3.19
- elif index_type == "IG":
- self.beta = 1.84
-
- def list(self, source=None, option_type=None):
- """returns list of vol surfaces"""
- r = []
- for k in _get_keys(self._quotes, []):
- if (source is None or k[1] == source) and \
- (option_type is None or k[2] == option_type):
- r.append(k)
- return r
-
- def __getitem__(self, surface_id):
- if surface_id not in self._surfaces:
- quotedate, source, option_type = surface_id
- quotes = self._quotes[(self._quotes.quotedate == quotedate) &
- (self._quotes.quote_source == source)]
- self._index.ref = quotes.ref.iat[0]
-
- 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)
- quotes = quotes.dropna(subset=['mid'])
- for expiry, df in quotes.groupby(['expiry']):
- option = BlackSwaption(self._index, expiry.date(), 100, option_type)
- prog = least_squares(calib_sabr, (0.01, 0.3, 3.5),
- bounds=([0, -1, 0], [np.inf, 1, np.inf]),
- args=(option, df.strike.values, df.mid.values, self.beta))
- T.append(option.T)
- r.append(prog.x)
- print(prog)
- self._surfaces[surface_id] = (T, r)
- return self._surfaces[surface_id]
- else:
- return self._surfaces[surface_id]
+def _calibrate_sabr(index, quotes, option_type, beta):
+ T, r = [], []
+ column = 'pay_mid' if option_type == 'payer' else 'rec_mid'
+ for expiry, df in quotes.groupby(['expiry']):
+ option = BlackSwaption(self._index, expiry.date(), 100, option_type)
+ prog = least_squares(calib_sabr, (0.01, 0.3, 3.5),
+ bounds=([0, -1, 0], [np.inf, 1, np.inf]),
+ args=(option, df.strike.values, df[column].values, beta))
+ T.append(option.T)
+ r.append(prog.x)
+ return T, r