diff options
| -rw-r--r-- | python/swaption.py | 62 |
1 files changed, 33 insertions, 29 deletions
diff --git a/python/swaption.py b/python/swaption.py index 0323eb5f..20cd2d03 100644 --- a/python/swaption.py +++ b/python/swaption.py @@ -24,7 +24,8 @@ serenitasdb = dbconn('serenitasdb') class Index(): """ minimal class to represent a credit index """ - def __init__(self, start_date, end_date, recovery, fixed_rate): + def __init__(self, start_date, end_date, recovery, fixed_rate, + notional = 10e6): """ start_date : :class:`datetime.date` index start_date (Could be issue date, or last imm date) @@ -36,7 +37,7 @@ class Index(): fixed coupon (in bps) """ self.fixed_rate = fixed_rate - self.notional = 1 + self.notional = notional self._start_date = start_date self._end_date = end_date self.recovery = recovery @@ -86,13 +87,12 @@ class Index(): """This is default adjusted forward price at time exercise_date""" step_in_date = exercise_date + datetime.timedelta(days=1) value_date = (pd.Timestamp(exercise_date) + 3* BDay()).date() - - a = self._fee_leg.pv(self.trade_date, step_in_date, value_date, + a = self._fee_leg.pv(self.trade_date, step_in_date, self._value_date, self._yc, self._sc, False) Delta = self._fee_leg.accrued(step_in_date) df = self._yc.discount_factor(value_date) if exercise_date > self.trade_date: - q = math.exp(-self.flat_hazard * (year_frac(self.trade_date, exercise_date)-0.5/365)) + q = math.exp(-self.flat_hazard * (year_frac(self.trade_date, exercise_date))) else: q = 1 clean_forward_annuity = a - Delta * df * q @@ -107,12 +107,6 @@ class Index(): def spread(self): return self._spread * 1e4 - @spread.setter - def spread(self, s: float): - """ s: spread in bps """ - self._spread = s * 1e-4 - self._update() - def _update(self): self._sc = SpreadCurve(self.trade_date, self._yc, self.start_date, self._step_in_date, self._value_date, @@ -124,6 +118,15 @@ class Index(): self._dl_pv = self._default_leg.pv( 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._price = 100 * (1 - self._clean_pv) + + @spread.setter + def spread(self, s: float): + """ s: spread in bps """ + self._spread = s * 1e-4 + self._update() @property def flat_hazard(self): @@ -133,7 +136,7 @@ class Index(): @property def pv(self): - return self.notional * (self._dl_pv - self._risky_annuity * self.fixed_rate * 1e-4) + return self.notional * self._pv @property def accrued(self): @@ -145,16 +148,20 @@ class Index(): @property def clean_pv(self): - return self.pv - self.accrued + return self._clean_pv @property def price(self): - return 100*(1-self.clean_pv/self.notional) + return self._price + + @price.setter + def price(self, val): + pass @property def DV01(self): old_pv = self.pv - self.spread +=1 + self.spread += 1 dv01 = self.pv - old_pv self.spread -= 1 return dv01 @@ -166,7 +173,7 @@ class Index(): for rh in self._helpers: rh.quote += 1e-4 self._yc = ql_to_jp(self._ql_yc) - self._update() + self._update() ## to force recomputation new_pv = self.pv for r in self._helpers: r.quote -= 1e-4 @@ -191,6 +198,7 @@ class Index(): @property def jump_to_default(self): return self.notional * (1 - self.recovery) - self.clean_pv + @property def risky_annuity(self): return self._risky_annuity - self._accrued @@ -309,31 +317,27 @@ def calib(S0, fp, exercise_date, exercise_date_settle, index, tilt, w): a, b = strike_vec(S, index._yc, exercise_date, exercise_date_settle, index.start_date, index.end_date, index.recovery) vec = a - index.fixed_rate * b * 1e-4 - df = index._yc.discount_factor(exercise_date_settle) / \ - index._yc.discount_factor(index._value_date) - return np.inner(vec * df - fp, w) + return np.inner(vec, w) - fp def g(index, spread, exercise_date): """ computes the strike price using the expected forward yield curve """ + rolled_curve = roll_yc(index._yc, exercise_date) 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, + sc = SpreadCurve(exercise_date, rolled_curve, 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) + rolled_curve, sc, True) + return index.notional * (spread - index.fixed_rate) * a *1e-4 def ATMstrike(index, exercise_date): exercise_date_settle = (pd.Timestamp(exercise_date) + 3* BDay()).date() - df = index._yc.discount_factor(exercise_date_settle) / \ - index._yc.discount_factor(index._value_date) + # df = index._yc.discount_factor(exercise_date_settle) / \ + # index._yc.discount_factor(index._value_date) fp = index.forward_pv(exercise_date) - closure = lambda S: g(index, S, exercise_date) * df - fp + closure = lambda S: g(index, S, exercise_date) - fp eta = 1.1 a = index.spread b = index.spread * eta @@ -467,7 +471,7 @@ def option(index, exercise_date, sigma, K, option_type="payer"): if __name__ == "__main__": import datetime from swaption import Index, Option - ig27_5yr = Index.from_name('ig', 27, '5yr', datetime.date(2016, 10, 21)) + ig27_5yr = Index.from_name('ig', 27, '5yr', datetime.date(2016, 10, 24)) ig27_5yr.spread = 74 payer = Option(ig27_5yr, datetime.date(2017, 3, 15), 75) payer.sigma = 0.4847 |
