diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/basket_index.py | 14 | ||||
| -rw-r--r-- | python/analytics/tranche_basket.py | 83 | ||||
| -rw-r--r-- | python/analytics/tranche_functions.py | 8 | ||||
| -rw-r--r-- | python/index_data.py | 2 |
4 files changed, 83 insertions, 24 deletions
diff --git a/python/analytics/basket_index.py b/python/analytics/basket_index.py index 7b0fa8f8..0347a224 100644 --- a/python/analytics/basket_index.py +++ b/python/analytics/basket_index.py @@ -17,7 +17,7 @@ class BasketIndex(CreditIndex): value_date: pd.Timestamp tweaks: List[float] - def __init__(self, index_type: str, series: int, tenors: List[str], *args, + def __init__(self, index_type: str, series: int, tenors: List[str], *, trade_date: pd.Timestamp=pd.Timestamp.today().normalize() - BDay()): self.index_type = index_type self.series = series @@ -33,7 +33,7 @@ class BasketIndex(CreditIndex): index_col='tenor', params=(index_type, series), parse_dates=['maturity', 'issue_date']) - r = _engine.execute("SELECT lastdate, indexfactor/100 AS factor, cumulativeloss, version " \ + r = _engine.execute("SELECT lastdate, indexfactor/100 AS factor, cumulativeloss/100, version " \ "FROM index_version " \ "WHERE index = %s AND series = %s" \ "ORDER BY lastdate", (index_type, series)) @@ -57,15 +57,15 @@ class BasketIndex(CreditIndex): @property def factor(self): - return self._query_version(1) + return self._query_version(0) @property def cumloss(self): - return self._query_version(2) + return self._query_version(1) @property def version(self): - return self._query_version(3) + return self._query_version(2) def _get_quotes(self): pass @@ -125,9 +125,9 @@ class BasketIndex(CreditIndex): self.tweak_portfolio(eps, m) class MarkitBasketIndex(BasketIndex): - def __init__(self, index_type: str, series: int, tenors: List[str], *args, + def __init__(self, index_type: str, series: int, tenors: List[str], *, trade_date: pd.Timestamp=pd.Timestamp.today().normalize() - BDay()): - super().__init__(index_type, series, tenors, *args, trade_date) + super().__init__(index_type, series, tenors, trade_date=trade_date) self.index_quotes = (get_index_quotes(index_type, series, tenors, years=None)['closeprice']. unstack(). diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py index 67327e00..ad96cb59 100644 --- a/python/analytics/tranche_basket.py +++ b/python/analytics/tranche_basket.py @@ -1,22 +1,61 @@ from .basket_index import BasketIndex from .db import _engine -from .tranche_functions import credit_schedule +from .tranche_functions import credit_schedule, adjust_attachments, cds_accrued from index_data import get_singlenames_curves, get_tranche_quotes from pyisda.cdsone import upfront_charge from pandas.tseries.offsets import BDay import pandas as pd +import numpy as np 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) + def __init__(self, index_type: str, series: int, tenor: str, *, + trade_date: pd.Timestamp=pd.Timestamp.today().normalize()): + print(trade_date) + super().__init__(index_type, series, [tenor], trade_date=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 + self.K_orig = np.hstack([0, self.tranche_quotes.detach]) + self.K = adjust_attachments(self.K_orig, self.cumloss, self.factor) + if index_type == "HY": + self.tranche_quotes['quotes'] = 1 - self.tranche_quotes.trancheupfrontmid / 100 + else: + self.tranche_quotes['quotes'] = self.tranche_quotes.trancheupfrontmid / 100 + self.tranche_quotes['running'] = self.tranche_quotes.trancherunningmid * 1e-4 + + if index_type == "XO": + coupon = 500 * 1e-4 + self.tranche_quotes.quotes.iat[3] = self._snacpv(self.tranche_quotes.running.iat[3], + coupon, + 0.4) + self.tranche_quotes.running = coupon + + if index_type == "EU": + if series >= 21: + coupon = 100 * 1e-4 + for i in [2, 3]: + self.tranche_quotes.quotes.iat[i] = self._snacpv( + self.tranche_quotes.running.iat[i], + coupon, + 0. if i == 2 else 0.4) + self.tranche_quotes.running.iat[i] = coupon + elif series == 9: + for i in [3, 4, 5]: + coupon = 25 * 1e-4 if i == 5 else 100 * 1e-4 + recov = 0.4 if i == 5 else 0 + self.tranche_quotes.quotes.iat[i] = self._snacpv( + self.tranche_quotes.running.iat[i], + coupon, + recov) + self.tranche_quotes.running.iat[i] = coupon + accrued = cds_accrued(self.trade_date, self.tranche_quotes.running) + self.tranche_quotes.quotes -= accrued + + self._Ngh = 250 + self._Ngrid = 201 + self._Z, self._w = GHquad(self._Ngh) def _get_quotes(self): refprice = self.tranche_quotes[0]['indexrefprice'] @@ -25,12 +64,32 @@ class TrancheBasket(BasketIndex): 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)} + _scnacpv(refspread * 1e-4, self.coupon(maturity), self.recovery)} raise ValueError("ref is missing") + def _snacpv(self, spread, coupon, recov): + return upfront_charge(self.trade_date, self.value_date, self.start_date, + self.step_in_date, self.start_date, self.maturity, + coupon, self.yc, spread, recov) + @property - def survival_matrix(self): - return super().survival_matrix(self.cs.index.values.astype('M8[D]').view('int') + 134774) + def default_prob(self): + return 1 - super().survival_matrix(self.cs.index.values.astype('M8[D]').view('int') + 134774) + + def tranche_legs(self, K, rho, complement=False): + if ((K == 0 and not complement) or (K == 1 and complement)): + return {'cl': 0., 'pl': 0.} + elif ((K == 1 and not complement) or (K == 0 and complement)): + return BCindexpv(index) + else: + L, R = BCloss_recov_dist(self.default_prob, + self.weights, + self.recovery, + rho, + self._Z, self._w, self._Ngrid) + if complement: + return {'cl': tranche_cl(L, R, self.cs, K, 1), + 'pl': tranche_pl(L, self.cs, K, 1)} + else: + return {'cl': tranche_cl(L, R, self.cs, 0, K), + 'pl': tranche_pl(L, self.cs, 0, K)} diff --git a/python/analytics/tranche_functions.py b/python/analytics/tranche_functions.py index 25020cd6..499bbc7e 100644 --- a/python/analytics/tranche_functions.py +++ b/python/analytics/tranche_functions.py @@ -304,14 +304,14 @@ def credit_schedule(tradedate, tenor, coupon, yc, enddate=None): return pydates[0], pd.DataFrame({"df": df, "coupons": coupons}, dates[1:]) -def cdsAccrued(tradedate, coupon): +def cds_accrued(tradedate, coupon): tradedate = pydate_to_qldate(tradedate) - end = tradedate + Period('3Mo') + end = tradedate + Period('3M') start_protection = tradedate + 1 DC = Actual360() - cal = UnitedStates() - sched = Schedule(start, end, Period('3Mo'), cal, date_generation_rule=CDS2015) + cal = WeekendsOnly() + sched = Schedule(tradedate, end, Period('3M'), cal, date_generation_rule=CDS2015) prevpaydate = sched.previous_date(tradedate) return DC.year_fraction(prevpaydate, start_protection) * coupon diff --git a/python/index_data.py b/python/index_data.py index a4f76113..730a4e8a 100644 --- a/python/index_data.py +++ b/python/index_data.py @@ -173,4 +173,4 @@ def get_tranche_quotes(index_type, series, tenor, date=datetime.date.today()): conn = dbconn('serenitasdb') with conn.cursor() as c: c.callproc("get_tranche_quotes", (index_type, series, tenor, date)) - return c.fetchall() + return pd.DataFrame.from_records(dict(d) for d in c) |
