diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/tranche_basket.py | 40 |
1 files changed, 23 insertions, 17 deletions
diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py index eeba7495..01261808 100644 --- a/python/analytics/tranche_basket.py +++ b/python/analytics/tranche_basket.py @@ -53,8 +53,7 @@ class DualCorrTranche(): self._Z, self._w = GHquad(self._Ngh) self.rho = [corr_attach, corr_detach] self.tranche_running = tranche_running - self._direction = -1. if notional > 0 else 1. - self.notional = abs(notional) + self.notional = notional self.cs = credit_schedule(value_date, None, 1., self._index.yc, self._index.maturities[0]) self._accrued = cds_accrued(value_date, tranche_running * 1e-4) @@ -64,8 +63,7 @@ class DualCorrTranche(): def _default_prob(self, epsilon=0.): return 1 - self._index.survival_matrix( - self.cs.index.values.astype('M8[D]'). - view('int') + 134774, epsilon)[0] + self.cs.index.to_numpy("M8[D]").view("int") + 134774, epsilon)[0] def __hash__(self): def aux(v): @@ -96,7 +94,7 @@ class DualCorrTranche(): instance.direction = rec['protection'] if rec['index_ref'] is not None: instance._index.tweak(rec['index_ref']) - + instance.reset_pv() return instance @property @@ -160,7 +158,7 @@ class DualCorrTranche(): @property def direction(self): - if self._direction == -1.: + if self.notional > 0.: return "Buyer" else: return "Seller" @@ -168,16 +166,20 @@ class DualCorrTranche(): @direction.setter def direction(self, d): if d == "Buyer": - self._direction = -1. + self.notional = abs(self.notional) elif d == "Seller": - self._direction = 1. + self.notional = -abs(self.notional) else: raise ValueError("Direction needs to be either 'Buyer' or 'Seller'") @property def pv(self): pl, cl = self._pv() - return float(-pl - cl + self._accrued) + return -self.notional * (pl + cl) + + @property + def clean_pv(self): + return self.pv + self.notional * self._accrued def _pv(self, epsilon=0.): """ computes coupon leg, protection leg and bond price. @@ -203,7 +205,9 @@ class DualCorrTranche(): @property def upfront(self): - return self._direction * self.notional * (self.pv - self._accrued) + """ returns upfront in points""" + pl, cl = self._pv() + return -100 * (pl + cl - self._accrued) @upfront.setter def upfront(self, upf): @@ -214,18 +218,18 @@ class DualCorrTranche(): print(r.converged) def reset_pv(self): - self._original_pv = self.pv + self._original_clean_pv = self.clean_pv self._trade_date = self.value_date @property def pnl(self): - if self._original_pv is None: + if self._original_clean_pv is None: raise ValueError("original pv not set") else: # TODO: handle factor change days_accrued = (self.value_date - self._trade_date).days / 360 - return self.notional * self._direction * (-self.pv + self._original_pv + - self.tranche_running * 1e-4 * days_accrued) + return (self.clean_pv - self._original_clean_pv + + self.tranche_running * 1e-4 * days_accrued) def __repr__(self): s = [f"{self.index_type}{self.series} {self.tenor} Tranche", @@ -282,7 +286,10 @@ class DualCorrTranche(): self.rho = [] for tranche_id, corr in c: self.rho.append(corr) - self._tranche_id = tranche_id + try: + self._tranche_id = tranche_id + except UnboundLocalError: + pass conn.close() @property @@ -307,8 +314,7 @@ class DualCorrTranche(): calc = self._greek_calc() factor = self.tranche_factor / self._index.factor return (calc['bp'][1] - calc['bp'][2]) / \ - (calc['indexbp'][1] - calc['indexbp'][2]) * \ - factor * -self._direction + (calc['indexbp'][1] - calc['indexbp'][2]) * factor @property def gamma(self): |
