diff options
| -rw-r--r-- | python/analytics/credit_default_swap.py | 37 | ||||
| -rw-r--r-- | python/tests/test_index.py | 34 |
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() |
