aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics')
-rw-r--r--python/analytics/basket_index.py2
-rw-r--r--python/analytics/index.py11
-rw-r--r--python/analytics/portfolio.py25
-rw-r--r--python/analytics/tranche_basket.py7
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):