diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/basket_index.py | 2 | ||||
| -rw-r--r-- | python/analytics/index.py | 11 | ||||
| -rw-r--r-- | python/analytics/portfolio.py | 25 | ||||
| -rw-r--r-- | python/analytics/tranche_basket.py | 7 |
4 files changed, 36 insertions, 9 deletions
diff --git a/python/analytics/basket_index.py b/python/analytics/basket_index.py index 3b2122c5..b218ed3a 100644 --- a/python/analytics/basket_index.py +++ b/python/analytics/basket_index.py @@ -436,7 +436,7 @@ class BasketIndex(CreditIndex): recov, ) - def jump_to_default(self): + def jtd_single_names(self): pvs = self.pv_vec().swaplevel(axis=1) pvs = pvs.protection_pv - pvs.duration * np.array(self.coupons) return -self.weights[:, None] * (self.recovery_rates[:, None] + pvs - 1) diff --git a/python/analytics/index.py b/python/analytics/index.py index 8e3e9684..3abe5376 100644 --- a/python/analytics/index.py +++ b/python/analytics/index.py @@ -3,6 +3,7 @@ import array import datetime import pandas as pd +from .basket_index import BasketIndex from .credit_default_swap import CreditDefaultSwap from . import serenitas_engine, dawn_engine from .exceptions import MissingDataError @@ -275,6 +276,16 @@ class CreditIndex(CreditDefaultSwap): def cumloss(self): return self._cumloss + def jtd_single_names(self, spreads=False): + """single names jump to defaut""" + bkt = BasketIndex(self.index_type, self.series, [self.tenor]) + bkt.value_date = self.value_date + bkt.tweak([self.ref]) + jtd = bkt.jtd_single_names() * self.notional + if spreads: + jtd["spread"] = bkt.spreads() * 10000 + return jtd.unstack().swaplevel() + def __repr__(self): if not self.spread: raise ValueError("Market spread is missing!") diff --git a/python/analytics/portfolio.py b/python/analytics/portfolio.py index 62861922..d37c0e11 100644 --- a/python/analytics/portfolio.py +++ b/python/analytics/portfolio.py @@ -2,6 +2,7 @@ from __future__ import annotations from .index import CreditIndex from .option import BlackSwaption from .tranche_basket import DualCorrTranche +from functools import reduce import pandas as pd import numpy as np @@ -136,12 +137,24 @@ class Portfolio: @property def jump_to_default(self): - r = [] - for t in self.trades: - print(t.index_type, t.series, t.attach, t.detach) - r.append(t.jump_to_default()) - df = pd.concat(r, axis=1) - return df.sum(axis=1) + return sum(t.jump_to_default for t in self.trades if isinstance(t, CreditIndex)) + + def jtd_single_names(self): + jtd = reduce( + lambda x, y: x.add(y, fill_value=0.0), + ( + t.jtd_single_names() + for t in self.trades + if isinstance(t, (DualCorrTranche, CreditIndex)) + ), + ) + return ( + jtd.unstack() + .sort_index(1, ascending=False) + .fillna(0.0) + .cumsum(axis=1) + .sort_index(1) + ) @value_date.setter def value_date(self, d): diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py index 4c67f06c..a42a31c6 100644 --- a/python/analytics/tranche_basket.py +++ b/python/analytics/tranche_basket.py @@ -678,7 +678,7 @@ class DualCorrTranche: if self.detach == 100: self.rho[1] = np.nan - def jump_to_default(self): + def jtd_single_names(self): curves = self._index.curves orig_factor, orig_cumloss = self._index.factor, self._index.cumloss orig_upf = self.tranche_factor * self.upfront @@ -711,7 +711,10 @@ class DualCorrTranche: ) self._index.curves = curves self.rho = rho_orig - return pd.Series(r, index=tickers) + return pd.Series( + r, + index=pd.MultiIndex.from_product([tickers, [pd.Timestamp(self.maturity)]]), + ) @property def tranche_factor(self): |
