diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/basket_index.py | 77 |
1 files changed, 59 insertions, 18 deletions
diff --git a/python/analytics/basket_index.py b/python/analytics/basket_index.py index b5d4b384..92962004 100644 --- a/python/analytics/basket_index.py +++ b/python/analytics/basket_index.py @@ -1,5 +1,6 @@ from .index_data import get_index_quotes, get_singlenames_curves from .db import _engine +from .utils import tenor_t from dateutil.relativedelta import relativedelta from functools import partial from pyisda.credit_index import CreditIndex @@ -50,6 +51,7 @@ class BasketIndex(CreditIndex): self.issue_date = self.index_desc.issue_date[0] maturities = self.index_desc.maturity[tenors].sort_values().dt.to_pydatetime() self.index_desc = self.index_desc.reset_index().set_index('maturity') + self.index_desc.tenor = self.index_desc.tenor.astype(tenor_t) curves = get_singlenames_curves(index_type, series, trade_date) self.currency = "EUR" if index_type in ["XO", "EU"] else "USD" self.yc = get_curve(trade_date, self.currency) @@ -104,31 +106,70 @@ class BasketIndex(CreditIndex): self.value_date = d + 3 * BDay() CreditIndex.trade_date.__set__(self, d) - def pv(self, maturity: pd.Timestamp, epsilon=0.): - return super().pv(self.step_in_date, self.value_date, maturity, self.yc, - self.recovery, self.coupon(maturity), epsilon) + def pv(self, epsilon=0., maturity=None, coupon=None): + if maturity is None: + r = [] + for m in self.maturities: + coupon = self.index_desc.coupon[m] + r.append(super().pv(self.step_in_date, self.value_date, + m, self.yc, self.recovery, + coupon, + epsilon)) + return pd.Series(r, index=self.index_desc.tenor, name='pv') + else: + return super().pv(self.step_in_date, self.value_date, maturity, + self.yc, self.recovery, coupon, + epsilon) + + + def coupon_leg(self, maturity=None): + return self.index_desc.coupon.values * self.duration() - def coupon_leg(self, maturity): - return self.coupon(maturity) * self.duration(maturity) + def protection_leg(self, maturity=None): + return self.pv() + self.coupon_leg() - def protection_leg(self, maturity): - return self.pv(maturity) + self.coupon_leg(maturity) + def spread(self, maturity=None): + return (self.index_desc.coupon.values + self.pv() / self.duration()) * 1e4 - def spread(self, maturity): - return (self.coupon(maturity) + self.pv(maturity) / self.duration(maturity)) * 1e4 + def duration(self, maturity=None): + if maturity is None: + r = [] + for m in self.maturities: + r.append(super().duration(self.step_in_date, self.value_date, + m, self.yc)) + return pd.Series(r, index=self.index_desc.tenor, name='duration') + else: + return super().duration(self.step_in_date, self.value_date, + maturity, self.yc) - def duration(self, maturity): - return super().duration(self.step_in_date, self.value_date, maturity, self.yc) + def theta(self, maturity=None, coupon=None): + """ index thetas - def theta(self, maturity): - if self.step_in_date.date() > maturity - relativedelta(years=1): - return np.NaN + if maturity is None, returns a series of theta for all tenors. + Otherwise compute the theta for that specific maturity (which need + not be an existing tenor)""" + if hasattr(self, "index_quotes"): + index_quotes = self.index_quotes.loc[self.trade_date] + else: + index_quotes = None + if maturity is None: + r = [] + for m in self.maturities: + coupon = self.index_desc.coupon[m] + index_quote = np.nan if index_quotes is None else index_quotes[m] + r.append(super().theta(self.step_in_date, self.value_date, m, + self.yc, self.recovery, coupon, + index_quote)) + return pd.Series(r, index=self.index_desc.tenor, name='theta') else: - index_quote = self.index_quotes.loc[self.trade_date, maturity] + if coupon is None: + raise ValueError("coupon needs to be defined") return super().theta(self.step_in_date, self.value_date, maturity, - self.yc, self.recovery, self.coupon(maturity), index_quote) - def coupon(self, maturity): - return self.index_desc.loc[maturity, 'coupon'] + self.yc, self.recovery, coupon, + np.nan) + + def coupon(self): + return self.index_desc.set_index('tenor').coupon def tweak(self, *args): """ tweak the singlename curves to match index quotes""" |
