aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics')
-rw-r--r--python/analytics/basket_index.py77
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"""