aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--python/analytics/credit_default_swap.py37
-rw-r--r--python/tests/test_index.py34
2 files changed, 42 insertions, 29 deletions
diff --git a/python/analytics/credit_default_swap.py b/python/analytics/credit_default_swap.py
index b6b2a16c..903fe230 100644
--- a/python/analytics/credit_default_swap.py
+++ b/python/analytics/credit_default_swap.py
@@ -50,6 +50,7 @@ class CreditDefaultSwap:
"_original_local_clean_pv",
"_trade_date",
"_factor",
+ "_fx",
)
def __init__(
@@ -186,9 +187,9 @@ class CreditDefaultSwap:
np.array([self.recovery]),
)
+ def _update_pvs(self):
if self._sc is None:
return
-
self._risky_annuity = self._fee_leg.pv(
self.value_date,
self._step_in_date,
@@ -215,6 +216,7 @@ class CreditDefaultSwap:
if self._spread is None or s != self.spread:
self._spread = s * 1e-4
self._update_spread_curve()
+ self._update_pvs()
self.notify()
@property
@@ -226,12 +228,7 @@ class CreditDefaultSwap:
@property
def pv(self):
if not analytics._local:
- return (
- self.notional
- * self._factor
- * self._pv
- * get_fx(self.currency, self.value_date)
- )
+ return self.notional * self._factor * self._pv * self._fx
else:
return self.notional * self._factor * self._pv
@@ -245,7 +242,7 @@ class CreditDefaultSwap:
def accrued(self):
r = -self.notional * self._factor * self._accrued * self.fixed_rate * 1e-4
if not analytics._local:
- r *= get_fx(self.currency, self.value_date)
+ r *= self._fx
return r
@property
@@ -256,13 +253,13 @@ class CreditDefaultSwap:
def clean_pv(self):
r = self.notional * self._factor * self._clean_pv
if not analytics._local:
- r *= get_fx(self.currency, self.value_date)
+ r *= self._fx
return r
@property
def price(self):
if not analytics._local:
- return 100 + (self._price - 100) / get_fx(self.currency, self.value_date)
+ return 100 + (self._price - 100) / self._fx
else:
return self._price
@@ -319,11 +316,14 @@ class CreditDefaultSwap:
with warnings.catch_warnings():
warnings.simplefilter("ignore")
self._update_dates(self.value_date + relativedelta(days=1))
+ self._update_pvs()
carry = -self.notional * self._factor * self.fixed_rate * 1e-4 / 360
if not analytics._local:
- carry *= get_fx(self.currency, old_value_date)
+ carry *= self._fx
roll_down = self.clean_pv - old_pv
+
self._update_dates(old_value_date)
+ self._update_pvs()
return carry + roll_down
@property
@@ -337,12 +337,14 @@ class CreditDefaultSwap:
rh.quote.value += 1e-4
ql_yc = YC(helpers)
self._yc = ql_to_jp(ql_yc)
- self._update_spread_curve() # to force recomputation
+ self._update_spread_curve()
+ self._update_pvs() # to force recomputation
new_pv = self.pv
# for r in self._helpers:
# r.quote -= 1e-4
self._yc = old_yc
self._update_spread_curve()
+ self._update_pvs()
return new_pv - old_pv
@property
@@ -350,12 +352,15 @@ class CreditDefaultSwap:
old_recovery = self.recovery
self.recovery = old_recovery - 0.01
self._update_spread_curve()
+ self._update_pvs()
pv_minus = self.pv
self.recovery = old_recovery + 0.01
self._update_spread_curve()
+ self._update_pvs()
pv_plus = self.pv
self.recovery = old_recovery
self._update_spread_curve()
+ self._update_pvs()
return (pv_plus - pv_minus) / 2
@property
@@ -379,7 +384,9 @@ class CreditDefaultSwap:
return
self._update_dates(d)
self._yc = get_curve(self.value_date, self.currency)
+ self._fx = get_fx(self.value_date, self.currency)
self._update_spread_curve()
+ self._update_pvs()
self.notify()
def _update_dates(self, d):
@@ -392,9 +399,7 @@ class CreditDefaultSwap:
self._cash_settle_date = pd.Timestamp(self._value_date) + 3 * BDay()
def reset_pv(self):
- self._original_clean_pv = self._clean_pv * get_fx(
- self.currency, self.value_date
- )
+ self._original_clean_pv = self._clean_pv * self._fx
self._original_local_clean_pv = self._clean_pv
self._trade_date = self._value_date
@@ -409,7 +414,7 @@ class CreditDefaultSwap:
self.notional
* self._factor
* (
- self._clean_pv * get_fx(self.currency, self.value_date)
+ self._clean_pv * self._fx
- self._original_clean_pv
- days_accrued * self.fixed_rate * 1e-4
)
diff --git a/python/tests/test_index.py b/python/tests/test_index.py
index 6f127fcd..a4ef886a 100644
--- a/python/tests/test_index.py
+++ b/python/tests/test_index.py
@@ -25,27 +25,32 @@ class TestPickle(unittest.TestCase):
def test_from_tradeid(self):
ig28 = CreditIndex.from_tradeid(874)
- self.assertTrue(ig28.spread, 68.)
+ self.assertTrue(ig28.spread, 68.0)
class TestStrike(unittest.TestCase):
index = CreditIndex("ig", 26, "5yr", value_date=datetime.date(2016, 7, 1))
- index.notional = 50_000_000.
+ index.notional = 50_000_000.0
index.spread = 75
exercise_date = datetime.date(2016, 8, 19)
def test_pv(self):
- self.assertAlmostEqual(self.index.clean_pv,
- g(self.index, self.index.spread, self.index.value_date) *
- self.index.notional)
+ self.assertAlmostEqual(
+ self.index.clean_pv,
+ g(self.index, self.index.spread, self.index.value_date)
+ * self.index.notional,
+ )
def test_strike(self):
"""strike price equals clean_pv using expected forward yield curve"""
- strike = g(self.index, self.index.spread, self.exercise_date) * self.index.notional
+ strike = (
+ g(self.index, self.index.spread, self.exercise_date) * self.index.notional
+ )
old_yc = self.index._yc
self.index.value_date = self.exercise_date
self.index._yc = old_yc.expected_forward_curve(self.exercise_date)
- self.index._update()
+ self.index._update_spread_curve()
+ self.index._update_pvs()
self.assertAlmostEqual(self.index.clean_pv, strike)
def test_price_setting(self):
@@ -54,23 +59,26 @@ class TestStrike(unittest.TestCase):
class TestForwardIndex(unittest.TestCase):
- index = CreditIndex("ig", 26, "5yr",
- value_date=datetime.date(2016, 7, 1))
- index.notional = 50_000_000.
+ index = CreditIndex("ig", 26, "5yr", value_date=datetime.date(2016, 7, 1))
+ index.notional = 50_000_000.0
index.spread = 75
exercise_date = datetime.date(2016, 8, 19)
fi = ForwardIndex(index, exercise_date)
def test_forward_pv(self):
"""default adjusted forward spread and forward annuity match"""
- self.assertAlmostEqual(self.fi.forward_pv,
- self.fi.forward_annuity *
- (self.fi.index.fixed_rate - self.forward_spread) * 1e-4)
+ self.assertAlmostEqual(
+ self.fi.forward_pv,
+ self.fi.forward_annuity
+ * (self.fi.index.fixed_rate - self.forward_spread)
+ * 1e-4,
+ )
def test_forward_pv(self):
"""default adjusted forward price for trade_date equals clean pv"""
fi = ForwardIndex(self.index, self.index.value_date)
self.assertAlmostEqual(fi.forward_pv, self.index.clean_pv / self.index.notional)
+
if __name__ == "__main__":
unittest.main()