diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/exceptions.py | 2 | ||||
| -rw-r--r-- | python/analytics/option.py | 34 | ||||
| -rw-r--r-- | python/analytics/tranche_basket.py | 7 |
3 files changed, 31 insertions, 12 deletions
diff --git a/python/analytics/exceptions.py b/python/analytics/exceptions.py new file mode 100644 index 00000000..42dc11b0 --- /dev/null +++ b/python/analytics/exceptions.py @@ -0,0 +1,2 @@ +class MissingDataError(Exception): + pass diff --git a/python/analytics/option.py b/python/analytics/option.py index 803f6500..c334a47e 100644 --- a/python/analytics/option.py +++ b/python/analytics/option.py @@ -1,13 +1,15 @@ import bottleneck as bn import datetime +import logging import math import numpy as np import pandas as pd import analytics from .black import black, Nx +from .exceptions import MissingDataError from .sabr import sabr -from .utils import GHquad, build_table +from .utils import GHquad, build_table, bus_day from .index import g, ForwardIndex, CreditIndex from .db import serenitas_engine, dawn_engine from .utils import memoize @@ -30,6 +32,8 @@ from scipy.integrate import quad from scipy.special import logit, expit +logger = logging.getLogger(__name__) + def calib(S0, fp, tilt, w, ctx): return expected_pv(tilt, w, S0, ctx) - fp @@ -94,22 +98,34 @@ class BlackSwaption(ForwardIndex): instance._orig_params = (rec.strike, index.factor, index.cumloss) return instance - def mark(self, source_list=[], surface_id=None, **args): + def mark(self, source_list=[], surface_id=None, **kwargs): ind = self.index ind.mark() # add None so that we always try everything source_list = source_list + [None] - vs = BlackSwaptionVolSurface(ind.index_type, - ind.series, - ind.tenor, - ind.value_date, - **args) + surface_date = kwargs.get("surface_date", ind.value_date) + i = 0 + while i < 5: + try: + vs = BlackSwaptionVolSurface(ind.index_type, + ind.series, + ind.tenor, + surface_date, + **kwargs) + + except MissingDataError as e: + logger.warning(str(e)) + surface_date -= bus_day + logger.info(f"trying {self.value_date - bus_day}") + i += 1 + else: + break if surface_id is None: for source in source_list: if len(vs.list(source, self.option_type)) >= 1: break else: - raise ValueError("No market data available for this day") + raise MissingDataError(f"{type(self).__name__}: No quote for type {self.option_type} and date {self.value_date}") surface_id = vs.list(source, self.option_type)[-1] try: self.sigma = float(vs[surface_id](self.T, np.log(self.moneyness))) @@ -508,7 +524,7 @@ class QuoteSurface(): self._quotes.loc[(self._quotes.quote_source == "GS") & (self._quotes['index'] =="HY"), ["pay_bid", "pay_offer", "rec_bid", "rec_offer"]] *=100 if self._quotes.empty: - raise ValueError(f"No quotes for date: {value_date}") + raise MissingDataError(f"{type(self).__name__}: No market quote for date {value_date}") self._quotes['quotedate'] = (self._quotes['quotedate'].dt. tz_convert('America/New_York'). dt.tz_localize(None)) diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py index 48353b46..56d5b0f2 100644 --- a/python/analytics/tranche_basket.py +++ b/python/analytics/tranche_basket.py @@ -3,6 +3,7 @@ from .tranche_functions import ( credit_schedule, adjust_attachments, GHquad, BCloss_recov_dist, BCloss_recov_trunc, tranche_cl, tranche_pl, tranche_pl_trunc, tranche_cl_trunc) +from .exceptions import MissingDataError from .index_data import get_tranche_quotes from .utils import memoize, build_table, bus_day, next_twentieth from collections import namedtuple @@ -72,7 +73,7 @@ class Skew(): conn.commit() serenitas_pool.putconn(conn) if not K: - raise ValueError(f"No skew for {index_type}{series} {tenor} on {value_date}") + raise MissingDataError(f"No skew for {index_type}{series} {tenor} on {value_date}") K.append(100) K = np.array(K) / 100 K = adjust_attachments(K, cumloss/100, factor/100) @@ -406,7 +407,7 @@ class DualCorrTranche(): try: ref, = c.fetchone() except TypeError: - raise ValueError(f"No quote for date {self.value_date}") + raise MissingDataError(f"{type(self).__name__}: No market quote for date {self.value_date}") try: self._index.tweak([ref]) except NameError: @@ -424,7 +425,7 @@ class DualCorrTranche(): self.series, self.tenor, value_date=d)) - except ValueError as e: + except MissingDataError as e: logger.warning(str(e)) d -= bus_day logger.info(f"trying {d}") |
