void OvernightIndexedSwapTest::testCachedValue() { BOOST_TEST_MESSAGE("Testing Eonia-swap calculation against cached value..."); CommonVars vars; Settings::instance().evaluationDate() = vars.today; vars.settlement = vars.calendar.advance(vars.today,vars.settlementDays,Days); Real flat = 0.05; vars.eoniaTermStructure.linkTo(flatRate(vars.settlement,flat,Actual360())); Real fixedRate = exp(flat) - 1; shared_ptr<OvernightIndexedSwap> swap = vars.makeSwap(1*Years, fixedRate, 0.0,false); shared_ptr<OvernightIndexedSwap> swap2 = vars.makeSwap(1*Years, fixedRate, 0.0,true); Real cachedNPV = 0.001730450147; Real tolerance = 1.0e-11; if (std::fabs(swap->NPV()-cachedNPV) > tolerance) BOOST_ERROR("\nfailed to reproduce cached swap value (non telescopic value dates):" << std::fixed << std::setprecision(12) << "\ncalculated: " << swap->NPV() << "\n expected: " << cachedNPV << "\n tolerance:" << tolerance); if (std::fabs(swap2->NPV()-cachedNPV) > tolerance) BOOST_ERROR("\nfailed to reproduce cached swap value (telescopic value dates):" << std::fixed << std::setprecision(12) << "\ncalculated: " << swap->NPV() << "\n expected: " << cachedNPV << "\n tolerance:" << tolerance); }
void OvernightIndexedSwapTest::testSeasonedSwaps() { BOOST_TEST_MESSAGE("Testing seasoned Eonia-swap calculation..."); CommonVars vars; Period lengths[] = { 1*Years, 2*Years, 5*Years, 10*Years, 20*Years }; Spread spreads[] = { -0.001, -0.01, 0.0, 0.01, 0.001 }; Date effectiveDate = Date(2, February, 2009); vars.eoniaIndex->addFixing(Date(2,February,2009), 0.0010); // fake fixing values vars.eoniaIndex->addFixing(Date(3,February,2009), 0.0011); vars.eoniaIndex->addFixing(Date(4,February,2009), 0.0012); vars.eoniaIndex->addFixing(Date(5,February,2009), 0.0013); for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(spreads); j++) { shared_ptr<OvernightIndexedSwap> swap = vars.makeSwap(lengths[i],0.0,spreads[j],false,effectiveDate); shared_ptr<OvernightIndexedSwap> swap2 = vars.makeSwap(lengths[i],0.0,spreads[j],true,effectiveDate); if (std::fabs(swap->NPV() - swap2->NPV()) > 1.0e-10) { BOOST_ERROR("swap npv is different:\n" << std::setprecision(2) << " length: " << lengths[i] << " \n" << " floating spread: " << io::rate(spreads[j]) << "\n" << " swap value (non telescopic value dates): " << swap->NPV() << "\n swap value (telescopic value dates ): " << swap2->NPV()); } } } }
void OvernightIndexedSwapTest::testFairSpread() { BOOST_TEST_MESSAGE("Testing Eonia-swap calculation of " "fair floating spread..."); CommonVars vars; Period lengths[] = { 1*Years, 2*Years, 5*Years, 10*Years, 20*Years }; Rate rates[] = { 0.04, 0.05, 0.06, 0.07 }; for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(rates); j++) { shared_ptr<OvernightIndexedSwap> swap = vars.makeSwap(lengths[i], rates[j], 0.0); Spread fairSpread = swap->fairSpread(); swap = vars.makeSwap(lengths[i], rates[j], fairSpread); if (std::fabs(swap->NPV()) > 1.0e-10) { BOOST_ERROR("\nrecalculating with implied spread:" << std::setprecision(2) << "\n length: " << lengths[i] << "\n fixed rate: " << io::rate(rates[j]) << "\nfair spread: " << io::rate(fairSpread) << "\n swap value: " << swap->NPV()); } } } }
void OvernightIndexedSwapTest::testFairRate() { BOOST_TEST_MESSAGE("Testing Eonia-swap calculation of fair fixed rate..."); CommonVars vars; Period lengths[] = { 1*Years, 2*Years, 5*Years, 10*Years, 20*Years }; Spread spreads[] = { -0.001, -0.01, 0.0, 0.01, 0.001 }; for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(spreads); j++) { shared_ptr<OvernightIndexedSwap> swap = vars.makeSwap(lengths[i],0.0,spreads[j]); swap = vars.makeSwap(lengths[i],swap->fairRate(),spreads[j]); if (std::fabs(swap->NPV()) > 1.0e-10) { BOOST_ERROR("recalculating with implied rate:\n" << std::setprecision(2) << " length: " << lengths[i] << " \n" << " floating spread: " << io::rate(spreads[j]) << "\n" << " swap value: " << swap->NPV()); } } } }
void SwapTest::testFairSpread() { BOOST_TEST_MESSAGE("Testing vanilla-swap calculation of " "fair floating spread..."); CommonVars vars; Integer lengths[] = { 1, 2, 5, 10, 20 }; Rate rates[] = { 0.04, 0.05, 0.06, 0.07 }; for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(rates); j++) { boost::shared_ptr<VanillaSwap> swap = vars.makeSwap(lengths[i],rates[j],0.0); swap = vars.makeSwap(lengths[i],rates[j],swap->fairSpread()); if (std::fabs(swap->NPV()) > 1.0e-10) { BOOST_ERROR("recalculating with implied spread:\n" << std::setprecision(2) << " length: " << lengths[i] << " years\n" << " fixed rate: " << io::rate(rates[j]) << "\n" << " swap value: " << swap->NPV()); } } } }
void SwapTest::testCachedValue() { BOOST_TEST_MESSAGE("Testing vanilla-swap calculation against cached value..."); CommonVars vars; vars.today = Date(17,June,2002); Settings::instance().evaluationDate() = vars.today; vars.settlement = vars.calendar.advance(vars.today,vars.settlementDays,Days); vars.termStructure.linkTo(flatRate(vars.settlement,0.05,Actual365Fixed())); boost::shared_ptr<VanillaSwap> swap = vars.makeSwap(10, 0.06, 0.001); #ifndef QL_USE_INDEXED_COUPON Real cachedNPV = -5.872863313209; #else Real cachedNPV = -5.872342992212; #endif if (std::fabs(swap->NPV()-cachedNPV) > 1.0e-11) BOOST_ERROR("failed to reproduce cached swap value:\n" << QL_FIXED << std::setprecision(12) << " calculated: " << swap->NPV() << "\n" << " expected: " << cachedNPV); }
void SwapTest::testSpreadDependency() { BOOST_TEST_MESSAGE("Testing vanilla-swap dependency on floating spread..."); CommonVars vars; Integer lengths[] = { 1, 2, 5, 10, 20 }; Rate rates[] = { 0.04, 0.05, 0.06, 0.07 }; Spread spreads[] = { -0.01, -0.002, -0.001, 0.0, 0.001, 0.002, 0.01 }; for (Size i=0; i<LENGTH(lengths); i++) { for (Size j=0; j<LENGTH(rates); j++) { // store the results for different spreads... std::vector<Real> swap_values; for (Size k=0; k<LENGTH(spreads); k++) { boost::shared_ptr<VanillaSwap> swap = vars.makeSwap(lengths[i],rates[j],spreads[k]); swap_values.push_back(swap->NPV()); } // and check that they go the right way std::vector<Real>::iterator it = std::adjacent_find(swap_values.begin(),swap_values.end(), std::greater<Real>()); if (it != swap_values.end()) { Size n = it - swap_values.begin(); BOOST_ERROR( "NPV is decreasing with the floating spread in a swap: \n" << " length: " << lengths[i] << " years\n" << " value: " << swap_values[n] << " receiving spread: " << io::rate(spreads[n]) << "\n" << " value: " << swap_values[n+1] << " receiving spread: " << io::rate(spreads[n+1])); } } } }
void OvernightIndexedSwapTest::testBootstrap() { BOOST_TEST_MESSAGE("Testing Eonia-swap curve building..."); CommonVars vars; std::vector<shared_ptr<RateHelper> > eoniaHelpers; std::vector<shared_ptr<RateHelper> > swap3mHelpers; shared_ptr<IborIndex> euribor3m(new Euribor3M); shared_ptr<Eonia> eonia(new Eonia); for (Size i = 0; i < LENGTH(depositData); i++) { Real rate = 0.01 * depositData[i].rate; shared_ptr<SimpleQuote> simple = shared_ptr<SimpleQuote>(new SimpleQuote(rate)); shared_ptr<Quote> quote (simple); Period term = depositData[i].n * depositData[i].unit; shared_ptr<RateHelper> helper(new DepositRateHelper(Handle<Quote>(quote), term, depositData[i].settlementDays, euribor3m->fixingCalendar(), euribor3m->businessDayConvention(), euribor3m->endOfMonth(), euribor3m->dayCounter())); if (term <= 2*Days) eoniaHelpers.push_back(helper); if (term <= 3*Months) swap3mHelpers.push_back(helper); } for (Size i = 0; i < LENGTH(fraData); i++) { Real rate = 0.01 * fraData[i].rate; shared_ptr<SimpleQuote> simple = shared_ptr<SimpleQuote>(new SimpleQuote(rate)); shared_ptr<Quote> quote (simple); shared_ptr<RateHelper> helper(new FraRateHelper(Handle<Quote>(quote), fraData[i].nExpiry, fraData[i].nMaturity, fraData[i].settlementDays, euribor3m->fixingCalendar(), euribor3m->businessDayConvention(), euribor3m->endOfMonth(), euribor3m->dayCounter())); swap3mHelpers.push_back(helper); } for (Size i = 0; i < LENGTH(eoniaSwapData); i++) { Real rate = 0.01 * eoniaSwapData[i].rate; shared_ptr<SimpleQuote> simple = shared_ptr<SimpleQuote>(new SimpleQuote(rate)); shared_ptr<Quote> quote (simple); Period term = eoniaSwapData[i].n * eoniaSwapData[i].unit; shared_ptr<RateHelper> helper(new OISRateHelper(eoniaSwapData[i].settlementDays, term, Handle<Quote>(quote), eonia)); eoniaHelpers.push_back(helper); } for (Size i = 0; i < LENGTH(swapData); i++) { Real rate = 0.01 * swapData[i].rate; shared_ptr<SimpleQuote> simple = shared_ptr<SimpleQuote>(new SimpleQuote(rate)); shared_ptr<Quote> quote (simple); Period tenor = swapData[i].nIndexUnits * swapData[i].indexUnit; Period term = swapData[i].nTermUnits * swapData[i].termUnit; shared_ptr<RateHelper> helper(new SwapRateHelper( Handle<Quote>(quote), term, vars.calendar, vars.fixedSwapFrequency, vars.fixedSwapConvention, vars.fixedSwapDayCount, euribor3m)); if (tenor == 3*Months) swap3mHelpers.push_back(helper); } shared_ptr<PiecewiseFlatForward> eoniaTS(new PiecewiseFlatForward (vars.today, eoniaHelpers, Actual365Fixed())); shared_ptr<PiecewiseFlatForward> swapTS(new PiecewiseFlatForward (vars.today, swap3mHelpers, Actual365Fixed())); vars.eoniaTermStructure.linkTo(eoniaTS); /* std::cout.setf (std::ios::fixed, std::ios::floatfield); std::cout.setf (std::ios::showpoint); */ // test curve consistency Real tolerance = 1.0e-8; for (Size i = 0; i < LENGTH(eoniaSwapData); i++) { Rate expected = eoniaSwapData[i].rate; Period term = eoniaSwapData[i].n * eoniaSwapData[i].unit; shared_ptr<OvernightIndexedSwap> swap = vars.makeSwap(term, 0.0, 0.0); Rate calculated = 100.0 * swap->fairRate(); Rate error = std::fabs(expected-calculated); if (error>tolerance) BOOST_FAIL("curve inconsistency:" << std::setprecision(10) << "\n swap length: " << term << "\n quoted rate: " << expected << "\n calculated rate: " << calculated << "\n error: " << error << "\n tolerance: " << tolerance); } // zero spread /* std::cout << "zero spread:" << std::endl; std::cout << "years date zero3m/% zero1d/% spread/bp" << std::endl; DayCounter dc = Actual365Fixed(); for (Size i = 1; i <= 10; i++) { Date d = vars.today + i*Years; Rate zero1d = eoniaTS->zeroRate(d, dc, Continuous, Annual,false).rate(); Rate zero3m = swapTS->zeroRate(d, dc, Continuous, Annual,false).rate(); std::cout << std::setw(2) << i << "y " << io::iso_date(d) << " " << std::setprecision(3) << zero3m * 100.0 << " " << zero1d * 100.0 << " " << std::setprecision(1) << (zero3m - zero1d) * 10000.0 << std::endl; } */ }
void BermudanSwaptionTest::testCachedValues() { BOOST_MESSAGE("Testing Bermudan swaption against cached values..."); CommonVars vars; vars.today = Date(15, February, 2002); Settings::instance().evaluationDate() = vars.today; vars.settlement = Date(19, February, 2002); // flat yield term structure impling 1x5 swap at 5% vars.termStructure.linkTo(flatRate(vars.settlement, 0.04875825, Actual365Fixed())); Rate atmRate = vars.makeSwap(0.0)->fairRate(); boost::shared_ptr<VanillaSwap> itmSwap = vars.makeSwap(0.8*atmRate); boost::shared_ptr<VanillaSwap> atmSwap = vars.makeSwap(atmRate); boost::shared_ptr<VanillaSwap> otmSwap = vars.makeSwap(1.2*atmRate); Real a = 0.048696, sigma = 0.0058904; boost::shared_ptr<ShortRateModel> model(new HullWhite(vars.termStructure, a, sigma)); std::vector<Date> exerciseDates; const Leg& leg = atmSwap->fixedLeg(); for (Size i=0; i<leg.size(); i++) { boost::shared_ptr<Coupon> coupon = boost::dynamic_pointer_cast<Coupon>(leg[i]); exerciseDates.push_back(coupon->accrualStartDate()); } boost::shared_ptr<Exercise> exercise(new BermudanExercise(exerciseDates)); boost::shared_ptr<PricingEngine> engine(new TreeSwaptionEngine(model, 50)); #if defined(QL_USE_INDEXED_COUPON) Real itmValue = 42.2413, atmValue = 12.8789, otmValue = 2.4759; #else Real itmValue = 42.2470, atmValue = 12.8826, otmValue = 2.4769; #endif Real tolerance = 1.0e-4; Swaption swaption(itmSwap, exercise); swaption.setPricingEngine(engine); if (std::fabs(swaption.NPV()-itmValue) > tolerance) BOOST_ERROR("failed to reproduce cached in-the-money swaption value:\n" << "calculated: " << swaption.NPV() << "\n" << "expected: " << itmValue); swaption = Swaption(atmSwap, exercise); swaption.setPricingEngine(engine); if (std::fabs(swaption.NPV()-atmValue) > tolerance) BOOST_ERROR("failed to reproduce cached at-the-money swaption value:\n" << "calculated: " << swaption.NPV() << "\n" << "expected: " << atmValue); swaption = Swaption(otmSwap, exercise); swaption.setPricingEngine(engine); if (std::fabs(swaption.NPV()-otmValue) > tolerance) BOOST_ERROR("failed to reproduce cached out-of-the-money " << "swaption value:\n" << "calculated: " << swaption.NPV() << "\n" << "expected: " << otmValue); for (Size j=0; j<exerciseDates.size(); j++) exerciseDates[j] = vars.calendar.adjust(exerciseDates[j]-10); exercise = boost::shared_ptr<Exercise>(new BermudanExercise(exerciseDates)); #if defined(QL_USE_INDEXED_COUPON) itmValue = 42.1917; atmValue = 12.7788; otmValue = 2.4388; #else itmValue = 42.1974; atmValue = 12.7825; otmValue = 2.4399; #endif swaption = Swaption(itmSwap, exercise); swaption.setPricingEngine(engine); if (std::fabs(swaption.NPV()-itmValue) > tolerance) BOOST_ERROR("failed to reproduce cached in-the-money swaption value:\n" << "calculated: " << swaption.NPV() << "\n" << "expected: " << itmValue); swaption = Swaption(atmSwap, exercise); swaption.setPricingEngine(engine); if (std::fabs(swaption.NPV()-atmValue) > tolerance) BOOST_ERROR("failed to reproduce cached at-the-money swaption value:\n" << "calculated: " << swaption.NPV() << "\n" << "expected: " << atmValue); swaption = Swaption(otmSwap, exercise); swaption.setPricingEngine(engine); if (std::fabs(swaption.NPV()-otmValue) > tolerance) BOOST_ERROR("failed to reproduce cached out-of-the-money " << "swaption value:\n" << "calculated: " << swaption.NPV() << "\n" << "expected: " << otmValue); }