diff options
| -rw-r--r-- | python/swaption.py | 57 |
1 files changed, 27 insertions, 30 deletions
diff --git a/python/swaption.py b/python/swaption.py index 5d00c9c8..c85a9b12 100644 --- a/python/swaption.py +++ b/python/swaption.py @@ -119,7 +119,7 @@ class Index(): self.trade_date, self._step_in_date, self._value_date, self._yc, self._sc, self.recovery) self._pv = self._dl_pv - self._risky_annuity * self.fixed_rate * 1e-4 - self._clean_pv = self._pv - self._accrued * self.fixed_rate * 1e-4 + self._clean_pv = self._pv + self._accrued * self.fixed_rate * 1e-4 self._price = 100 * (1 - self._clean_pv) @spread.setter @@ -148,7 +148,7 @@ class Index(): @property def clean_pv(self): - return self._clean_pv + return self.notional * self._clean_pv @property def price(self): @@ -312,16 +312,20 @@ def year_frac(d1, d2, day_count_conv = "Actual/365"): return (d2-d1).days/360 -def calib(S0, fp, exercise_date, exercise_date_settle, index, tilt, w): +def calib(S0, fp, exercise_date, exercise_date_settle, index, + rolled_curve, tilt, w): S = S0 * tilt * 1e-4 - a, b = strike_vec(S, index._yc, exercise_date, exercise_date_settle, + 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 -def g(index, spread, exercise_date): +def g(index, spread, exercise_date, use_rolled_curve = True): """ computes the strike clean price using the expected forward yield curve """ - rolled_curve = roll_yc(index._yc, exercise_date) + if use_rolled_curve: + rolled_curve = roll_yc(index._yc, exercise_date) + else: + rolled_curve = index._yc step_in_date = exercise_date + datetime.timedelta(days=1) exercise_date_settle = (pd.Timestamp(exercise_date) + 3* BDay()).date() sc = SpreadCurve(exercise_date, rolled_curve, index.start_date, @@ -330,22 +334,7 @@ def g(index, spread, exercise_date): index.recovery) a = index._fee_leg.pv(exercise_date, step_in_date, exercise_date_settle, rolled_curve, sc, True) - return index.notional * (spread - index.fixed_rate) * a *1e-4 - -def g2(index, spread, exercise_date): - """ computes the strike price using the expected forward yield curve """ - step_in_date = exercise_date + datetime.timedelta(days=1) - exercise_date_settle = (pd.Timestamp(exercise_date) + 3* BDay()).date() - sc = SpreadCurve(exercise_date, index._yc, index.start_date, - step_in_date, exercise_date_settle, - [index.end_date], array.array('d', [spread * 1e-4]), - index.recovery) - a = index._fee_leg.pv(exercise_date, step_in_date, exercise_date_settle, - index._yc, sc, True) - dl_pv = index._default_leg.pv( - exercise_date, step_in_date, exercise_date_settle, index._yc, - sc, index.recovery) - return index.notional * (dl_pv - a * index.fixed_rate * 1e-4) + return (spread - index.fixed_rate) * a *1e-4 def ATMstrike(index, exercise_date): exercise_date_settle = (pd.Timestamp(exercise_date) + 3* BDay()).date() @@ -364,6 +353,7 @@ class Option: def __init__(self, index, exercise_date, strike, option_type="payer"): self.index = index self._exercise_date = exercise_date + self._forward_yc = roll_yc(self.index._yc, self.exercise_date) self.exercise_date_settle = (pd.Timestamp(self.exercise_date) + 3* BDay()).date() self._T = None self.strike = strike @@ -374,18 +364,21 @@ class Option: @property def exercise_date(self): return self._exercise_date + @exercise_date.setter def exercise_date(self, d : datetime.date): self._exercise_date = d self.exercise_date_settle = (pd.Timestamp(d) + 3* BDay()).date() + self._forward_yc = roll_yc(self.index._yc, self.exercise_date) @property def pv(self): - fp = self.index.forward_pv(self.exercise_date)/self.index.notional + fp = self.index.forward_pv(self.exercise_date) / self.index.notional T = self.T tilt = np.exp(-self.sigma**2/2 * T + self.sigma * self._Z * math.sqrt(T)) + rolled_curve = roll_yc(self.index._yc, self.exercise_date) args = (fp, self.exercise_date, self.exercise_date_settle, - self.index, tilt, self._w) + self.index, self._forward_yc, tilt, self._w) eta = 1.1 a = self.index.spread b = self.index.spread * eta @@ -406,13 +399,13 @@ class Option: Zstar = (math.log(self.strike/S0) + self.sigma**2/2 * T) / \ (self.sigma * math.sqrt(T)) if self.option_type == "payer": - Z = Zstar + np.logspace(0, 2, 300) - 1 + Z = Zstar + np.logspace(0, 1.5, 300) - 1 elif self.option_type == "receiver": - Z = Zstar - np.logspace(0, 2, 300) + 1 + Z = Zstar - np.logspace(0, 1.5, 300) + 1 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.index._yc, self.exercise_date, + a, b = strike_vec(S * 1e-4, rolled_curve, 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) - G) * 1/math.sqrt(2*math.pi) * np.exp(-Z**2/2) @@ -422,18 +415,22 @@ class Option: @property def pv2(self): G = g(self.index, self.strike, self.exercise_date) - fp = self.index.forward_pv(self.exercise_date) + fp = self.index.forward_pv(self.exercise_date) / self.index.notional forward_annuity = self.index.forward_annuity(self.exercise_date) DA_forward_spread = fp / forward_annuity + self.index.fixed_rate * 1e-4 strike_tilde = self.index.fixed_rate * 1e-4 + G / forward_annuity - return forward_annuity * black(DA_forward_spread, strike_tilde, self.T, self.sigma, self.option_type) + return forward_annuity * black(DA_forward_spread, + strike_tilde, + self.T, + self.sigma, + self.option_type) * self.notional @property def delta(self): old_index_pv = self.index.pv old_pv = self.pv self.index.spread += 0.1 - notional_ratio = self.index.notional/self.option.notional + notional_ratio = self.index.notional/self.notional delta = (self.pv - old_pv)/(self.index.pv - old_index_pv) * notional_ratio self.index.spread -= 0.1 return delta |
