aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/analytics/tranche_basket.py29
1 files changed, 24 insertions, 5 deletions
diff --git a/python/analytics/tranche_basket.py b/python/analytics/tranche_basket.py
index 4b6491ea..6681b53f 100644
--- a/python/analytics/tranche_basket.py
+++ b/python/analytics/tranche_basket.py
@@ -3,8 +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 collections import namedtuple
from copy import deepcopy
+from lru import LRU
from pyisda.date import cds_accrued
from scipy.optimize import brentq
from scipy.interpolate import CubicSpline, PchipInterpolator
@@ -13,6 +15,23 @@ import datetime
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(BasketIndex):
def __init__(self, index_type: str, series: int, tenor: str, *,
@@ -57,11 +76,11 @@ class DualCorrTranche(BasketIndex):
elif np.isnan(rho):
raise ValueError("rho needs to be a real number between 0. and 1.")
else:
- L, R = BCloss_recov_dist(self.default_prob.values,
- self.weights,
- self.recovery_rates,
- rho,
- self._Z, self._w, self._Ngrid)
+ L, R = BCloss_recov_dist_cached(self.default_prob,
+ self.weights,
+ self.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))