void SwaptionTest::testCachedValue() { BOOST_MESSAGE("Testing swaption value against cached value..."); CommonVars vars; vars.today = Date(13, March, 2002); vars.settlement = Date(15, March, 2002); Settings::instance().evaluationDate() = vars.today; vars.termStructure.linkTo(flatRate(vars.settlement, 0.05, Actual365Fixed())); Date exerciseDate = vars.calendar.advance(vars.settlement, 5*Years); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, Days); boost::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(10*Years, vars.index, 0.06) .withEffectiveDate(startDate); boost::shared_ptr<Swaption> swaption = vars.makeSwaption(swap, exerciseDate, 0.20); #ifndef QL_USE_INDEXED_COUPON Real cachedNPV = 0.036418158579; #else Real cachedNPV = 0.036421429684; #endif // FLOATING_POINT_EXCEPTION if (std::fabs(swaption->NPV()-cachedNPV) > 1.0e-12) BOOST_ERROR("failed to reproduce cached swaption value:\n" << QL_FIXED << std::setprecision(12) << "\ncalculated: " << swaption->NPV() << "\nexpected: " << cachedNPV); }
void SwaptionTest::testImpliedVolatility() { BOOST_MESSAGE("Testing implied volatility for swaptions..."); CommonVars vars; Size maxEvaluations = 100; Real tolerance = 1.0e-08; Settlement::Type types[] = { Settlement::Physical, Settlement::Cash }; // test data Rate strikes[] = { 0.02, 0.03, 0.04, 0.05, 0.06, 0.07 }; Volatility vols[] = { 0.01, 0.05, 0.10, 0.20, 0.30, 0.70, 0.90 }; for (Size i=0; i<LENGTH(exercises); i++) { for (Size j=0; j<LENGTH(lengths); j++) { Date exerciseDate = vars.calendar.advance(vars.today,exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays, Days); for (Size t=0; t<LENGTH(strikes); t++) { for (Size k=0; k<LENGTH(type); k++) { boost::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(lengths[j], vars.index, strikes[t]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); for (Size h=0; h<LENGTH(types); h++) { for (Size u=0; u<LENGTH(vols); u++) { boost::shared_ptr<Swaption> swaption = vars.makeSwaption(swap, exerciseDate, vols[u], types[h]); // Black price Real value = swaption->NPV(); Volatility implVol = 0.0; try { implVol = swaption->impliedVolatility(value, vars.termStructure, 0.10, tolerance, maxEvaluations); } catch (std::exception& e) { // couldn't bracket? swaption->setPricingEngine(vars.makeEngine(0.0)); Real value2 = swaption->NPV(); if (std::fabs(value-value2) < tolerance) { // ok, just skip: continue; } // otherwise, report error BOOST_ERROR("implied vol failure: " << exercises[i] << "x" << lengths[j] << " " << type[k] << "\nsettlement: " << types[h] << "\nstrike " << strikes[t] << "\natm level: " << io::rate(swap->fairRate()) << "\nvol: " << io::volatility(vols[u]) << "\nprice: " << value << "\n" << e.what()); } if (std::fabs(implVol-vols[u]) > tolerance) { // the difference might not matter swaption->setPricingEngine(vars.makeEngine(implVol)); Real value2 = swaption->NPV(); if (std::fabs(value-value2) > tolerance) { BOOST_ERROR("implied vol failure: " << exercises[i] << "x" << lengths[j] << " " << type[k] << "\nsettlement: " << types[h] << "\nstrike " << strikes[t] << "\natm level: " << io::rate(swap->fairRate()) << "\nvol: " << io::volatility(vols[u]) << "\nprice: " << value << "\nimplied vol: " << io::volatility(implVol) << "\nimplied price: " << value2); } } } } } } } } }
void SwaptionTest::testCashSettledSwaptions() { BOOST_MESSAGE("Testing cash settled swaptions modified annuity..."); CommonVars vars; Rate strike = 0.05; for (Size i=0; i<LENGTH(exercises); i++) { for (Size j=0; j<LENGTH(lengths); j++) { Date exerciseDate = vars.calendar.advance(vars.today,exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays,Days); Date maturity = vars.calendar.advance(startDate,lengths[j], vars.floatingConvention); Schedule floatSchedule(startDate, maturity, vars.floatingTenor, vars.calendar,vars.floatingConvention, vars.floatingConvention, DateGeneration::Forward, false); // Swap with fixed leg conventions: Business Days = Unadjusted, DayCount = 30/360 Schedule fixedSchedule_u(startDate, maturity, Period(vars.fixedFrequency), vars.calendar, Unadjusted, Unadjusted, DateGeneration::Forward, true); boost::shared_ptr<VanillaSwap> swap_u360( new VanillaSwap(type[0], vars.nominal, fixedSchedule_u,strike,Thirty360(), floatSchedule,vars.index,0.0, vars.index->dayCounter())); // Swap with fixed leg conventions: Business Days = Unadjusted, DayCount = Act/365 boost::shared_ptr<VanillaSwap> swap_u365( new VanillaSwap(type[0],vars.nominal, fixedSchedule_u,strike,Actual365Fixed(), floatSchedule,vars.index,0.0, vars.index->dayCounter())); // Swap with fixed leg conventions: Business Days = Modified Following, DayCount = 30/360 Schedule fixedSchedule_a(startDate,maturity, Period(vars.fixedFrequency), vars.calendar,ModifiedFollowing, ModifiedFollowing, DateGeneration::Forward, true); boost::shared_ptr<VanillaSwap> swap_a360( new VanillaSwap(type[0],vars.nominal, fixedSchedule_a,strike,Thirty360(), floatSchedule,vars.index,0.0, vars.index->dayCounter())); // Swap with fixed leg conventions: Business Days = Modified Following, DayCount = Act/365 boost::shared_ptr<VanillaSwap> swap_a365( new VanillaSwap(type[0],vars.nominal, fixedSchedule_a,strike,Actual365Fixed(), floatSchedule,vars.index,0.0, vars.index->dayCounter())); boost::shared_ptr<PricingEngine> swapEngine( new DiscountingSwapEngine(vars.termStructure)); swap_u360->setPricingEngine(swapEngine); swap_a360->setPricingEngine(swapEngine); swap_u365->setPricingEngine(swapEngine); swap_a365->setPricingEngine(swapEngine); const Leg& swapFixedLeg_u360 = swap_u360->fixedLeg(); const Leg& swapFixedLeg_a360 = swap_a360->fixedLeg(); const Leg& swapFixedLeg_u365 = swap_u365->fixedLeg(); const Leg& swapFixedLeg_a365 = swap_a365->fixedLeg(); // FlatForward curves // FLOATING_POINT_EXCEPTION Handle<YieldTermStructure> termStructure_u360( boost::shared_ptr<YieldTermStructure>( new FlatForward(vars.settlement,swap_u360->fairRate(), Thirty360(),Compounded, vars.fixedFrequency))); Handle<YieldTermStructure> termStructure_a360( boost::shared_ptr<YieldTermStructure>( new FlatForward(vars.settlement,swap_a360->fairRate(), Thirty360(),Compounded, vars.fixedFrequency))); Handle<YieldTermStructure> termStructure_u365( boost::shared_ptr<YieldTermStructure>( new FlatForward(vars.settlement,swap_u365->fairRate(), Actual365Fixed(),Compounded, vars.fixedFrequency))); Handle<YieldTermStructure> termStructure_a365( boost::shared_ptr<YieldTermStructure>( new FlatForward(vars.settlement,swap_a365->fairRate(), Actual365Fixed(),Compounded, vars.fixedFrequency))); // Annuity calculated by swap method fixedLegBPS(). // Fixed leg conventions: Unadjusted, 30/360 Real annuity_u360 = swap_u360->fixedLegBPS() / 0.0001; annuity_u360 = swap_u360->type()==VanillaSwap::Payer ? -annuity_u360 : annuity_u360; // Fixed leg conventions: ModifiedFollowing, act/365 Real annuity_a365 = swap_a365->fixedLegBPS() / 0.0001; annuity_a365 = swap_a365->type()==VanillaSwap::Payer ? -annuity_a365 : annuity_a365; // Fixed leg conventions: ModifiedFollowing, 30/360 Real annuity_a360 = swap_a360->fixedLegBPS() / 0.0001; annuity_a360 = swap_a360->type()==VanillaSwap::Payer ? -annuity_a360 : annuity_a360; // Fixed leg conventions: Unadjusted, act/365 Real annuity_u365 = swap_u365->fixedLegBPS() / 0.0001; annuity_u365 = swap_u365->type()==VanillaSwap::Payer ? -annuity_u365 : annuity_u365; // Calculation of Modified Annuity (cash settlement) // Fixed leg conventions of swap: unadjusted, 30/360 Real cashannuity_u360 = 0.; Size i; for (i=0; i<swapFixedLeg_u360.size(); i++) { cashannuity_u360 += swapFixedLeg_u360[i]->amount()/strike * termStructure_u360->discount( swapFixedLeg_u360[i]->date()); } // Fixed leg conventions of swap: unadjusted, act/365 Real cashannuity_u365 = 0.; for (i=0; i<swapFixedLeg_u365.size(); i++) { cashannuity_u365 += swapFixedLeg_u365[i]->amount()/strike * termStructure_u365->discount( swapFixedLeg_u365[i]->date()); } // Fixed leg conventions of swap: modified following, 30/360 Real cashannuity_a360 = 0.; for (i=0; i<swapFixedLeg_a360.size(); i++) { cashannuity_a360 += swapFixedLeg_a360[i]->amount()/strike * termStructure_a360->discount( swapFixedLeg_a360[i]->date()); } // Fixed leg conventions of swap: modified following, act/365 Real cashannuity_a365 = 0.; for (i=0; i<swapFixedLeg_a365.size(); i++) { cashannuity_a365 += swapFixedLeg_a365[i]->amount()/strike * termStructure_a365->discount( swapFixedLeg_a365[i]->date()); } // Swaptions: underlying swap fixed leg conventions: // unadjusted, 30/360 // Physical settled swaption boost::shared_ptr<Swaption> swaption_p_u360 = vars.makeSwaption(swap_u360,exerciseDate,0.20); Real value_p_u360 = swaption_p_u360->NPV(); // Cash settled swaption boost::shared_ptr<Swaption> swaption_c_u360 = vars.makeSwaption(swap_u360,exerciseDate,0.20, Settlement::Cash); Real value_c_u360 = swaption_c_u360->NPV(); // the NPV's ratio must be equal to annuities ratio Real npv_ratio_u360 = value_c_u360 / value_p_u360; Real annuity_ratio_u360 = cashannuity_u360 / annuity_u360; // Swaptions: underlying swap fixed leg conventions: // modified following, act/365 // Physical settled swaption boost::shared_ptr<Swaption> swaption_p_a365 = vars.makeSwaption(swap_a365,exerciseDate,0.20); Real value_p_a365 = swaption_p_a365->NPV(); // Cash settled swaption boost::shared_ptr<Swaption> swaption_c_a365 = vars.makeSwaption(swap_a365,exerciseDate,0.20, Settlement::Cash); Real value_c_a365 = swaption_c_a365->NPV(); // the NPV's ratio must be equal to annuities ratio Real npv_ratio_a365 = value_c_a365 / value_p_a365; Real annuity_ratio_a365 = cashannuity_a365 / annuity_a365; // Swaptions: underlying swap fixed leg conventions: // modified following, 30/360 // Physical settled swaption boost::shared_ptr<Swaption> swaption_p_a360 = vars.makeSwaption(swap_a360,exerciseDate,0.20); Real value_p_a360 = swaption_p_a360->NPV(); // Cash settled swaption boost::shared_ptr<Swaption> swaption_c_a360 = vars.makeSwaption(swap_a360,exerciseDate,0.20, Settlement::Cash); Real value_c_a360 = swaption_c_a360->NPV(); // the NPV's ratio must be equal to annuities ratio Real npv_ratio_a360 = value_c_a360 / value_p_a360; Real annuity_ratio_a360 = cashannuity_a360 / annuity_a360; // Swaptions: underlying swap fixed leg conventions: // unadjusted, act/365 // Physical settled swaption boost::shared_ptr<Swaption> swaption_p_u365 = vars.makeSwaption(swap_u365,exerciseDate,0.20); Real value_p_u365 = swaption_p_u365->NPV(); // Cash settled swaption boost::shared_ptr<Swaption> swaption_c_u365 = vars.makeSwaption(swap_u365,exerciseDate,0.20, Settlement::Cash); Real value_c_u365 = swaption_c_u365->NPV(); // the NPV's ratio must be equal to annuities ratio Real npv_ratio_u365 = value_c_u365 / value_p_u365; Real annuity_ratio_u365 = cashannuity_u365 / annuity_u365; if (std::fabs(annuity_ratio_u360-npv_ratio_u360)>1e-10 ) { BOOST_ERROR("\n" << " The npv's ratio must be equal to " << " annuities ratio" << "\n" " Swaption " << exercises[i].units() << "y x " << lengths[j].units() << "y" << " (underlying swap fixed leg Unadjusted, 30/360)" << "\n" << " Today : " << vars.today << "\n" << " Settlement date : " << vars.settlement << "\n" << " Exercise date : " << exerciseDate << "\n" << " Swap start date : " << startDate << "\n" << " Swap end date : " << maturity << "\n" << " physical delivered swaption npv : " << value_p_u360 << "\t\t\t" << " annuity : " << annuity_u360 << "\n" << " cash delivered swaption npv : " << value_c_u360 << "\t\t\t" << " annuity : " << cashannuity_u360 << "\n" << " npv ratio : " << npv_ratio_u360 << "\n" << " annuity ratio : " << annuity_ratio_u360 << "\n" << " difference : " << (annuity_ratio_u360-npv_ratio_u360) ); } if (std::fabs(annuity_ratio_a365-npv_ratio_a365)>1e-10) { BOOST_ERROR("\n" << " The npv's ratio must be equal to " << " annuities ratio" << "\n" " Swaption " << exercises[i].units() << "y x " << lengths[j].units() << "y" << " (underlying swap fixed leg Modified Following, act/365" << "\n" << " Today : " << vars.today << "\n" << " Settlement date : " << vars.settlement << "\n" << " Exercise date : " << exerciseDate << "\n" << " Swap start date : " << startDate << "\n" << " Swap end date : " << maturity << "\n" << " physical delivered swaption npv : " << value_p_a365 << "\t\t\t" << " annuity : " << annuity_a365 << "\n" << " cash delivered swaption npv : " << value_c_a365 << "\t\t\t" << " annuity : " << cashannuity_a365 << "\n" << " npv ratio : " << npv_ratio_a365 << "\n" << " annuity ratio : " << annuity_ratio_a365 << "\n" << " difference : " << (annuity_ratio_a365-npv_ratio_a365) ); } if (std::fabs(annuity_ratio_a360-npv_ratio_a360)>1e-10) { BOOST_ERROR("\n" << " The npv's ratio must be equal to " << " annuities ratio" << "\n" " Swaption " << exercises[i].units() << "y x " << lengths[j].units() << "y" << " (underlying swap fixed leg Unadjusted, 30/360)" << "\n" << " Today : " << vars.today << "\n" << " Settlement date : " << vars.settlement << "\n" << " Exercise date : " << exerciseDate << "\n" << " Swap start date : " << startDate << "\n" << " Swap end date : " << maturity << "\n" << " physical delivered swaption npv : " << value_p_a360 << "\t\t\t" << " annuity : " << annuity_a360 << "\n" << " cash delivered swaption npv : " << value_c_a360 << "\t\t\t" << " annuity : " << cashannuity_a360 << "\n" << " npv ratio : " << npv_ratio_a360 << "\n" << " annuity ratio : " << annuity_ratio_a360 << "\n" << " difference : " << (annuity_ratio_a360-npv_ratio_a360) ); } if (std::fabs(annuity_ratio_u365-npv_ratio_u365)>1e-10) { BOOST_ERROR("\n" << " The npv's ratio must be equal to " << " annuities ratio" << "\n" " Swaption " << exercises[i].units() << "y x " << lengths[j].units() << "y" << " (underlying swap fixed leg Unadjusted, act/365)" << "\n" << " Today : " << vars.today << "\n" << " Settlement date : " << vars.settlement << "\n" << " Exercise date : " << exerciseDate << "\n" << " Swap start date : " << startDate << "\n" << " Swap end date : " << maturity << "\n" << " physical delivered swaption npv : " << value_p_u365 << "\t\t\t" << " annuity : " << annuity_u365 << "\n" << " cash delivered swaption npv : " << value_c_u365 << "\t\t\t" << " annuity : " << cashannuity_u365 << "\n" << " npv ratio : " << npv_ratio_u365 << "\n" << " annuity ratio : " << annuity_ratio_u365 << "\n" << " difference : " << (annuity_ratio_u365-npv_ratio_u365) ); } } } }
void SwaptionTest::testVega() { BOOST_MESSAGE("Testing swaption vega..."); CommonVars vars; Settlement::Type types[] = { Settlement::Physical, Settlement::Cash }; Rate strikes[] = { 0.03, 0.04, 0.05, 0.06, 0.07 }; Volatility vols[] = { 0.01, 0.20, 0.30, 0.70, 0.90 }; Volatility shift = 1e-8; for (Size i=0; i<LENGTH(exercises); i++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays*Days); for (Size j=0; j<LENGTH(lengths); j++) { for (Size t=0; t<LENGTH(strikes); t++) { for (Size h=0; h<LENGTH(type); h++) { boost::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(lengths[j], vars.index, strikes[t]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[h]); for (Size u=0; u<LENGTH(vols); u++) { boost::shared_ptr<Swaption> swaption = vars.makeSwaption(swap, exerciseDate, vols[u], types[h]); // FLOATING_POINT_EXCEPTION boost::shared_ptr<Swaption> swaption1 = vars.makeSwaption(swap, exerciseDate, vols[u]-shift, types[h]); boost::shared_ptr<Swaption> swaption2 = vars.makeSwaption(swap, exerciseDate, vols[u]+shift, types[h]); Real swaptionNPV = swaption->NPV(); Real numericalVegaPerPoint = (swaption2->NPV()-swaption1->NPV())/(200.0*shift); // check only relevant vega if (numericalVegaPerPoint/swaptionNPV>1.0e-7) { Real analyticalVegaPerPoint = swaption->result<Real>("vega")/100.0; Real discrepancy = std::fabs(analyticalVegaPerPoint - numericalVegaPerPoint); discrepancy /= numericalVegaPerPoint; Real tolerance = 0.015; if (discrepancy > tolerance) BOOST_FAIL("failed to compute swaption vega:" << "\n option tenor: " << exercises[i] << "\n volatility: " << io::rate(vols[u]) << "\n option type: " << swaption->type() << "\n swap tenor: " << lengths[j] << "\n strike: " << io::rate(strikes[t]) << "\n settlement: " << types[h] << "\n nominal: " << swaption->underlyingSwap()->nominal() << "\n npv: " << swaptionNPV << "\n calculated vega: " << analyticalVegaPerPoint << "\n expected vega: " << numericalVegaPerPoint << "\n discrepancy: " << io::rate(discrepancy) << "\n tolerance: " << io::rate(tolerance)); } } } } } } }
void SwaptionTest::testSpreadTreatment() { BOOST_MESSAGE("Testing swaption treatment of spread..."); CommonVars vars; Spread spreads[] = { -0.002, -0.001, 0.0, 0.001, 0.002 }; for (Size i=0; i<LENGTH(exercises); i++) { for (Size j=0; j<LENGTH(lengths); j++) { for (Size k=0; k<LENGTH(type); k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays,Days); for (Size l=0; l<LENGTH(spreads); l++) { boost::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(lengths[j], vars.index, 0.06) .withEffectiveDate(startDate) .withFloatingLegSpread(spreads[l]) .withType(type[k]); // FLOATING_POINT_EXCEPTION Spread correction = spreads[l] * swap->floatingLegBPS() / swap->fixedLegBPS(); boost::shared_ptr<VanillaSwap> equivalentSwap = MakeVanillaSwap(lengths[j], vars.index, 0.06+correction) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); boost::shared_ptr<Swaption> swaption1 = vars.makeSwaption(swap,exerciseDate,0.20); boost::shared_ptr<Swaption> swaption2 = vars.makeSwaption(equivalentSwap,exerciseDate,0.20); boost::shared_ptr<Swaption> swaption1_cash = vars.makeSwaption(swap,exerciseDate,0.20, Settlement::Cash); boost::shared_ptr<Swaption> swaption2_cash = vars.makeSwaption(equivalentSwap,exerciseDate,0.20, Settlement::Cash); if (std::fabs(swaption1->NPV()-swaption2->NPV()) > 1.0e-6) BOOST_ERROR("wrong spread treatment:" << "\nexercise: " << exerciseDate << "\nlength: " << lengths[j] << "\ntype " << type[k] << "\nspread: " << io::rate(spreads[l]) << "\noriginal swaption value: " << swaption1->NPV() << "\nequivalent swaption value: " << swaption2->NPV()); if (std::fabs(swaption1_cash->NPV()-swaption2_cash->NPV()) > 1.0e-6) BOOST_ERROR("wrong spread treatment:" << "\nexercise date: " << exerciseDate << "\nlength: " << lengths[j] << "\npay " << (type[k] ? "fixed" : "floating") << "\nspread: " << io::rate(spreads[l]) << "\nvalue of original swaption: " << swaption1_cash->NPV() << "\nvalue of equivalent swaption: " << swaption2_cash->NPV()); } } } } }
void SwaptionTest::testSpreadDependency() { BOOST_MESSAGE("Testing swaption dependency on spread..."); CommonVars vars; Spread spreads[] = { -0.002, -0.001, 0.0, 0.001, 0.002 }; for (Size i=0; i<LENGTH(exercises); i++) { for (Size j=0; j<LENGTH(lengths); j++) { for (Size k=0; k<LENGTH(type); k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays,Days); // store the results for different rates... std::vector<Real> values; std::vector<Real> values_cash; for (Size l=0; l<LENGTH(spreads); l++) { boost::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(lengths[j], vars.index, 0.06) .withEffectiveDate(startDate) .withFloatingLegSpread(spreads[l]) .withType(type[k]); boost::shared_ptr<Swaption> swaption = vars.makeSwaption(swap,exerciseDate,0.20); // FLOATING_POINT_EXCEPTION values.push_back(swaption->NPV()); boost::shared_ptr<Swaption> swaption_cash = vars.makeSwaption(swap,exerciseDate,0.20, Settlement::Cash); values_cash.push_back(swaption_cash->NPV()); } // and check that they go the right way if (type[k]==VanillaSwap::Payer) { std::vector<Real>::iterator it = std::adjacent_find(values.begin(), values.end(), std::greater<Real>()); if (it != values.end()) { Size n = it - values.begin(); BOOST_ERROR("NPV is decreasing with the spread " << "in a payer swaption (physical delivered):" << "\nexercise date: " << exerciseDate << "\nlength: " << lengths[j] << "\nvalue: " << values[n ] << " for spread: " << io::rate(spreads[n]) << "\nvalue: " << values[n+1] << " for spread: " << io::rate(spreads[n+1])); } std::vector<Real>::iterator it_cash = std::adjacent_find(values_cash.begin(), values_cash.end(), std::greater<Real>()); if (it_cash != values_cash.end()) { Size n = it_cash - values_cash.begin(); BOOST_ERROR("NPV is decreasing with the spread " << "in a payer swaption (cash delivered):" << "\nexercise date: " << exerciseDate << "\nlength: " << lengths[j] << "\nvalue: " << values_cash[n ] << " for spread: " << io::rate(spreads[n]) << "\nvalue: " << values_cash[n+1] << " for spread: " << io::rate(spreads[n+1])); } } else { std::vector<Real>::iterator it = std::adjacent_find(values.begin(), values.end(), std::less<Real>()); if (it != values.end()) { Size n = it - values.begin(); BOOST_ERROR("NPV is increasing with the spread " << "in a receiver swaption (physical delivered):" "\nexercise date: " << exerciseDate << "\nlength: " << lengths[j] << "\nvalue: " << values[n ] << " for spread: " << io::rate(spreads[n]) << "\nvalue: " << values[n+1] << " for spread: " << io::rate(spreads[n+1])); } std::vector<Real>::iterator it_cash = std::adjacent_find(values_cash.begin(), values_cash.end(), std::less<Real>()); if (it_cash != values_cash.end()) { Size n = it_cash - values_cash.begin(); BOOST_ERROR("NPV is increasing with the spread " << "in a receiver swaption (cash delivered):" "\nexercise date: " << exerciseDate << "\nlength: " << lengths[j] << "\nvalue: " << values_cash[n ] << " for spread: " << io::rate(spreads[n]) << "\nvalue: " << values_cash[n+1] << " for spread: " << io::rate(spreads[n+1])); } } } } } }
void SwaptionTest::testStrikeDependency() { BOOST_MESSAGE("Testing swaption dependency on strike..."); CommonVars vars; Rate strikes[] = { 0.03, 0.04, 0.05, 0.06, 0.07 }; for (Size i=0; i<LENGTH(exercises); i++) { for (Size j=0; j<LENGTH(lengths); j++) { for (Size k=0; k<LENGTH(type); k++) { Date exerciseDate = vars.calendar.advance(vars.today, exercises[i]); Date startDate = vars.calendar.advance(exerciseDate, vars.settlementDays,Days); // store the results for different rates... std::vector<Real> values; std::vector<Real> values_cash; Volatility vol = 0.20; for (Size l=0; l<LENGTH(strikes); l++) { boost::shared_ptr<VanillaSwap> swap = MakeVanillaSwap(lengths[j], vars.index, strikes[l]) .withEffectiveDate(startDate) .withFloatingLegSpread(0.0) .withType(type[k]); boost::shared_ptr<Swaption> swaption = vars.makeSwaption(swap,exerciseDate,vol); // FLOATING_POINT_EXCEPTION values.push_back(swaption->NPV()); boost::shared_ptr<Swaption> swaption_cash = vars.makeSwaption(swap,exerciseDate,vol, Settlement::Cash); values_cash.push_back(swaption_cash->NPV()); } // and check that they go the right way if (type[k]==VanillaSwap::Payer) { std::vector<Real>::iterator it = std::adjacent_find(values.begin(), values.end(), std::less<Real>()); if (it != values.end()) { Size n = it - values.begin(); BOOST_ERROR("NPV of Payer swaption with delivery settlement" "is increasing with the strike:" << "\noption tenor: " << exercises[i] << "\noption date: " << exerciseDate << "\nvolatility: " << io::rate(vol) << "\nswap tenor: " << lengths[j] << "\nvalue: " << values[n ] <<" at strike: " << io::rate(strikes[n ]) << "\nvalue: " << values[n+1] << " at strike: " << io::rate(strikes[n+1])); } std::vector<Real>::iterator it_cash = std::adjacent_find(values_cash.begin(), values_cash.end(), std::less<Real>()); if (it_cash != values_cash.end()) { Size n = it_cash - values_cash.begin(); BOOST_ERROR("NPV of Payer swaption with cash settlement" "is increasing with the strike:" << "\noption tenor: " << exercises[i] << "\noption date: " << exerciseDate << "\nvolatility: " << io::rate(vol) << "\nswap tenor: " << lengths[j] << "\nvalue: " << values_cash[n ] << " at strike: " << io::rate(strikes[n ]) << "\nvalue: " << values_cash[n+1] << " at strike: " << io::rate(strikes[n+1])); } } else { std::vector<Real>::iterator it = std::adjacent_find(values.begin(), values.end(), std::greater<Real>()); if (it != values.end()) { Size n = it - values.begin(); BOOST_ERROR("NPV of Receiver swaption with delivery settlement" "is increasing with the strike:" << "\noption tenor: " << exercises[i] << "\noption date: " << exerciseDate << "\nvolatility: " << io::rate(vol) << "\nswap tenor: " << lengths[j] << "\nvalue: " << values[n ] << " at strike: " << io::rate(strikes[n ]) << "\nvalue: " << values[n+1] << " at strike: " << io::rate(strikes[n+1])); } std::vector<Real>::iterator it_cash = std::adjacent_find(values_cash.begin(), values_cash.end(), std::greater<Real>()); if (it_cash != values_cash.end()) { Size n = it_cash - values_cash.begin(); BOOST_ERROR("NPV of Receiver swaption with cash settlement" "is increasing with the strike:" << "\noption tenor: " << exercises[i] << "\noption date: " << exerciseDate << "\nvolatility: " << io::rate(vol) << "\nswap tenor: " << lengths[j] << "\nvalue: " << values_cash[n ] << " at strike: " << io::rate(strikes[n ]) << "\nvalue: " << values_cash[n+1] << " at strike: " << io::rate(strikes[n+1])); } } } } } }