diff options
Diffstat (limited to 'python/analytics/tranche_basket.py')
| -rw-r--r-- | python/analytics/tranche_basket.py | 60 |
1 files changed, 26 insertions, 34 deletions
diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py index 034ca416..5cd152f3 100644 --- a/python/analytics/tranche_basket.py +++ b/python/analytics/tranche_basket.py @@ -3,11 +3,10 @@ from .tranche_functions import ( credit_schedule, adjust_attachments, GHquad, BCloss_recov_dist, BCloss_recov_trunc, tranche_cl, tranche_pl) from .index_data import get_tranche_quotes -from cityhash import CityHash64 +from .utils import memoize from collections import namedtuple from db import dbconn from copy import deepcopy -from functools import partial from lru import LRU from pyisda.date import cds_accrued from scipy.optimize import brentq @@ -18,27 +17,6 @@ import pandas as pd import numpy as np -_cache = LRU(64) - - -def BCloss_recov_dist_cached(default_prob, - weights, - recovery_rates, - rho, - Z, w, Ngrid): - h = CityHash64(default_prob.T) ^ CityHash64(weights) ^ \ - CityHash64(recovery_rates) ^ hash(rho) - if h in _cache: - return _cache[h] - else: - _cache[h] = BCloss_recov_dist(default_prob, - weights, - recovery_rates, - rho, - Z, w, Ngrid) - return _cache[h] - - class DualCorrTranche(): def __init__(self, index_type: str, series: int, tenor: str, *, attach: float, detach: float, corr_attach: float, @@ -47,13 +25,13 @@ class DualCorrTranche(): value_date: pd.Timestamp=pd.Timestamp.today().normalize()): self._index = BasketIndex(index_type, series, [tenor], value_date=value_date) - def get_quotes(index, spread): - maturity = index.maturities[0] + def get_quotes(self, spread): + maturity = self.maturities[0] return {maturity: - index._snacpv(spread * 1e-4, index.coupon(maturity), index.recovery, - maturity)} - - self._index._get_quotes = partial(get_quotes, self._index) + self._snacpv(spread * 1e-4, self.coupon(maturity), self.recovery, + maturity)} + # monkey patch _get_quotes (don't try it at home) + BasketIndex._get_quotes = get_quotes self.tenor = tenor self.K_orig = np.array([attach, detach]) / 100 self.attach, self.detach = attach, detach @@ -68,12 +46,25 @@ class DualCorrTranche(): 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) + self._cache = LRU(64) + self._ignore_hash = set(['_Z', '_w', 'cs', '_cache', '_ignore_hash']) def _default_prob(self): return 1 - self._index.survival_matrix( self.cs.index.values.astype('M8[D]'). view('int') + 134774)[0] + def __hash__(self): + def aux(v): + if isinstance(v, list): + return hash(tuple(v)) + elif type(v) is np.ndarray: + return hash(v.tobytes()) + else: + return hash(v) + return hash(tuple(aux(v) for k, v in vars(self).items() + if k not in self._ignore_hash)) + @classmethod def from_tradeid(cls, trade_id): with dbconn('dawndb') as conn: @@ -106,6 +97,7 @@ class DualCorrTranche(): self.cs = credit_schedule(d, None, 1., self._index.yc, self._index.maturities[0]) self._accrued = cds_accrued(d, self.tranche_running * 1e-4) + @memoize def tranche_legs(self, K, rho): if K == 0.: return 0., 0. @@ -114,11 +106,11 @@ class DualCorrTranche(): elif np.isnan(rho): raise ValueError("rho needs to be a real number between 0. and 1.") else: - L, R = BCloss_recov_dist_cached(self._default_prob(), - self._index.weights, - self._index.recovery_rates, - rho, - self._Z, self._w, self._Ngrid) + L, R = BCloss_recov_dist(self._default_prob(), + self._index.weights, + self._index.recovery_rates, + rho, + self._Z, self._w, self._Ngrid) Legs = namedtuple('TrancheLegs', 'coupon_leg, protection_leg') return Legs(tranche_cl(L, R, self.cs, 0., K), tranche_pl(L, self.cs, 0., K)) |
