diff options
Diffstat (limited to 'python/analytics')
| -rw-r--r-- | python/analytics/option.py | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/python/analytics/option.py b/python/analytics/option.py index 2863e77b..856b4cae 100644 --- a/python/analytics/option.py +++ b/python/analytics/option.py @@ -73,7 +73,8 @@ def ATMstrike(index, exercise_date): class BlackSwaption(ForwardIndex): """Swaption class""" - def __init__(self, index, exercise_date, strike, option_type="payer"): + def __init__(self, index, exercise_date, strike, option_type="payer", + direction="Long"): ForwardIndex.__init__(self, index, exercise_date) self._exercise_date = exercise_date self._forward_yc = roll_yc(index._yc, exercise_date) @@ -84,6 +85,7 @@ class BlackSwaption(ForwardIndex): self.notional = 1 self.sigma = None self._cache = {} + self._direction = 1 @classmethod def from_tradeid(cls, trade_id): @@ -97,6 +99,7 @@ class BlackSwaption(ForwardIndex): instance = cls(index, rec.expiration_date, rec.strike, rec.swaption_type.lower()) instance.notional = rec.notional instance.pv = rec.price * 1e-2 * rec.notional + instance.direction = "Long" if rec.buysell else "Short" return instance @property @@ -141,6 +144,22 @@ class BlackSwaption(ForwardIndex): return self.strike / self.atm_strike @property + def direction(self): + if self._direction == 1.: + return "Long" + else: + return "Short" + + @direction.setter + def direction(self, d): + if d == "Long": + self._direction = 1. + elif d == "Short": + self._direction = -1. + else: + raise ValueError("Direction needs to be either 'Buyer' or 'Seller'") + + @property def intrinsic_value(self): V = self.df * (self.forward_pv - self._G) return max(V, 0) if self.option_type == "payer" else max(-V, 0) @@ -156,11 +175,13 @@ class BlackSwaption(ForwardIndex): return self.intrinsic_value else: strike_tilde = self.index.fixed_rate * 1e-4 + self._G / self.forward_annuity * self.df - return self.forward_annuity * black(self.forward_spread * 1e-4, - strike_tilde, - self.T, - self.sigma, - self.option_type == "payer") * self.notional + return self._direction * self.forward_annuity * \ + black(self.forward_spread * 1e-4, + strike_tilde, + self.T, + self.sigma, + self.option_type == "payer") * self.notional + @pv.setter def pv(self, val): if np.isnan(val): @@ -192,7 +213,8 @@ class BlackSwaption(ForwardIndex): self._update() notional_ratio = self.index.notional/self.notional self._dv01 = (self.pv - old_pv) - delta = self._dv01/(self.index.pv - old_index_pv) * notional_ratio + delta = -self.index._direction * self._dv01 * notional_ratio / \ + (self.index.pv - old_index_pv) self.index.spread -= 1 self._update() return delta @@ -211,7 +233,7 @@ class BlackSwaption(ForwardIndex): old_delta = self.delta self.index.spread -= 10 self._update() - gamma = abs(self.delta - old_delta) + gamma = old_delta - self.delta self.index.spread += 5 self._update() return gamma @@ -244,7 +266,7 @@ class BlackSwaption(ForwardIndex): @property def breakeven(self): - pv = self.pv / self.notional + pv = self._direction * self.pv / self.notional if self.index._quote_is_price: if self.option_type == "payer": return 100 * (1 - self._G - pv) @@ -338,7 +360,7 @@ class Swaption(BlackSwaption): 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 + return self._direction * self.notional * simps(val, Z) * self.df @pv.setter def pv(self, val): |
