Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Functions
lgmflexiswapengine.cpp File Reference
#include "toplevelfixture.hpp"
#include <qle/models/irlgm1fpiecewiseconstanthullwhiteadaptor.hpp>
#include <qle/models/lgm.hpp>
#include <qle/pricingengines/numericlgmmultilegoptionengine.hpp>
#include <qle/pricingengines/numericlgmflexiswapengine.hpp>
#include <ql/cashflows/floatingratecoupon.hpp>
#include <ql/currencies/europe.hpp>
#include <ql/indexes/ibor/euribor.hpp>
#include <ql/models/shortrate/onefactormodels/gsr.hpp>
#include <ql/pricingengines/swap/discountingswapengine.hpp>
#include <ql/pricingengines/swaption/gaussian1dswaptionengine.hpp>
#include <ql/termstructures/yield/flatforward.hpp>
#include <ql/time/all.hpp>
#include <boost/assign/std/vector.hpp>
#include <boost/timer/timer.hpp>
#include <boost/test/unit_test.hpp>
#include <algorithm>

Go to the source code of this file.

Functions

 BOOST_AUTO_TEST_CASE (testSingleSwaption)
 
 BOOST_AUTO_TEST_CASE (testMultipleSwaptions)
 
 BOOST_AUTO_TEST_CASE (testDeterministicCase)
 

Function Documentation

◆ BOOST_AUTO_TEST_CASE() [1/3]

BOOST_AUTO_TEST_CASE ( testSingleSwaption  )

Definition at line 112 of file lgmflexiswapengine.cpp.

112 {
113
114 BOOST_TEST_MESSAGE("Testing LGM Flexi-Swap engine in single swaption case...");
115
116 // vanilla bermudan swaption
117
118 QuantLib::ext::shared_ptr<Exercise> exercise = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates, false);
119 QuantLib::ext::shared_ptr<Swaption> swaption = QuantLib::ext::make_shared<Swaption>(vanillaSwap, exercise);
120
121 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngine =
122 QuantLib::ext::make_shared<NumericLgmSwaptionEngine>(lgm, 7.0, 16, 7.0, 32);
123
124 swaption->setPricingEngine(swaptionEngine);
125 boost::timer::cpu_timer timer;
126 Real swaptionNpv = swaption->NPV();
127 timer.stop();
128
129 Real swapNpv = vanillaSwap->NPV();
130
131 BOOST_TEST_MESSAGE("swaption npv = " << swaptionNpv << " swap npv = " << swapNpv
132 << " fix = " << vanillaSwap->legNPV(0) << " float =" << vanillaSwap->legNPV(1)
133 << " timing = " << timer.elapsed().wall * 1e-6 << " ms");
134
135 // flexi swap
136
137 Size nFixed = fixedSchedule.size() - 1, nFloat = floatingSchedule.size() - 1;
138 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap = QuantLib::ext::make_shared<FlexiSwap>(
139 VanillaSwap::Payer, std::vector<Real>(nFixed, nominal), std::vector<Real>(nFloat, nominal), fixedSchedule,
140 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
141 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
142 std::vector<Real>(nFloat, Null<Real>()), Actual360(), std::vector<Real>(nFixed, 0.0), Position::Long);
143 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap2 = QuantLib::ext::make_shared<FlexiSwap>(
144 VanillaSwap::Receiver, std::vector<Real>(nFixed, nominal), std::vector<Real>(nFloat, nominal), fixedSchedule,
145 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
146 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
147 std::vector<Real>(nFloat, Null<Real>()), Actual360(), std::vector<Real>(nFixed, 0.0), Position::Short);
148
149 auto flexiEngine = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
151 auto flexiEngine2 = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
153
154 flexiSwap->setPricingEngine(dscSwapEngine);
155 flexiSwap2->setPricingEngine(dscSwapEngine);
156 Real flexiUnderlyingNpvAnalytical = flexiSwap->NPV();
157 Real flexiUnderlyingNpvAnalytical2 = flexiSwap2->NPV();
158
159 flexiSwap->setPricingEngine(flexiEngine);
160 flexiSwap2->setPricingEngine(flexiEngine);
161 timer.start();
162 Real flexiNpv = flexiSwap->NPV();
163 timer.stop();
164 Real timing2 = timer.elapsed().wall * 1e-6;
165 Real flexiUnderlyingNpv = flexiSwap->underlyingValue();
166 Real flexiOptionNpv = flexiNpv - flexiUnderlyingNpv;
167 Real flexiNpv2 = flexiSwap2->NPV();
168 Real flexiUnderlyingNpv2 = flexiSwap2->underlyingValue();
169 Real flexiOptionNpv2 = flexiNpv2 - flexiUnderlyingNpv2;
170
171 flexiSwap->setPricingEngine(flexiEngine2);
172 flexiSwap2->setPricingEngine(flexiEngine2);
173 timer.start();
174 Real flexiNpvb = flexiSwap->NPV();
175 timer.stop();
176 Real timing3 = timer.elapsed().wall * 1e-6;
177 Real flexiUnderlyingNpvb = flexiSwap->underlyingValue();
178 Real flexiOptionNpvb = flexiNpv - flexiUnderlyingNpv;
179 Real flexiNpvb2 = flexiSwap2->NPV();
180 Real flexiUnderlyingNpvb2 = flexiSwap2->underlyingValue();
181 Real flexiOptionNpvb2 = flexiNpv2 - flexiUnderlyingNpv2;
182
183 BOOST_TEST_MESSAGE("A1 flexi npv = " << flexiNpv << " flexi underlying npv = " << flexiUnderlyingNpv
184 << " flexi option npv = " << flexiOptionNpv
185 << " flexi analytical underlying npv = " << flexiUnderlyingNpvAnalytical
186 << " timing = " << timing2 << " ms (method=SwaptionArray)");
187 BOOST_TEST_MESSAGE("A2 flexi npv = " << flexiNpv2 << " flexi underlying npv = " << flexiUnderlyingNpv2
188 << " flexi option npv = " << flexiOptionNpv2
189 << " flexi analytical underlying npv = " << flexiUnderlyingNpvAnalytical2);
190
191 BOOST_TEST_MESSAGE("B1 flexi npv = " << flexiNpvb << " flexi underlying npv = " << flexiUnderlyingNpvb
192 << " flexi option npv = " << flexiOptionNpvb
193 << " flexi analytical underlying npv = " << flexiUnderlyingNpvAnalytical
194 << " timing = " << timing3 << " ms (method=SingleSwaptions)");
195 BOOST_TEST_MESSAGE("B2 flexi npv = " << flexiNpvb2 << " flexi underlying npv = " << flexiUnderlyingNpvb2
196 << " flexi option npv = " << flexiOptionNpvb2
197 << " flexi analytical underlying npv = " << flexiUnderlyingNpvAnalytical2);
198
199 // checks
200
201 Real tol = 3E-5 * nominal; // 0.3 bp on nominal
202
203 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv + swapNpv), tol);
204 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv - swaptionNpv), tol);
205
206 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv2 - swapNpv), tol);
207 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv2 + swaptionNpv), tol);
208
209 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpvAnalytical + swapNpv), tol);
210 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpvAnalytical2 - swapNpv), tol);
211
212 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpvb + swapNpv), tol);
213 BOOST_CHECK_SMALL(std::abs(flexiOptionNpvb - swaptionNpv), tol);
214
215 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpvb2 - swapNpv), tol);
216 BOOST_CHECK_SMALL(std::abs(flexiOptionNpvb2 + swaptionNpv), tol);
217
218 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpvAnalytical + swapNpv), tol);
219 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpvAnalytical2 - swapNpv), tol);
220
221} // testSingleSwaption

◆ BOOST_AUTO_TEST_CASE() [2/3]

BOOST_AUTO_TEST_CASE ( testMultipleSwaptions  )

Definition at line 223 of file lgmflexiswapengine.cpp.

223 {
224
225 BOOST_TEST_MESSAGE("Testing LGM Flexi-Swap engine in multiple swaption case...");
226
227 // flexi swap
228
229 Size nFixed = fixedSchedule.size() - 1, nFloat = floatingSchedule.size() - 1;
230 std::vector<Real> fixedNotionals{900.0, 1000.0, 1000.0, 800.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0};
231 std::vector<Real> floatNotionals{900.0, 900.0, 1000.0, 1000.0, 1000.0, 1000.0, 800.0, 800.0, 500.0, 500.0,
232 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0, 500.0};
233 std::vector<Real> lowerNotionals{900.0, 1000.0, 750.0, 600.0, 250.0, 0.0, 0.0, 0.0, 0.0, 0.0};
234
235 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap = QuantLib::ext::make_shared<FlexiSwap>(
236 VanillaSwap::Payer, fixedNotionals, floatNotionals, fixedSchedule, std::vector<Real>(nFixed, strike),
237 Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0), std::vector<Real>(nFloat, 0.0),
238 std::vector<Real>(nFloat, Null<Real>()), std::vector<Real>(nFloat, Null<Real>()), Actual360(), lowerNotionals,
239 Position::Long);
240
241 auto flexiEngine = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
243 auto flexiEngine2 = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
245
246 flexiSwap->setPricingEngine(flexiEngine);
247 boost::timer::cpu_timer timer;
248 Real flexiNpv = flexiSwap->NPV();
249 timer.stop();
250 Real timing1 = timer.elapsed().wall * 1e-6;
251 Real flexiUnderlyingNpv = flexiSwap->underlyingValue();
252 Real flexiOptionNpv = flexiNpv - flexiUnderlyingNpv;
253
254 flexiSwap->setPricingEngine(flexiEngine2);
255 timer.start();
256 Real flexiNpv2 = flexiSwap->NPV();
257 timer.stop();
258 Real timing3 = timer.elapsed().wall * 1e-6;
259 Real flexiUnderlyingNpv2 = flexiSwap->underlyingValue();
260 Real flexiOptionNpv2 = flexiNpv2 - flexiUnderlyingNpv2;
261
262 flexiSwap->setPricingEngine(dscSwapEngine);
263 Real flexiUnderlyingNpvAnalytical = flexiSwap->NPV();
264
265 // replicating swaptions
266
267 // 1) vol = 200, start 2, end 3
268 Schedule fixedSchedule1(fixedSchedule[2], fixedSchedule[3], 1 * Years, cal, ModifiedFollowing, ModifiedFollowing,
269 DateGeneration::Forward, false);
270 Schedule floatingSchedule1(floatingSchedule[4], floatingSchedule[6], 6 * Months, cal, ModifiedFollowing,
271 ModifiedFollowing, DateGeneration::Forward, false);
272 auto swap1 = QuantLib::ext::make_shared<VanillaSwap>(VanillaSwap::Receiver, 200.0, fixedSchedule1, strike, Thirty360(Thirty360::BondBasis),
273 floatingSchedule1, euribor6m, 0.0, Actual360());
274 std::vector<Date> exerciseDates1(exerciseDates.begin() + 1, exerciseDates.begin() + 2);
275 auto exercise1 = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates1, false);
276 auto swaption1 = QuantLib::ext::make_shared<Swaption>(swap1, exercise1);
277
278 // 1) vol = 50, start 2, end 4
279 Schedule fixedSchedule2(fixedSchedule[2], fixedSchedule[4], 1 * Years, cal, ModifiedFollowing, ModifiedFollowing,
280 DateGeneration::Forward, false);
281 Schedule floatingSchedule2(floatingSchedule[4], floatingSchedule[8], 6 * Months, cal, ModifiedFollowing,
282 ModifiedFollowing, DateGeneration::Forward, false);
283 auto swap2 = QuantLib::ext::make_shared<VanillaSwap>(VanillaSwap::Receiver, 50.0, fixedSchedule2, strike, Thirty360(Thirty360::BondBasis),
284 floatingSchedule2, euribor6m, 0.0, Actual360());
285 std::vector<Date> exerciseDates2(exerciseDates.begin() + 1, exerciseDates.begin() + 3);
286 auto exercise2 = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates2, false);
287 auto swaption2 = QuantLib::ext::make_shared<Swaption>(swap2, exercise2);
288
289 // 3) vol = 150, start 3, end 4
290 Schedule fixedSchedule3(fixedSchedule[3], fixedSchedule[4], 1 * Years, cal, ModifiedFollowing, ModifiedFollowing,
291 DateGeneration::Forward, false);
292 Schedule floatingSchedule3(floatingSchedule[6], floatingSchedule[8], 6 * Months, cal, ModifiedFollowing,
293 ModifiedFollowing, DateGeneration::Forward, false);
294 auto swap3 = QuantLib::ext::make_shared<VanillaSwap>(VanillaSwap::Receiver, 150.0, fixedSchedule3, strike, Thirty360(Thirty360::BondBasis),
295 floatingSchedule3, euribor6m, 0.0, Actual360());
296 std::vector<Date> exerciseDates3(exerciseDates.begin() + 2, exerciseDates.begin() + 3);
297 auto exercise3 = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates3, false);
298 auto swaption3 = QuantLib::ext::make_shared<Swaption>(swap3, exercise3);
299
300 // 4) vol = 250, start 4, end 10
301 Schedule fixedSchedule4(fixedSchedule[4], fixedSchedule[10], 1 * Years, cal, ModifiedFollowing, ModifiedFollowing,
302 DateGeneration::Forward, false);
303 Schedule floatingSchedule4(floatingSchedule[8], floatingSchedule[20], 6 * Months, cal, ModifiedFollowing,
304 ModifiedFollowing, DateGeneration::Forward, false);
305 auto swap4 = QuantLib::ext::make_shared<VanillaSwap>(VanillaSwap::Receiver, 250.0, fixedSchedule4, strike, Thirty360(Thirty360::BondBasis),
306 floatingSchedule4, euribor6m, 0.0, Actual360());
307 std::vector<Date> exerciseDates4(exerciseDates.begin() + 3, exerciseDates.begin() + 9);
308 auto exercise4 = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates4, false);
309 auto swaption4 = QuantLib::ext::make_shared<Swaption>(swap4, exercise4);
310
311 // 5) vol = 250, start 5, end 10
312 Schedule fixedSchedule5(fixedSchedule[5], fixedSchedule[10], 1 * Years, cal, ModifiedFollowing, ModifiedFollowing,
313 DateGeneration::Forward, false);
314 Schedule floatingSchedule5(floatingSchedule[10], floatingSchedule[20], 6 * Months, cal, ModifiedFollowing,
315 ModifiedFollowing, DateGeneration::Forward, false);
316 auto swap5 = QuantLib::ext::make_shared<VanillaSwap>(VanillaSwap::Receiver, 250.0, fixedSchedule5, strike, Thirty360(Thirty360::BondBasis),
317 floatingSchedule5, euribor6m, 0.0, Actual360());
318 std::vector<Date> exerciseDates5(exerciseDates.begin() + 4, exerciseDates.begin() + 9);
319 auto exercise5 = QuantLib::ext::make_shared<BermudanExercise>(exerciseDates5, false);
320 auto swaption5 = QuantLib::ext::make_shared<Swaption>(swap5, exercise5);
321
322 QuantLib::ext::shared_ptr<PricingEngine> swaptionEngine =
323 QuantLib::ext::make_shared<NumericLgmSwaptionEngine>(lgm, 7.0, 16, 7.0, 32);
324 swaption1->setPricingEngine(swaptionEngine);
325 swaption2->setPricingEngine(swaptionEngine);
326 swaption3->setPricingEngine(swaptionEngine);
327 swaption4->setPricingEngine(swaptionEngine);
328 swaption5->setPricingEngine(swaptionEngine);
329 timer.start();
330 Real swaptionNpv = swaption1->NPV() + swaption2->NPV() + swaption3->NPV() + swaption4->NPV() + swaption5->NPV();
331 timer.stop();
332 Real timing2 = timer.elapsed().wall * 1e-6;
333
334 BOOST_TEST_MESSAGE("swaption basket npv =" << swaptionNpv << " timing = " << timing2 << " ms");
335 BOOST_TEST_MESSAGE("A flexi npv = " << flexiNpv << " flexi underlying npv = " << flexiUnderlyingNpv
336 << " flexi option npv = " << flexiOptionNpv
337 << " flexi analytical underlying npv = " << flexiUnderlyingNpvAnalytical
338 << " timing = " << timing1 << " ms (method=SwaptionArray)");
339 BOOST_TEST_MESSAGE("B flexi npv = " << flexiNpv2 << " flexi underlying npv = " << flexiUnderlyingNpv2
340 << " flexi option npv = " << flexiOptionNpv2
341 << " flexi analytical underlying npv = " << flexiUnderlyingNpvAnalytical
342 << " timing = " << timing3 << " ms (method=SingleSwaptions)");
343 // checks
344
345 Real tol = 3E-5 * nominal; // 0.3 bp on nominal
346
347 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv - swaptionNpv), tol);
348 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv - flexiUnderlyingNpvAnalytical), tol);
349 BOOST_CHECK_SMALL(std::abs(flexiNpv - flexiUnderlyingNpv - flexiOptionNpv), 1E-10);
350
351 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv2 - swaptionNpv), tol);
352 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv2 - flexiUnderlyingNpvAnalytical), tol);
353 BOOST_CHECK_SMALL(std::abs(flexiNpv2 - flexiUnderlyingNpv2 - flexiOptionNpv2), 1E-10);
354}

◆ BOOST_AUTO_TEST_CASE() [3/3]

BOOST_AUTO_TEST_CASE ( testDeterministicCase  )

Definition at line 356 of file lgmflexiswapengine.cpp.

356 {
357
358 BOOST_TEST_MESSAGE("Testing LGM Flexi-Swap engine in deterministic case (zero swaptions)...");
359
360 // vanilla swap
361
362 Real swapNpv = vanillaSwap->NPV();
363 BOOST_TEST_MESSAGE("swap npv = " << swapNpv << " fix = " << vanillaSwap->legNPV(0)
364 << " float =" << vanillaSwap->legNPV(1));
365
366 // flexi swap
367
368 Size nFixed = fixedSchedule.size() - 1, nFloat = floatingSchedule.size() - 1;
369 QuantLib::ext::shared_ptr<FlexiSwap> flexiSwap = QuantLib::ext::make_shared<FlexiSwap>(
370 VanillaSwap::Payer, std::vector<Real>(nFixed, nominal), std::vector<Real>(nFloat, nominal), fixedSchedule,
371 std::vector<Real>(nFixed, strike), Thirty360(Thirty360::BondBasis), floatingSchedule, euribor6m, std::vector<Real>(nFloat, 1.0),
372 std::vector<Real>(nFloat, 0.0), std::vector<Real>(nFloat, Null<Real>()),
373 std::vector<Real>(nFloat, Null<Real>()), Actual360(), std::vector<Real>(nFixed, nominal), Position::Long);
374
375 auto flexiEngine = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
377 auto flexiEngine2 = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
379 auto flexiEngine3 = QuantLib::ext::make_shared<NumericLgmFlexiSwapEngine>(
381
382 flexiSwap->setPricingEngine(flexiEngine);
383 Real flexiNpv = flexiSwap->NPV();
384 Real flexiUnderlyingNpv = flexiSwap->underlyingValue();
385 Real flexiOptionNpv = flexiNpv - flexiUnderlyingNpv;
386 flexiSwap->setPricingEngine(flexiEngine2);
387 Real flexiNpv2 = flexiSwap->NPV();
388 Real flexiUnderlyingNpv2 = flexiSwap->underlyingValue();
389 Real flexiOptionNpv2 = flexiNpv2 - flexiUnderlyingNpv2;
390 flexiSwap->setPricingEngine(flexiEngine3);
391 Real flexiNpv3 = flexiSwap->NPV();
392 Real flexiUnderlyingNpv3 = flexiSwap->underlyingValue();
393 Real flexiOptionNpv3 = flexiNpv3 - flexiUnderlyingNpv3;
394
395 BOOST_TEST_MESSAGE("1 flexi npv = " << flexiNpv << " flexi underlying npv = " << flexiUnderlyingNpv
396 << " flexi option npv = " << flexiOptionNpv << " (method=SwaptionArray)");
397 BOOST_TEST_MESSAGE("2 flexi npv = " << flexiNpv2 << " flexi underlying npv = " << flexiUnderlyingNpv2
398 << " flexi option npv = " << flexiOptionNpv2 << " (method=SwaptionArray)");
399 BOOST_TEST_MESSAGE("3 flexi npv = " << flexiNpv3 << " flexi underlying npv = " << flexiUnderlyingNpv3
400 << " flexi option npv = " << flexiOptionNpv3 << " (method=SwaptionArray)");
401
402 // checks
403
404 Real tol = 3E-5 * nominal; // 0.3 bp on nominal
405
406 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv + swapNpv), tol);
407 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv), tol);
408 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv2 + swapNpv), tol);
409 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv2), tol);
410 BOOST_CHECK_SMALL(std::abs(flexiUnderlyingNpv3 + swapNpv), tol);
411 BOOST_CHECK_SMALL(std::abs(flexiOptionNpv3), tol);
412
413} // testDeterministicCase