class SofrFuture(unittest.TestCase): def setUp(self): self.today = Date(26, October, 2018) self.settings = Settings().__enter__() self.settings.evaluation_date = self.today def test_bootstrap(self): """ testing bootstrap over SOFR futures...""" sofr_quotes = [ [Monthly, Oct, 2018, 97.8175, RateAveraging.Simple], [Monthly, Nov, 2018, 97.770, RateAveraging.Simple], [Monthly, Dec, 2018, 97.685, RateAveraging.Simple], [Monthly, Jan, 2019, 97.595, RateAveraging.Simple], [Monthly, Feb, 2019, 97.590, RateAveraging.Simple], [Monthly, Mar, 2019, 97.525, RateAveraging.Simple], [Quarterly, Mar, 2019, 97.440, RateAveraging.Compound], [Quarterly, Jun, 2019, 97.295, RateAveraging.Compound], [Quarterly, Sep, 2019, 97.220, RateAveraging.Compound], [Quarterly, Dec, 2019, 97.170, RateAveraging.Compound], [Quarterly, Mar, 2020, 97.160, RateAveraging.Compound], [Quarterly, Jun, 2020, 97.165, RateAveraging.Compound], [Quarterly, Sep, 2020, 97.175, RateAveraging.Compound], ] index = Sofr() index.add_fixing(Date(1, October, 2018), 0.0222) index.add_fixing(Date(2, October, 2018), 0.022) index.add_fixing(Date(3, October, 2018), 0.022) index.add_fixing(Date(4, October, 2018), 0.0218) index.add_fixing(Date(5, October, 2018), 0.0216) index.add_fixing(Date(9, October, 2018), 0.0215) index.add_fixing(Date(10, October, 2018), 0.0215) index.add_fixing(Date(11, October, 2018), 0.0217) index.add_fixing(Date(12, October, 2018), 0.0218) index.add_fixing(Date(15, October, 2018), 0.0221) index.add_fixing(Date(16, October, 2018), 0.0218) index.add_fixing(Date(17, October, 2018), 0.0218) index.add_fixing(Date(18, October, 2018), 0.0219) index.add_fixing(Date(19, October, 2018), 0.0219) index.add_fixing(Date(22, October, 2018), 0.0218) index.add_fixing(Date(23, October, 2018), 0.0217) index.add_fixing(Date(24, October, 2018), 0.0218) index.add_fixing(Date(25, October, 2018), 0.0219) helpers = [] for freq, month, year, price, compounding in sofr_quotes: helpers.append( SofrFutureRateHelper(price, month, year, freq, index, 0.0, compounding) ) curve = PiecewiseYieldCurve[BootstrapTrait.Discount, Linear].from_reference_date(self.today, helpers, Actual365Fixed()) sofr = Sofr(curve) sf = OvernightIndexFuture(sofr, Date(20, Mar, 2019), Date(19, Jun, 2019)) expected_price = 97.44 tolerance = 1e-9 self.assertAlmostEqual(sf.npv, expected_price, 9) def tearDown(self): self.settings.__exit__(None, None, None)
class TestOvernightIndexedSwap(unittest.TestCase): def setUp(self): self.today = Date(5, 2, 2009) self.settlement_days = 2 self.nominal = 100 self.settings = Settings().__enter__() self.settings.evaluation_date = self.today self.eonia_term_structure = YieldTermStructure() self.eonia_index = Eonia(self.eonia_term_structure) self.calendar = self.eonia_index.fixing_calendar self.settlement = self.calendar.advance(self.today, self.settlement_days, Following) self.eonia_term_structure.link_to(flat_rate(0.05)) def make_swap(self, length, fixed_rate, spread, telescopic_value_dates, effective_date=None, payment_lag=0, averaging_method=RateAveraging.Compound): return (MakeOIS( length, self.eonia_index, fixed_rate, 0 * Days).with_effective_date( self.settlement if effective_date is None else effective_date ).with_overnight_leg_spread(spread).with_nominal( self.nominal).with_payment_lag( payment_lag).with_discounting_term_structure( self.eonia_term_structure).with_telescopic_value_dates( telescopic_value_dates).with_averaging_method( averaging_method))() def test_fair_rate(self): lengths = [1 * Years, 2 * Years, 5 * Years, 10 * Years, 20 * Years] spreads = [-0.001, -.01, 0.0, 0.01, 0.001] for length, spread in product(lengths, spreads): with self.subTest(length=length, spread=spread): swap = self.make_swap(length, 0.0, spread, False) swap2 = self.make_swap(length, 0.0, spread, True) self.assertAlmostEqual(swap.fair_rate, swap2.fair_rate) swap = self.make_swap(length, swap.fair_rate, spread, False) self.assertAlmostEqual(swap.npv, 0.0) swap = self.make_swap(length, swap.fair_rate, spread, True) self.assertAlmostEqual(swap.npv, 0.0) def test_fair_spread(self): lengths = [1 * Years, 2 * Years, 5 * Years, 10 * Years, 20 * Years] rates = [0.04, 0.05, 0.06, 0.07] for length, rate in product(lengths, rates): with self.subTest(length=length, rate=rate): swap = self.make_swap(length, rate, 0.0, False) swap2 = self.make_swap(length, rate, 0.0, True) fair_spread = swap.fair_spread fair_spread2 = swap.fair_spread self.assertAlmostEqual(swap.fair_spread, swap2.fair_spread) swap = self.make_swap(length, rate, fair_spread, False) self.assertAlmostEqual(swap.npv, 0.0) swap = self.make_swap(length, rate, fair_spread, True) self.assertAlmostEqual(swap.npv, 0.0) def test_cached_value(self): flat = 0.05 self.eonia_term_structure.link_to( flat_rate(flat, Actual360(), reference_date=self.settlement)) fixed_rate = math.exp(flat) - 1 swap = self.make_swap(1 * Years, fixed_rate, 0.0, False) swap2 = self.make_swap(1 * Years, fixed_rate, 0.0, True) cached_npv = 0.001730450147 self.assertAlmostEqual(swap.npv, cached_npv) self.assertAlmostEqual(swap2.npv, cached_npv) def tearUp(self): self.settings.__exit__(None, None, None)