aboutsummaryrefslogtreecommitdiffstats
path: root/python/analytics
diff options
context:
space:
mode:
Diffstat (limited to 'python/analytics')
-rw-r--r--python/analytics/option.py42
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):