Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
mclgmswaptionengine.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <boost/test/unit_test.hpp>
20//#include <oret/toplevelfixture.hpp>
22
23#include <algorithm>
24#include <boost/assign/std/vector.hpp>
25
28#include <qle/models/lgm.hpp>
30
32
33#include <ql/currencies/europe.hpp>
34#include <ql/indexes/ibor/euribor.hpp>
35#include <ql/models/shortrate/onefactormodels/gsr.hpp>
36#include <ql/pricingengines/swap/discountingswapengine.hpp>
37#include <ql/pricingengines/swaption/gaussian1dswaptionengine.hpp>
38#include <ql/termstructures/yield/flatforward.hpp>
39#include <ql/time/all.hpp>
40
41#include <boost/timer/timer.hpp>
42
43using namespace boost::assign;
44using namespace QuantLib;
45using namespace QuantExt;
46using namespace boost::unit_test_framework;
47using namespace std;
48
49BOOST_FIXTURE_TEST_SUITE(OreAmcTestSuite, qle::test::TopLevelFixture)
50
51BOOST_AUTO_TEST_SUITE(AmcMcLgmSwaptionEngineTest)
52
53BOOST_AUTO_TEST_CASE(testAgainstSwaptionEngines) {
54
55 BOOST_TEST_MESSAGE("Testing MC LGM Bermudan swaption engine against other bermudan swaption engines...");
56
57 Calendar cal = TARGET();
58 Date evalDate(5, February, 2016);
59 Date effectiveDate(cal.advance(evalDate, 2 * Days));
60 Date startDate(cal.advance(effectiveDate, 1 * Years));
61 Date maturityDate(cal.advance(startDate, 9 * Years));
62
63 Settings::instance().evaluationDate() = evalDate;
64
65 // Setup the bermudan swaption and its underlying swap
66 Real nominal = 1.0;
67 // Fixed leg
68 Rate fixedRate = 0.02;
69 DayCounter fixedDayCount = Thirty360(Thirty360::BondBasis);
70 Schedule fixedSchedule(startDate, maturityDate, 1 * Years, cal, ModifiedFollowing, ModifiedFollowing,
71 DateGeneration::Forward, false);
72
73 // Floating leg
74 Handle<YieldTermStructure> yts(QuantLib::ext::make_shared<FlatForward>(evalDate, 0.02, Actual365Fixed()));
75 QuantLib::ext::shared_ptr<IborIndex> euribor6m(QuantLib::ext::make_shared<Euribor>(6 * Months, yts));
76 Spread spread = 0.0;
77 DayCounter floatingDayCount = Actual360();
78 Schedule floatingSchedule(startDate, maturityDate, 6 * Months, cal, ModifiedFollowing, ModifiedFollowing,
79 DateGeneration::Forward, false);
80
81 // Underlying swap
82 QuantLib::ext::shared_ptr<VanillaSwap> undlSwap = QuantLib::ext::make_shared<VanillaSwap>(
83 VanillaSwap(VanillaSwap::Payer, nominal, fixedSchedule, fixedRate, fixedDayCount, floatingSchedule, euribor6m,
84 spread, floatingDayCount));
85
86 undlSwap->setPricingEngine(QuantLib::ext::make_shared<DiscountingSwapEngine>(yts));
87 BOOST_TEST_MESSAGE("Underlying value analytic = " << undlSwap->NPV());
88
89 // Bermudan swaption
90 std::vector<Date> exerciseDates;
91 for (Size i = 0; i < 9; ++i) {
92 exerciseDates.push_back(cal.advance(fixedSchedule[i], -2 * Days));
93 }
94 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates, false);
95 QuantLib::ext::shared_ptr<Swaption> swaption = QuantLib::ext::make_shared<Swaption>(undlSwap, exercise);
96
97 // Setup models and model adaptors
98 std::vector<Date> stepDates = std::vector<Date>(exerciseDates.begin(), exerciseDates.end() - 1);
99 Array stepTimes(stepDates.size());
100 for (Size i = 0; i < stepDates.size(); ++i) {
101 stepTimes[i] = yts->timeFromReference(stepDates[i]);
102 }
103
104 std::vector<Real> sigmas(stepDates.size() + 1);
105 for (Size i = 0; i < sigmas.size(); ++i) {
106 sigmas[i] = 0.0050 + (0.0080 - 0.0050) * std::exp(-0.2 * static_cast<double>(i));
107 }
108
109 Real reversion = 0.03;
110 QuantLib::ext::shared_ptr<Gsr> gsr = QuantLib::ext::make_shared<Gsr>(yts, stepDates, sigmas, reversion, 50.0);
111
112 // The Hull White adaptor for the LGM parametrization should lead to equal Bermudan swaption prices
113 QuantLib::ext::shared_ptr<IrLgm1fParametrization> lgmParam = QuantLib::ext::make_shared<IrLgm1fPiecewiseConstantHullWhiteAdaptor>(
114 EURCurrency(), yts, stepTimes, Array(sigmas.begin(), sigmas.end()), stepTimes, Array(sigmas.size(), reversion));
115
116 // fix any T forward measure
117 QuantLib::ext::shared_ptr<LinearGaussMarkovModel> lgm = QuantLib::ext::make_shared<LinearGaussMarkovModel>(lgmParam);
118 QuantLib::ext::shared_ptr<Gaussian1dModel> lgmGaussian1d = QuantLib::ext::make_shared<Gaussian1dCrossAssetAdaptor>(lgm);
119
120 // Setup the different pricing engines
121 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngineGsr =
122 QuantLib::ext::make_shared<Gaussian1dSwaptionEngine>(gsr, 64, 7.0, true, false);
123
124 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngineLgm =
125 QuantLib::ext::make_shared<Gaussian1dSwaptionEngine>(lgmGaussian1d, 64, 7.0, true, false);
126
127 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngineLgm2 =
128 QuantLib::ext::make_shared<NumericLgmSwaptionEngine>(lgm, 7.0, 16, 7.0, 32);
129
130 Size polynomOrder = 4;
131 LsmBasisSystem::PolynomialType polynomType = LsmBasisSystem::Monomial;
132 Size tSamples = 10000;
133 Size pSamples = 10000;
134 QuantLib::ext::shared_ptr<StochasticProcess> stateProcess = lgm->stateProcess();
135
136 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngineLgmMC = QuantLib::ext::shared_ptr<McLgmSwaptionEngine>(
137 new McLgmSwaptionEngine(lgm, MersenneTwisterAntithetic, SobolBrownianBridge, tSamples, pSamples, 42, 43,
138 polynomOrder, polynomType));
139
140 // Calculate the T0 price of the bermudan swaption using different engines
141 swaption->setPricingEngine(swaptionEngineGsr);
142 Real npvGsr = swaption->NPV();
143
144 swaption->setPricingEngine(swaptionEngineLgm);
145 Real npvLgm = swaption->NPV();
146
147 swaption->setPricingEngine(swaptionEngineLgm2);
148 Real npvLgm2 = swaption->NPV();
149
150 boost::timer::cpu_timer timer;
151 swaption->setPricingEngine(swaptionEngineLgmMC);
152 Real npvLgmMc = swaption->NPV();
153 Real undNpvMc = swaption->result<Real>("underlyingNpv");
154 BOOST_TEST_MESSAGE("Underlying value mc = " << undNpvMc);
155 BOOST_TEST_MESSAGE("npvGsr: " << npvGsr << ", npvLgm: " << npvLgm << ", npvLgm2: " << npvLgm
156 << ", npvLgmMc: " << npvLgmMc);
157 timer.stop();
158 BOOST_TEST_MESSAGE("timing mc engine: " << timer.elapsed().wall * 1e-6 << " ms");
159
160 Real tol = 2E-4; // basis point tolerance
161 BOOST_CHECK_SMALL(std::fabs(undNpvMc - undlSwap->NPV()), tol);
162 BOOST_CHECK_SMALL(std::fabs(npvGsr - npvLgm), tol);
163 BOOST_CHECK_SMALL(std::fabs(npvGsr - npvLgm2), tol);
164 BOOST_CHECK_SMALL(std::fabs(npvGsr - npvLgmMc), tol);
165} // testAgainstSwaptionEngines
166
167BOOST_AUTO_TEST_SUITE_END()
168
169BOOST_AUTO_TEST_SUITE_END()
adaptor class that extracts one irlgm1f component
adaptor to emulate piecewise constant Hull White parameters
lgm model class
MC LGM swaption engines.
BOOST_AUTO_TEST_CASE(testAgainstSwaptionEngines)
Fixture that can be used at top level.