diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/option.py | 76 |
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 |
