aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics/basket_index.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics/basket_index.py')
-rw-r--r--python/analytics/basket_index.py84
1 files changed, 63 insertions, 21 deletions
diff --git a/python/analytics/basket_index.py b/python/analytics/basket_index.py
index 261197cc..f41494fc 100644
--- a/python/analytics/basket_index.py
+++ b/python/analytics/basket_index.py
@@ -1,4 +1,6 @@
-import index_data as data
+from index_data import (get_index_quotes, get_singlenames_curves,
+ get_tranche_quotes, _serenitas_engine)
+from tranche_functions import credit_schedule
from dateutil.relativedelta import relativedelta
from pyisda.credit_index import CreditIndex
from typing import List
@@ -7,6 +9,7 @@ import pandas as pd
import datetime
from scipy.optimize import brentq
from pandas.tseries.offsets import BDay
+from pyisda.cdsone import upfront_charge
class BasketIndex(CreditIndex):
index_type: str
@@ -24,25 +27,18 @@ class BasketIndex(CreditIndex):
self.recovery = 0.4
else:
self.recovery = 0.3
- self.index_quotes = (data.get_index_quotes(index_type, series,
- tenors, years=None)['closeprice'].
- unstack().
- groupby(level='date', as_index=False).nth(0).
- reset_index(['index', 'series'], drop=True))
self.index_desc = pd.read_sql_query("SELECT tenor, maturity, coupon * 1e-4 AS coupon, " \
"issue_date "\
"FROM index_maturity " \
"WHERE index=%s AND series=%s",
- data._serenitas_engine,
+ _serenitas_engine,
index_col='tenor',
params=(index_type, series),
parse_dates=['maturity', 'issue_date'])
- self.index_quotes.columns = self.index_desc.loc[self.index_quotes.columns, "maturity"]
- self.index_quotes = 1 - self.index_quotes / 100
self.issue_date = self.index_desc.issue_date[0]
- maturities = self.index_quotes.columns.sort_values().to_pydatetime()
+ maturities = self.index_desc.maturity.sort_values().dt.to_pydatetime()
self.index_desc = self.index_desc.reset_index().set_index('maturity')
- curves, args = data.get_singlenames_curves(index_type, series, trade_date)
+ curves, args = get_singlenames_curves(index_type, series, trade_date)
_, jp_yc, _, step_in_date, value_date, _ = args
self.yc = jp_yc
self.step_in_date = step_in_date
@@ -51,13 +47,16 @@ class BasketIndex(CreditIndex):
self.tweaks = []
super().__init__(self.issue_date, maturities, curves)
+ def _get_quotes(self):
+ pass
+
@property
def trade_date(self):
return self._trade_date
@trade_date.setter
def trade_date(self, d: pd.Timestamp):
- curves, args = data.get_singlenames_curves(self.index_type, self.series, d)
+ curves, args = get_singlenames_curves(self.index_type, self.series, d)
_, jp_yc, _, step_in_date, value_date, _ = args
self.yc = jp_yc
self.step_in_date = step_in_date
@@ -66,9 +65,8 @@ class BasketIndex(CreditIndex):
self.curves = curves
def pv(self, maturity: pd.Timestamp, epsilon=0.):
- coupon = self.index_desc.loc[maturity, 'coupon']
return super().pv(self.step_in_date, self.value_date, maturity, self.yc,
- self.recovery, coupon, epsilon)
+ self.recovery, self.coupon(maturity), epsilon)
def duration(self, maturity):
return super().duration(self.step_in_date, self.value_date, maturity, self.yc)
@@ -77,16 +75,17 @@ class BasketIndex(CreditIndex):
if self.step_in_date.date() > maturity - relativedelta(years=1):
return np.NaN
else:
- coupon = self.index_desc.loc[maturity, 'coupon']
- index_quote = self.index_quotes.loc[self.trade_date,maturity]
+ index_quote = self.index_quotes.loc[self.trade_date, maturity]
return super().theta(self.step_in_date, self.value_date, maturity,
- self.yc, self.recovery, coupon, index_quote)
+ self.yc, self.recovery, self.coupon(maturity), index_quote)
+ def coupon(self, maturity):
+ return self.index_desc.loc[maturity, 'coupon']
+
def tweak(self):
""" tweak the singlename curves to match index quotes"""
- quotes = self.index_quotes.loc[self.trade_date]
+ quotes = self._get_quotes()
self.tweaks = []
- for m, index_quote in quotes.iteritems():
- coupon = self.index_desc.loc[m, 'coupon']
+ for m, index_quote in quotes.items():
lo, hi = -0.3, 0.3
while lo > -1:
try:
@@ -105,6 +104,49 @@ class BasketIndex(CreditIndex):
self.tweaks.append(eps)
self.tweak_portfolio(eps, m)
+class MarkitBasketIndex(BasketIndex):
+ def __init__(self, index_type: str, series: int, tenors: List[str], *args,
+ trade_date: pd.Timestamp=pd.Timestamp.today().normalize() - BDay()):
+ super().__init__(index_type, series, tenors, *args, trade_date)
+ self.index_quotes = (get_index_quotes(index_type, series,
+ tenors, years=None)['closeprice'].
+ unstack().
+ groupby(level='date', as_index=False).nth(0).
+ reset_index(['index', 'series', 'version'], drop=True))
+ self.index_quotes.columns = self.index_desc.loc[self.index_quotes.columns, "maturity"]
+ self.index_quotes = 1 - self.index_quotes / 100
+
+ def _get_quotes(self):
+ return self.index_quotes.loc[self.trade_date]
+
+class TrancheBasket(BasketIndex):
+ def __init__(self, index_type: str, series: int, tenor: str, *args,
+ trade_date: pd.Timestamp=pd.Timestamp.today().normalize() - BDay()):
+ super().__init__(index_type, series, [tenor], *args, trade_date)
+ self.tranche_quotes = get_tranche_quotes(index_type, series, tenor, trade_date.date())
+ index_desc = self.index_desc.reset_index('maturity').set_index('tenor')
+ self.maturity = index_desc.loc[tenor].maturity
+ self.start_date, self.cs = credit_schedule(trade_date, tenor[:-1], 1, self.yc)
+ self.K_orig = [0] + [q['detach'] for q in self.tranche_quotes]
+ self.K = adjust_attachments(self.K_orig, self
+
+ def _get_quotes(self):
+ refprice = self.tranche_quotes[0]['indexrefprice']
+ refspread = self.tranche_quotes[0]['indexrefspread']
+ if refprice is not None:
+ return {self.maturity: 1 - refprice / 100}
+ if refspread is not None:
+ return {self.maturity:
+ upfront_charge(self.trade_date, self.value_date, self.start_date,
+ self.step_in_date, self.start_date, self.maturity,
+ self.coupon(self.maturity), self.yc,
+ refspread * 1e-4, self.recovery)}
+ raise ValueError("ref is missing")
+
+ @property
+ def survival_matrix(self):
+ return super().survival_matrix(self.cs.index.values.astype('M8[D]').view('int') + 134774)
+
if __name__ == "__main__":
ig28 = BasketIndex("IG", 28, ["3yr", "5yr", "7yr", "10yr"])
from quantlib.time.api import Schedule, Rule, Date, Period, WeekendsOnly
@@ -112,5 +154,5 @@ if __name__ == "__main__":
settings = Settings()
cds_schedule = Schedule.from_rule(settings.evaluation_date, Date.from_datetime(ig28.maturities[-1]),
- Period('3M'), WeekendsOnly(), date_generation_rule=Rule.CDS2015)
+ Period('3M'), WeekendsOnly(), date_generation_rule=Rule.CDS2015)
sp = ig28.survival_matrix(cds_schedule.to_npdates().view('int') + 134774)