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));
            }
    }
}
Example #2
0
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));
}
Example #3
0
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));
    }
  }
}