void OptionletStripperTest::testTermVolatilityStripping1() { BOOST_TEST_MESSAGE( "Testing forward/forward vol stripping from non-flat term " "vol surface using optionletstripper1..."); CommonVars vars; vars.setCapFloorTermVolSurface(); shared_ptr<IborIndex> iborIndex(new Euribor6M(vars.yieldTermStructure)); boost::shared_ptr<OptionletStripper> optionletStripper1(new OptionletStripper1(vars.capFloorVolSurface, iborIndex, Null<Rate>(), vars.accuracy)); boost::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter = boost::shared_ptr<StrippedOptionletAdapter>(new StrippedOptionletAdapter(optionletStripper1)); Handle<OptionletVolatilityStructure> vol(strippedOptionletAdapter); vol->enableExtrapolation(); boost::shared_ptr<BlackCapFloorEngine> strippedVolEngine(new BlackCapFloorEngine(vars.yieldTermStructure, vol)); boost::shared_ptr<CapFloor> cap; for (Size tenorIndex=0; tenorIndex<vars.optionTenors.size(); ++tenorIndex) { for (Size strikeIndex=0; strikeIndex<vars.strikes.size(); ++strikeIndex) { cap = MakeCapFloor(CapFloor::Cap, vars.optionTenors[tenorIndex], iborIndex, vars.strikes[strikeIndex], 0*Days) .withPricingEngine(strippedVolEngine); Real priceFromStrippedVolatility = cap->NPV(); boost::shared_ptr<PricingEngine> blackCapFloorEngineConstantVolatility(new BlackCapFloorEngine(vars.yieldTermStructure, vars.termV[tenorIndex][strikeIndex])); cap->setPricingEngine(blackCapFloorEngineConstantVolatility); Real priceFromConstantVolatility = cap->NPV(); Real error = std::fabs(priceFromStrippedVolatility - priceFromConstantVolatility); if (error>vars.tolerance) BOOST_FAIL("\noption tenor: " << vars.optionTenors[tenorIndex] << "\nstrike: " << io::rate(vars.strikes[strikeIndex]) << "\nstripped vol price: " << io::rate(priceFromStrippedVolatility) << "\nconstant vol price: " << io::rate(priceFromConstantVolatility) << "\nerror: " << io::rate(error) << "\ntolerance: " << io::rate(vars.tolerance)); } } }
void OptionletStripperTest::testSwitchStrike() { BOOST_TEST_MESSAGE("Testing switch strike level and recalibration of level " "in case of curve relinking..."); CommonVars vars; Settings::instance().evaluationDate() = Date(28, October, 2013); vars.setCapFloorTermVolSurface(); RelinkableHandle< YieldTermStructure > yieldTermStructure; yieldTermStructure.linkTo(boost::shared_ptr< FlatForward >( new FlatForward(0, vars.calendar, 0.03, vars.dayCounter))); shared_ptr< IborIndex > iborIndex(new Euribor6M(yieldTermStructure)); boost::shared_ptr< OptionletStripper1 > optionletStripper1( new OptionletStripper1(vars.capFloorVolSurface, iborIndex, Null< Rate >(), vars.accuracy)); #if defined(QL_USE_INDEXED_COUPON) Real expected = 0.02981258; #else Real expected = 0.02981223; #endif Real error = std::fabs(optionletStripper1->switchStrike() - expected); if (error > vars.tolerance) BOOST_FAIL("\nSwitchstrike not correctly computed: " << "\nexpected switch strike: " << io::rate(expected) << "\ncomputed switch strike: " << io::rate(optionletStripper1->switchStrike()) << "\nerror: " << io::rate(error) << "\ntolerance: " << io::rate(vars.tolerance)); yieldTermStructure.linkTo(boost::shared_ptr< FlatForward >( new FlatForward(0, vars.calendar, 0.05, vars.dayCounter))); #if defined(QL_USE_INDEXED_COUPON) expected = 0.0499381; #else expected = 0.0499371; #endif error = std::fabs(optionletStripper1->switchStrike() - expected); if (error > vars.tolerance) BOOST_FAIL("\nSwitchstrike not correctly computed: " << "\nexpected switch strike: " << io::rate(expected) << "\ncomputed switch strike: " << io::rate(optionletStripper1->switchStrike()) << "\nerror: " << io::rate(error) << "\ntolerance: " << io::rate(vars.tolerance)); }
void OptionletStripperTest::testTermVolatilityStripping2() { BOOST_TEST_MESSAGE( "Testing forward/forward vol stripping from non-flat term vol " "surface using OptionletStripper2 class..."); CommonVars vars; Settings::instance().evaluationDate() = Date::todaysDate(); vars.setCapFloorTermVolCurve(); vars.setCapFloorTermVolSurface(); shared_ptr<IborIndex> iborIndex(new Euribor6M(vars.yieldTermStructure)); // optionletstripper1 boost::shared_ptr<OptionletStripper1> optionletStripper1(new OptionletStripper1(vars.capFloorVolSurface, iborIndex, Null<Rate>(), vars.accuracy)); boost::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter1 = boost::shared_ptr<StrippedOptionletAdapter>(new StrippedOptionletAdapter(optionletStripper1)); Handle<OptionletVolatilityStructure> vol1(strippedOptionletAdapter1); vol1->enableExtrapolation(); // optionletstripper2 boost::shared_ptr<OptionletStripper> optionletStripper2(new OptionletStripper2(optionletStripper1, vars.capFloorVolCurve)); boost::shared_ptr<StrippedOptionletAdapter> strippedOptionletAdapter2(new StrippedOptionletAdapter(optionletStripper2)); Handle<OptionletVolatilityStructure> vol2(strippedOptionletAdapter2); vol2->enableExtrapolation(); // consistency check: diff(stripped vol1-stripped vol2) for (Size strikeIndex=0; strikeIndex<vars.strikes.size(); ++strikeIndex) { for (Size tenorIndex=0; tenorIndex<vars.optionTenors.size(); ++tenorIndex) { Volatility strippedVol1 = vol1->volatility(vars.optionTenors[tenorIndex], vars.strikes[strikeIndex], true); Volatility strippedVol2 = vol2->volatility(vars.optionTenors[tenorIndex], vars.strikes[strikeIndex], true); // vol from flat vol surface (for comparison only) Volatility flatVol = vars.capFloorVolSurface->volatility(vars.optionTenors[tenorIndex], vars.strikes[strikeIndex], true); Real error = std::fabs(strippedVol1-strippedVol2); if (error>vars.tolerance) BOOST_FAIL("\noption tenor: " << vars.optionTenors[tenorIndex] << "\nstrike: " << io::rate(vars.strikes[strikeIndex]) << "\nstripped vol1: " << io::rate(strippedVol1) << "\nstripped vol2: " << io::rate(strippedVol2) << "\nflat vol: " << io::rate(flatVol) << "\nerror: " << io::rate(error) << "\ntolerance: " << io::rate(vars.tolerance)); } } }