Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Namespaces | Typedefs | Functions
piecewiseoptionletstripper.cpp File Reference
#include <boost/assign.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/variant.hpp>
#include <test/capfloormarketdata.hpp>
#include <test/toplevelfixture.hpp>
#include <test/yieldcurvemarketdata.hpp>
#include <ql/instruments/makecapfloor.hpp>
#include <ql/pricingengines/capfloor/bacheliercapfloorengine.hpp>
#include <ql/pricingengines/capfloor/blackcapfloorengine.hpp>
#include <qle/math/flatextrapolation.hpp>
#include <qle/termstructures/capfloorhelper.hpp>
#include <qle/termstructures/capfloortermvolcurve.hpp>
#include <qle/termstructures/optionletstripperwithatm.hpp>
#include <qle/termstructures/piecewiseoptionletstripper.hpp>
#include <qle/termstructures/strippedoptionletadapter.hpp>

Go to the source code of this file.

Namespaces

namespace  boost
 
namespace  boost::test_tools
 
namespace  boost::test_tools::tt_detail
 

Typedefs

typedef QuantLib::BootstrapHelper< QuantLib::OptionletVolatilityStructure > helper
 
using TermVolSurface = QuantExt::CapFloorTermVolSurfaceExact
 

Functions

 BOOST_DATA_TEST_CASE_F (CommonVars, testPiecewiseOptionletSurfaceStripping, bdata::make(volatilityTypes) *bdata::make(timeInterpolationTypes) *bdata::make(smileInterpolationTypes) *bdata::make(flatFirstPeriodValues) *bdata::make(isMovingValues) *bdata::make(vsInterpMethods) *bdata::make(interpOnOptionletValues) *bdata::make(addAtmValues), volatilityType, timeInterp, smileInterp, flatFirstPeriod, isMoving, vsInterpMethod, interpOnOptionlet, addAtm)
 
 BOOST_FIXTURE_TEST_CASE (testExtrapolation, CommonVars)
 
 BOOST_FIXTURE_TEST_CASE (testCachedLinearFlat, CommonVars)
 
 BOOST_FIXTURE_TEST_CASE (testChangingCapFloorSurface, CommonVars)
 

Typedef Documentation

◆ helper

typedef QuantLib::BootstrapHelper<QuantLib::OptionletVolatilityStructure> helper

Definition at line 45 of file piecewiseoptionletstripper.cpp.

◆ TermVolSurface

Definition at line 46 of file piecewiseoptionletstripper.cpp.

Function Documentation

◆ BOOST_DATA_TEST_CASE_F()

BOOST_DATA_TEST_CASE_F ( CommonVars  ,
testPiecewiseOptionletSurfaceStripping  ,
bdata::make(volatilityTypes) *bdata::make(timeInterpolationTypes) *bdata::make(smileInterpolationTypes) *bdata::make(flatFirstPeriodValues) *bdata::make(isMovingValues) *bdata::make(vsInterpMethods) *bdata::make(interpOnOptionletValues) *bdata::make(addAtmValues)  ,
volatilityType  ,
timeInterp  ,
smileInterp  ,
flatFirstPeriod  ,
isMoving  ,
vsInterpMethod  ,
interpOnOptionlet  ,
addAtm   
)

Definition at line 346 of file piecewiseoptionletstripper.cpp.

352 {
353
354 BOOST_TEST_MESSAGE("Testing piecewise optionlet stripping of cap floor surface");
355
356 BOOST_TEST_MESSAGE("Test inputs are:");
357 BOOST_TEST_MESSAGE(" Input volatility type:" << volatilityType);
358 BOOST_TEST_MESSAGE(" Time Interpolation: " << to_string(timeInterp));
359 BOOST_TEST_MESSAGE(" Smile Interpolation: " << to_string(smileInterp));
360 BOOST_TEST_MESSAGE(" Flat first period: " << boolalpha << flatFirstPeriod);
361 BOOST_TEST_MESSAGE(" Floating reference date: " << boolalpha << isMoving);
362 BOOST_TEST_MESSAGE(" Cap floor term interpolation: " << vsInterpMethod);
363 BOOST_TEST_MESSAGE(" Interpolate on optionlets: " << boolalpha << interpOnOptionlet);
364 BOOST_TEST_MESSAGE(" Add in ATM curve: " << boolalpha << addAtm);
365
366 // Create the piecewise optionlet stripper from the surface and wrap in an adapter
367 Handle<OptionletVolatilityStructure> ovs;
368 switch (timeInterp.which()) {
369 case 0:
370 if (smileInterp.which() == 0) {
371 ovs = createOvs<Linear, Linear>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
372 interpOnOptionlet, addAtm);
373 } else if (smileInterp.which() == 2) {
374 ovs = createOvs<Linear, LinearFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
375 interpOnOptionlet, addAtm);
376 } else if (smileInterp.which() == 3) {
377 ovs = createOvs<Linear, Cubic>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod, interpOnOptionlet,
378 addAtm);
379 } else if (smileInterp.which() == 4) {
380 ovs = createOvs<Linear, CubicFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
381 interpOnOptionlet, addAtm);
382 } else {
383 BOOST_FAIL("Unexpected smile interpolation type");
384 }
385 break;
386 case 1:
387 if (smileInterp.which() == 0) {
388 ovs = createOvs<BackwardFlat, Linear>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
389 interpOnOptionlet, addAtm);
390 } else if (smileInterp.which() == 2) {
391 ovs = createOvs<BackwardFlat, LinearFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
392 interpOnOptionlet, addAtm);
393 } else if (smileInterp.which() == 3) {
394 ovs = createOvs<BackwardFlat, Cubic>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
395 interpOnOptionlet, addAtm);
396 } else if (smileInterp.which() == 4) {
397 ovs = createOvs<BackwardFlat, CubicFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
398 interpOnOptionlet, addAtm);
399 } else {
400 BOOST_FAIL("Unexpected smile interpolation type");
401 }
402 break;
403 case 2:
404 if (smileInterp.which() == 0) {
405 ovs = createOvs<LinearFlat, Linear>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
406 interpOnOptionlet, addAtm);
407 } else if (smileInterp.which() == 2) {
408 ovs = createOvs<LinearFlat, LinearFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
409 interpOnOptionlet, addAtm);
410 } else if (smileInterp.which() == 3) {
411 ovs = createOvs<LinearFlat, Cubic>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
412 interpOnOptionlet, addAtm);
413 } else if (smileInterp.which() == 4) {
414 ovs = createOvs<LinearFlat, CubicFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
415 interpOnOptionlet, addAtm);
416 } else {
417 BOOST_FAIL("Unexpected smile interpolation type");
418 }
419 break;
420 case 3:
421 if (smileInterp.which() == 0) {
422 ovs = createOvs<Cubic, Linear>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod, interpOnOptionlet,
423 addAtm);
424 } else if (smileInterp.which() == 2) {
425 ovs = createOvs<Cubic, LinearFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
426 interpOnOptionlet, addAtm);
427 } else if (smileInterp.which() == 3) {
428 ovs = createOvs<Cubic, Cubic>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod, interpOnOptionlet,
429 addAtm);
430 } else if (smileInterp.which() == 4) {
431 ovs = createOvs<Cubic, CubicFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
432 interpOnOptionlet, addAtm);
433 } else {
434 BOOST_FAIL("Unexpected smile interpolation type");
435 }
436 break;
437 case 4:
438 if (smileInterp.which() == 0) {
439 ovs = createOvs<CubicFlat, Linear>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
440 interpOnOptionlet, addAtm);
441 } else if (smileInterp.which() == 2) {
442 ovs = createOvs<CubicFlat, LinearFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
443 interpOnOptionlet, addAtm);
444 } else if (smileInterp.which() == 3) {
445 ovs = createOvs<CubicFlat, Cubic>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
446 interpOnOptionlet, addAtm);
447 } else if (smileInterp.which() == 4) {
448 ovs = createOvs<CubicFlat, CubicFlat>(volatilityType, flatFirstPeriod, isMoving, vsInterpMethod,
449 interpOnOptionlet, addAtm);
450 } else {
451 BOOST_FAIL("Unexpected smile interpolation type");
452 }
453 break;
454 default:
455 BOOST_FAIL("Unexpected time interpolation type");
456 }
457
458 // Price all of the input surface instruments using the cap floor term volatilities and again with the optionlet
459 // volatilities and check that the NPVs match
460 Handle<YieldTermStructure> discount = testYieldCurves.discountEonia;
461 QuantLib::ext::shared_ptr<CapFloor> capFloor;
462
463 for (Size i = 0; i < testVols.tenors.size(); i++) {
464
465 for (Size j = 0; j < testVols.strikes.size(); j++) {
466
467 // Create the OTM cap floor instrument that we will price
468 capFloor = MakeCapFloor(CapFloor::Cap, testVols.tenors[i], iborIndex, testVols.strikes[j]);
469 Rate atm = capFloor->atmRate(**discount);
470 if (testVols.strikes[j] < atm) {
471 capFloor = MakeCapFloor(CapFloor::Floor, testVols.tenors[i], iborIndex, testVols.strikes[j]);
472 }
473
474 // Price the instrument using the flat term volatility
475 Volatility flatVol;
476 if (volatilityType == ShiftedLognormal) {
477 flatVol = testVols.slnVols_1[i][j];
478 capFloor->setPricingEngine(
479 QuantLib::ext::make_shared<BlackCapFloorEngine>(discount, flatVol, dayCounter, testVols.shift_1));
480 } else {
481 flatVol = testVols.nVols[i][j];
482 capFloor->setPricingEngine(QuantLib::ext::make_shared<BachelierCapFloorEngine>(discount, flatVol, dayCounter));
483 }
484 Real flatNpv = capFloor->NPV();
485
486 // Price the instrument using the stripped (Normal) optionlet surface
487 capFloor->setPricingEngine(QuantLib::ext::make_shared<BachelierCapFloorEngine>(discount, ovs));
488 Real strippedNpv = capFloor->NPV();
489
490 // Check that the difference is within the tolerance
491 Real diff = fabs(flatNpv - strippedNpv);
492 BOOST_CHECK_SMALL(diff, tolerance);
493
494 BOOST_TEST_MESSAGE(" (Cap/Floor, Tenor, Strike, Volatility, Flat NPV, Stripped NPV, Flat - Stripped) = ("
495 << capFloor->type() << ", " << testVols.tenors[i] << ", " << testVols.strikes[j] << ", "
496 << flatVol << ", " << flatNpv << ", " << strippedNpv << ", " << diff << ")");
497 }
498 }
499
500 // If we have added in ATM, test the ATM value also
501 if (addAtm) {
502
503 for (Size i = 0; i < testVols.atmTenors.size(); i++) {
504
505 // Create the ATM cap (with a dummy strike first)
506 capFloor = MakeCapFloor(CapFloor::Cap, testVols.atmTenors[i], iborIndex, 0.01);
507 Rate atm = capFloor->atmRate(**discount);
508 capFloor = MakeCapFloor(CapFloor::Cap, testVols.atmTenors[i], iborIndex, atm);
509
510 // Price the instrument using the flat term volatility
511 Volatility flatVol;
512 if (volatilityType == ShiftedLognormal) {
513 flatVol = testVols.slnAtmVols_1[i];
514 capFloor->setPricingEngine(
515 QuantLib::ext::make_shared<BlackCapFloorEngine>(discount, flatVol, dayCounter, testVols.shift_1));
516 } else {
517 flatVol = testVols.nAtmVols[i];
518 capFloor->setPricingEngine(QuantLib::ext::make_shared<BachelierCapFloorEngine>(discount, flatVol, dayCounter));
519 }
520 Real flatNpv = capFloor->NPV();
521
522 // Price the instrument using the stripped (Normal) optionlet surface
523 capFloor->setPricingEngine(QuantLib::ext::make_shared<BachelierCapFloorEngine>(discount, ovs));
524 Real strippedNpv = capFloor->NPV();
525
526 // Check that the difference is within the tolerance
527 Real diff = fabs(flatNpv - strippedNpv);
528 BOOST_CHECK_SMALL(diff, tolerance);
529
530 BOOST_TEST_MESSAGE(" (Cap/Floor, Tenor, Strike, Volatility, Flat NPV, Stripped NPV, Flat - Stripped) = ("
531 << capFloor->type() << ", " << testVols.atmTenors[i] << ", ATM [" << atm << "], "
532 << flatVol << ", " << flatNpv << ", " << strippedNpv << ", " << diff << ")");
533 }
534 }
535}

◆ BOOST_FIXTURE_TEST_CASE() [1/3]

BOOST_FIXTURE_TEST_CASE ( testExtrapolation  ,
CommonVars   
)

Definition at line 537 of file piecewiseoptionletstripper.cpp.

537 {
538
539 BOOST_TEST_MESSAGE("Testing extrapolation settings");
540
541 // A shift of 1bp that will be used below
542 Real shift = 0.001;
543
544 // Pick one configuration and check that extrapolation works as expected
545 Handle<OptionletVolatilityStructure> ovs =
546 createOvs<LinearFlat, LinearFlat>(Normal, true, false, TermVolSurface::Bilinear, true, false);
547
548 // Boundaries
549 Date maxDate = ovs->maxDate();
550 Rate minStrike = ovs->minStrike();
551 Rate maxStrike = ovs->maxStrike();
552
553 // Trivial check
554 BOOST_REQUIRE(maxStrike > minStrike);
555
556 // Asking for vol before reference date throws
557 Date testDate = referenceDate - 1 * Days;
558 Rate testStrike = (maxStrike + minStrike) / 2;
559 BOOST_CHECK_THROW(ovs->volatility(testDate, testStrike, false), Error);
560 BOOST_CHECK_THROW(ovs->volatility(testDate, testStrike, true), Error);
561
562 // Check that asking for a volatility within the boundary does not throw
563 testDate = referenceDate + 1 * Days;
564 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, false));
565
566 testDate = maxDate - 1 * Days;
567 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, false));
568
569 // Check that asking for a volatility outside the boundary throws
570 testDate = maxDate + 1 * Days;
571 BOOST_CHECK_THROW(ovs->volatility(testDate, testStrike, false), Error);
572
573 testDate = referenceDate + 1 * Days;
574 testStrike = minStrike - shift;
575 BOOST_CHECK_THROW(ovs->volatility(testDate, testStrike, false), Error);
576
577 testStrike = maxStrike + shift;
578 BOOST_CHECK_THROW(ovs->volatility(testDate, testStrike, false), Error);
579
580 // Check that asking for a volatility outside the boundary, with explicit extrapolation on, does not throw
581 testDate = maxDate + 1 * Days;
582 testStrike = (maxStrike + minStrike) / 2;
583 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, true));
584
585 testDate = referenceDate + 1 * Days;
586 testStrike = minStrike - shift;
587 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, true));
588
589 testStrike = maxStrike + shift;
590 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, true));
591
592 // Check that asking for a volatility outside the boundary, after turning on extrapolation, does not throw
593 ovs->enableExtrapolation();
594
595 testDate = maxDate + 1 * Days;
596 testStrike = (maxStrike + minStrike) / 2;
597 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, false));
598
599 testDate = referenceDate + 1 * Days;
600 testStrike = minStrike - shift;
601 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, false));
602
603 testStrike = maxStrike + shift;
604 BOOST_CHECK_NO_THROW(ovs->volatility(testDate, testStrike, false));
605}

◆ BOOST_FIXTURE_TEST_CASE() [2/3]

BOOST_FIXTURE_TEST_CASE ( testCachedLinearFlat  ,
CommonVars   
)

Definition at line 608 of file piecewiseoptionletstripper.cpp.

608 {
609
610 BOOST_TEST_MESSAGE("Testing against cached optionlet volatilities with LinearFlat time and smile interpolation");
611
612 // Create the cap floor term vol surface
613 QuantLib::ext::shared_ptr<TermVolSurface> cfts =
614 QuantLib::ext::make_shared<TermVolSurface>(referenceDate, calendar, bdc, testVols.tenors, testVols.strikes,
615 testVols.nVols, dayCounter, TermVolSurface::Bilinear);
616
617 // Create the piecewise optionlet stripper
618 QuantLib::ext::shared_ptr<QuantExt::OptionletStripper> pwos = QuantLib::ext::make_shared<PiecewiseOptionletStripper<LinearFlat> >(
619 cfts, iborIndex, testYieldCurves.discountEonia, true, Normal, 0.0, Normal);
620
621 // Create the OptionletVolatilityStructure
622 Handle<OptionletVolatilityStructure> ovs = Handle<OptionletVolatilityStructure>(
623 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, LinearFlat> >(referenceDate, pwos));
624 ovs->enableExtrapolation();
625
626 // Check optionlet fixing dates against cached fixing dates
627 BOOST_CHECK_EQUAL_COLLECTIONS(cachedOptionletFixingDates.begin(), cachedOptionletFixingDates.end(),
628 pwos->optionletFixingDates().begin(), pwos->optionletFixingDates().end());
629
630 // Check cached optionlet values at optionlet fixing dates
631 Matrix cached(cachedOptionletFixingDates.size(), cachedStrikes.size(), cachedValues.begin(), cachedValues.end());
632 BOOST_TEST_MESSAGE("Optionlet volatilities at the fixing dates");
633 BOOST_TEST_MESSAGE("date,strike,volatility,cached,diff");
634 for (Size i = 0; i < pwos->optionletFixingDates().size(); i++) {
635 for (Size j = 0; j < cachedStrikes.size(); j++) {
636 Date d = pwos->optionletFixingDates()[i];
637 Rate s = cachedStrikes[j];
638 Volatility v = ovs->volatility(d, s);
639 Volatility diff = fabs(v - cached[i][j]);
640 BOOST_CHECK_SMALL(diff, tolerance);
641 BOOST_TEST_MESSAGE(io::iso_date(d) << "," << s << "," << fixed << setprecision(12) << v << ","
642 << cached[i][j] << "," << diff);
643 }
644 }
645
646 // Check cached optionlet values at ad-hoc dates
647 cached = Matrix(cachedAdHocDates.size(), cachedStrikes.size(), cachedAdHocValues.begin(), cachedAdHocValues.end());
648 BOOST_TEST_MESSAGE("Optionlet volatilities at the ad-hoc dates");
649 BOOST_TEST_MESSAGE("date,strike,volatility,cached,diff");
650 for (Size i = 0; i < cachedAdHocDates.size(); i++) {
651 for (Size j = 0; j < cachedStrikes.size(); j++) {
652 Date d = cachedAdHocDates[i];
653 Rate s = cachedStrikes[j];
654 Volatility v = ovs->volatility(d, s);
655 Volatility diff = fabs(v - cached[i][j]);
656 BOOST_CHECK_SMALL(diff, tolerance);
657 BOOST_TEST_MESSAGE(io::iso_date(d) << "," << s << "," << fixed << setprecision(12) << v << ","
658 << cached[i][j] << "," << diff);
659 }
660 }
661}

◆ BOOST_FIXTURE_TEST_CASE() [3/3]

BOOST_FIXTURE_TEST_CASE ( testChangingCapFloorSurface  ,
CommonVars   
)

Definition at line 663 of file piecewiseoptionletstripper.cpp.

663 {
664
665 BOOST_TEST_MESSAGE("Testing changing the input cap floor surface");
666
667 // Take four normal volatilities from test data and create quotes
668 Size lastTenorIdx = testVols.tenors.size() - 1;
669 Size lastStrikeIdx = testVols.strikes.size() - 1;
670
671 vector<Period> tenors = list_of(testVols.tenors[0])(testVols.tenors[lastTenorIdx]);
672 vector<Rate> strikes = list_of(testVols.strikes[0])(testVols.strikes[lastStrikeIdx]);
673
674 vector<vector<QuantLib::ext::shared_ptr<SimpleQuote> > > quotes(2);
675 quotes[0].push_back(QuantLib::ext::make_shared<SimpleQuote>(testVols.nVols[0][0]));
676 quotes[0].push_back(QuantLib::ext::make_shared<SimpleQuote>(testVols.nVols[0][lastStrikeIdx]));
677 quotes[1].push_back(QuantLib::ext::make_shared<SimpleQuote>(testVols.nVols[lastTenorIdx][0]));
678 quotes[1].push_back(QuantLib::ext::make_shared<SimpleQuote>(testVols.nVols[lastTenorIdx][lastStrikeIdx]));
679
680 vector<vector<Handle<Quote> > > quoteHs(2);
681 quoteHs[0].push_back(Handle<Quote>(quotes[0][0]));
682 quoteHs[0].push_back(Handle<Quote>(quotes[0][1]));
683 quoteHs[1].push_back(Handle<Quote>(quotes[1][0]));
684 quoteHs[1].push_back(Handle<Quote>(quotes[1][1]));
685
686 // Create the cap floor term vol surface using the quotes
687 QuantLib::ext::shared_ptr<TermVolSurface> cfts = QuantLib::ext::make_shared<TermVolSurface>(
688 settlementDays, calendar, bdc, tenors, strikes, quoteHs, dayCounter, TermVolSurface::Bilinear);
689
690 // Create the piecewise optionlet stripper
691 QuantLib::ext::shared_ptr<QuantExt::OptionletStripper> pwos = QuantLib::ext::make_shared<PiecewiseOptionletStripper<LinearFlat> >(
692 cfts, iborIndex, testYieldCurves.discountEonia, true, Normal, 0.0, Normal);
693
694 // Create the OptionletVolatilityStructure
695 QuantLib::ext::shared_ptr<OptionletVolatilityStructure> ovs =
696 QuantLib::ext::make_shared<QuantExt::StrippedOptionletAdapter<LinearFlat, LinearFlat> >(pwos);
697 ovs->enableExtrapolation();
698
699 // Request optionlet volatility at test date
700 Date testDate = pwos->optionletFixingDates().back();
701 Volatility initialVol = ovs->volatility(testDate, strikes[0]);
702 BOOST_TEST_MESSAGE("Test vol before shift is: " << fixed << setprecision(12) << initialVol);
703 Volatility expInitialVol = 0.007941492816;
704 BOOST_CHECK_SMALL(fabs(expInitialVol - initialVol), tolerance);
705
706 // Shift the input quote and request the same optionlet volatility
707 Rate shift = 1.1;
708 quotes[1][0]->setValue(shift * quotes[1][0]->value());
709 Volatility shiftedVol = ovs->volatility(testDate, strikes[0]);
710 BOOST_TEST_MESSAGE("Test vol after shift is: " << fixed << setprecision(12) << shiftedVol);
711 Volatility expShiftedVol = 0.008926338986;
712 BOOST_CHECK_SMALL(fabs(expShiftedVol - shiftedVol), tolerance);
713
714 // Reset the input quote
715 quotes[1][0]->setValue(quotes[1][0]->value() / shift);
716 initialVol = ovs->volatility(testDate, strikes[0]);
717 BOOST_TEST_MESSAGE("Test vol after reset is: " << fixed << setprecision(12) << initialVol);
718 BOOST_CHECK_SMALL(fabs(expInitialVol - initialVol), tolerance);
719
720 // Change the evaluation date
721 Date newDate = referenceDate + 1 * Weeks;
722 Settings::instance().evaluationDate() = newDate;
723
724 // Check that the optionlet volatility structure's reference date has moved
725 // Only the case because we used a "moving" adapter
726 BOOST_CHECK_EQUAL(ovs->referenceDate(), newDate);
727
728 // Check that one of the optionlet fixing dates in the PiecewiseOptionletStripper has moved
729 // Only the case because we used a "moving" cap floor volatility term surface as input
730 Date newLastOptionletDate = pwos->optionletFixingDates().back();
731 BOOST_TEST_MESSAGE("Last fixing date moved from " << io::iso_date(testDate) << " to "
732 << io::iso_date(newLastOptionletDate));
733 BOOST_CHECK(newLastOptionletDate > testDate);
734
735 // Check the newly calculated optionlet vol for the old test date
736 Volatility newVol = ovs->volatility(testDate, strikes[0]);
737 BOOST_TEST_MESSAGE("Test vol after moving evaluation date is: " << fixed << setprecision(12) << newVol);
738 Volatility expNewVol = 0.007932365669;
739 BOOST_CHECK_SMALL(fabs(expNewVol - newVol), tolerance);
740}
vector< Real > strikes