diff options
Diffstat (limited to 'python')
| -rw-r--r-- | python/analytics/option.py | 31 |
1 files changed, 19 insertions, 12 deletions
diff --git a/python/analytics/option.py b/python/analytics/option.py index 2604e073..60861c99 100644 --- a/python/analytics/option.py +++ b/python/analytics/option.py @@ -2,7 +2,6 @@ from __future__ import division import array import datetime -import hashlib import math import numpy as np import pandas as pd @@ -18,6 +17,7 @@ except ImportError: import pickle from pickle import dumps +from functools import wraps from pyisda.curve import SpreadCurve from pyisda.flat_hazard import pv_vec from scipy.optimize import brentq @@ -31,6 +31,19 @@ def calib(S0, fp, exercise_date, exercise_date_settle, index.fixed_rate * 1e-4) return np.inner(pv, w) - fp +def memoize(f): + @wraps(f) + def cached_f(*args, **kwargs): + obj = args[0] + key = (f.__name__, hash(obj)) + if key in obj._cache: + return obj._cache[key] + else: + v = f(*args, **kwargs) + obj._cache[key] = v + return v + return cached_f + def ATMstrike(index, exercise_date): exercise_date_settle = (pd.Timestamp(exercise_date) + 3* BDay()).date() fp = index.forward_pv(exercise_date) / index.notional @@ -104,17 +117,13 @@ class Swaption(ForwardIndex): V = self.df * (self.forward_pv - self._G) return max(V, 0) if self.option_type == "payer" else max(-V, 0) - @property - def _state(self): - return hashlib.md5(dumps( - {k: v for k, v in self.__dict__.items() if k not in - ['_cache', '_Z', '_w']}, protocol = pickle.HIGHEST_PROTOCOL)).digest() + def __hash__(self): + return hash(dumps([v for k, v in self.__dict__.items() if k not in + ['_cache', '_Z', '_w']], protocol=pickle.HIGHEST_PROTOCOL)) @property + @memoize def pv(self): - k = self._state - if k in self._cache: - return self._cache[k] T = self.T tilt = np.exp(-self.sigma**2/2 * T + self.sigma * self._Z * math.sqrt(T)) args = (self.forward_pv, self.exercise_date, self.exercise_date_settle, @@ -145,9 +154,7 @@ class Swaption(ForwardIndex): self.exercise_date_settle, self.index.start_date, self.index.end_date, self.index.recovery, self.index.fixed_rate * 1e-4) val = (r - self._G) * 1/math.sqrt(2*math.pi) * np.exp(-Z**2/2) - pv = self.notional * simps(val, Z) * self.df - self._cache[k] = pv - return pv + return self.notional * simps(val, Z) * self.df @pv.setter def pv(self, val): |
