diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/index.py | 32 | ||||
| -rw-r--r-- | python/analytics/option.py | 18 |
2 files changed, 27 insertions, 23 deletions
diff --git a/python/analytics/index.py b/python/analytics/index.py index d085b140..56ab4704 100644 --- a/python/analytics/index.py +++ b/python/analytics/index.py @@ -59,6 +59,7 @@ class Index(): self._sc = None self._risky_annuity = None self._spread = None + self._price = None self.name = None @property @@ -168,19 +169,20 @@ class Index(): @price.setter def price(self, val): - def handle(x, self, val): - self._spread = x + if self._price is None or math.fabs(val, self._price) > 1e-6: + def handle(x, self, val): + self._spread = x + self._update() + return val - self.price + eta = 1.2 + a = self.fixed_rate*1e-4 * 0.5 + b = a * eta + while True: + if handle(b, self, val) > 0: + break + b *= eta + self._spread = brentq(handle, a, b, args = (self, val)) self._update() - return val - self.price - eta = 1.2 - a = self.fixed_rate*1e-4 * 0.5 - b = a * eta - while True: - if handle(b, self, val) > 0: - break - b *= eta - self._spread = brentq(handle, a, b, args = (self, val)) - self._update() @property def DV01(self): @@ -366,10 +368,12 @@ class ForwardIndex(): @ref.setter def ref(self, val : float): if self._ref_is_price: - if math.abs(self.index.price - val) > 1e-6: + if self.index.price is None or \ + math.fabs(self.index.price - val) > 1e-6: self.index.price = val + self._update() else: - if val != self.index.spread: + if self.index.spread is None or val != self.index.spread: self.index.spread = val self._update() diff --git a/python/analytics/option.py b/python/analytics/option.py index 89b6e244..1f250bb3 100644 --- a/python/analytics/option.py +++ b/python/analytics/option.py @@ -10,17 +10,17 @@ from .index import g, ForwardIndex from yieldcurve import roll_yc from pandas.tseries.offsets import BDay from pyisda.curve import SpreadCurve -from pyisda.flat_hazard import strike_vec +from pyisda.flat_hazard import pv_vec from scipy.optimize import brentq from scipy.integrate import simps def calib(S0, fp, exercise_date : datetime.date, exercise_date_settle :datetime.date, index, rolled_curve, tilt, w): S = S0 * tilt * 1e-4 - a, b = strike_vec(S, rolled_curve, exercise_date, exercise_date_settle, - index.start_date, index.end_date, index.recovery) - vec = a - index.fixed_rate * b * 1e-4 - return np.inner(vec, w) - fp + pv = pv_vec(S, rolled_curve, exercise_date, exercise_date_settle, + index.start_date, index.end_date, index.recovery, + index.fixed_rate * 1e-4) + return np.inner(pv, w) - fp def ATMstrike(index, exercise_date : datetime.date): exercise_date_settle = (pd.Timestamp(exercise_date) + 3* BDay()).date() @@ -120,10 +120,10 @@ class Swaption(ForwardIndex): else: raise ValueError("option_type needs to be either 'payer' or 'receiver'") S = S0 * np.exp(-self.sigma**2/2 * T + self.sigma * Z * math.sqrt(T)) - a, b = strike_vec(S * 1e-4, self._forward_yc, self.exercise_date, - self.exercise_date_settle, - self.index.start_date, self.index.end_date, self.index.recovery) - val = ((a - b * self.index.fixed_rate*1e-4) - self._G) * 1/math.sqrt(2*math.pi) * np.exp(-Z**2/2) + r = pv_vec(S * 1e-4, self._forward_yc, self.exercise_date, + 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) return self.notional * simps(val, Z) * self.df @pv.setter |
