Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
crossassetmodel2.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 "toplevelfixture.hpp"
20#include "utilities.hpp"
21#include <boost/test/unit_test.hpp>
47#include <qle/models/lgm.hpp>
71
72#include <ql/currencies/all.hpp>
73#include <ql/indexes/ibor/euribor.hpp>
74#include <ql/instruments/vanillaoption.hpp>
75#include <ql/math/matrixutilities/symmetricschurdecomposition.hpp>
76#include <ql/math/optimization/levenbergmarquardt.hpp>
77#include <ql/math/randomnumbers/rngtraits.hpp>
78#include <ql/math/statistics/incrementalstatistics.hpp>
79#include <ql/methods/montecarlo/multipathgenerator.hpp>
80#include <ql/methods/montecarlo/pathgenerator.hpp>
81#include <ql/quotes/simplequote.hpp>
82#include <ql/termstructures/yield/flatforward.hpp>
83#include <ql/time/calendars/target.hpp>
84#include <ql/time/daycounters/actual360.hpp>
85#include <ql/time/daycounters/actualactual.hpp>
86#include <ql/time/daycounters/thirty360.hpp>
87
88#include <boost/make_shared.hpp>
89// fix for boost 1.64, see https://lists.boost.org/Archives/boost/2016/11/231756.php
90#if BOOST_VERSION >= 106400
91#include <boost/serialization/array_wrapper.hpp>
92#endif
93#include <boost/accumulators/accumulators.hpp>
94#include <boost/accumulators/statistics/covariance.hpp>
95#include <boost/accumulators/statistics/error_of_mean.hpp>
96#include <boost/accumulators/statistics/mean.hpp>
97#include <boost/accumulators/statistics/stats.hpp>
98#include <boost/accumulators/statistics/variates/covariate.hpp>
99
100using namespace QuantLib;
101using namespace QuantExt;
102
103using boost::unit_test_framework::test_suite;
104using namespace boost::accumulators;
105
106namespace {
107
108struct Lgm31fTestData {
109 Lgm31fTestData()
110 : refDate(18, Dec, 2015),
111 yts(QuantLib::ext::make_shared<FlatForward>(refDate, 0.02, ActualActual(ActualActual::ISDA))) {
112
113 Settings::instance().evaluationDate() = refDate;
114 Size tmp[31] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 16, 17, 18,
115 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 13, 29, 14, 30, 15 };
116 for (Size i = 0; i < 31; ++i) {
117 mapping[i] = tmp[i];
118 invMapping[mapping[i]] = i;
119 }
120
121 // ========================================================
122 // correlation matrix (13 ccy, 12 fx, 3 inf pairs (CPI,RR))
123 // ========================================================
124
125 // we map the CPI index and RR to pseudo-FX components here,
126 // therefore non EUR inflation components (i.e. the UK region)
127 // will produce deviating results, since implicitly we assume
128 // EUR as the inflation currency
129
130 // also, we have a mapping from the original indices to the new
131 // indices because of the CPI components, as follows
132 // (original => here)
133 // 0-12 => 0-12
134 // 13-24 => 16-27
135 // 25 => 28
136 // 26 => 13
137 // 27 => 29
138 // 28 => 14
139 // 29 => 30
140 // 30 => 15
141
142 // the procution correlation matrix is replaced with a random matrix
143 Real cTmp[31][31] = {
144 { 1,
145 0.0343941943887,
146 0.0419721265321,
147 -0.142932369598,
148 -0.386557229367,
149 0.295980379198,
150 0.239653818382,
151 -0.0763295458047,
152 0.212498186632,
153 0.118054743124,
154 -0.224766256083,
155 0.0853451819853,
156 -0.0511995874871,
157 0.174426283844,
158 -0.115460813133,
159 -0.0721582349166,
160 -0.214211359774,
161 -0.372084086492,
162 0.0469382929157,
163 0.30664207438,
164 -0.133293417835,
165 0.0548758513486,
166 0.189912198964,
167 -0.0998094066064,
168 0.116105136048,
169 -0.199567439204,
170 -0.179792210522,
171 -0.453605090893,
172 0.0344684113421,
173 -0.132400972608,
174 -0.0805829297654 },
175 { 0.0343941943887, 1,
176 -0.147392177981, 0.190600641536,
177 -0.145481590883, 0.294365640605,
178 0.0601368008482, -0.00283945283275,
179 -0.116431730925, -0.0716820259802,
180 0.00544003244763, -0.0758559072172,
181 -0.237919974947, 0.000824706024761,
182 0.179058963744, 0.132955192962,
183 -0.167456315193, -0.140212134815,
184 0.270173086657, 0.0461584452481,
185 0.174592984613, 0.479050202449,
186 0.231241635614, -0.365940995584,
187 -0.0300723876502, -0.0105021785277,
188 -0.0793226259723, 0.0364552498451,
189 -0.0428313590286, 0.00045179600518,
190 0.157958640397 },
191 { 0.0419721265321, -0.147392177981, 1,
192 -0.205721605587, 0.176351903075, -0.173886364182,
193 -0.176531389565, 0.0171718091121, -0.161928720878,
194 -0.223807424589, 0.227847712733, -0.129833355428,
195 -0.0765470112144, 0.0603061533934, -0.184873264163,
196 -0.0392532615883, 0.103720246234, 0.185194385726,
197 0.00352650332331, 0.147170801505, 0.138074664199,
198 -0.0750107965393, -0.075044498716, -0.135712263795,
199 0.0435965536933, -0.196699468487, -0.133209415874,
200 0.0669018267551, 0.0411062492118, 0.10827807138,
201 0.285547544897 },
202 { -0.142932369598, 0.190600641536, -0.205721605587, 1,
203 0.111438752029, -0.154504285602, -0.240592717398, 0.228776139817,
204 -0.0408638740298, 0.139994885856, 0.010428290396, -0.0266321253259,
205 0.235772909297, -0.0550148577982, 0.011581957914, -0.0958782780357,
206 -0.0356439790974, 0.167623910315, 0.282668618187, -0.116049244115,
207 0.0378447443195, 0.416830955389, 0.125613729312, 0.0751289225199,
208 0.0474611193829, 0.119515798352, -0.186354768062, 0.00463486576889,
209 0.0895319580574, -0.42296528782, -0.0250457680104 },
210 { -0.386557229367, -0.145481590883, 0.176351903075, 0.111438752029, 1,
211 -0.0948655518868, -0.156442491224, 0.091693504433, -0.037767000351, -0.235460535367,
212 0.0676834096513, -0.36550450905, 0.013058702437, 0.173947911446, -0.0894751146898,
213 -0.0697842787023, 0.330415682457, 0.105948381112, 0.213956029639, -0.306516644502,
214 0.03156673834, -0.0438700627351, -0.0471934284693, -0.0479093575566, -0.191764263322,
215 0.0691491923609, -0.0169112375186, 0.418856276254, -0.587952407744, -0.11074678055,
216 0.118830155093 },
217 { 0.295980379198, 0.294365640605, -0.173886364182, -0.154504285602, -0.0948655518868, 1,
218 0.312150303064, -0.296339376122, 0.222818035874, -0.333383472886, 0.045665647834, -0.178734828838,
219 0.233294477666, 0.00914551279587, 0.16991477323, 0.237871041338, -0.107953837139, -0.196472981313,
220 -0.197667927622, 0.243660580044, 0.283222098211, 0.255181424113, 0.0738214833113, -0.0875506146088,
221 0.0228176567117, -0.021839186816, -0.200983147135, 0.118339983121, -0.0380308812843, 0.0697554664965,
222 -0.290573412107 },
223 { 0.239653818382,
224 0.0601368008482,
225 -0.176531389565,
226 -0.240592717398,
227 -0.156442491224,
228 0.312150303064,
229 1,
230 0.16427616005,
231 0.187114559514,
232 -0.128567362633,
233 -0.0298087283209,
234 0.310220353467,
235 -0.155650952549,
236 -0.0907943245024,
237 0.150077574282,
238 0.233831100752,
239 0.14510564225,
240 -0.106158234925,
241 -0.186638489406,
242 0.108493899313,
243 0.186677617029,
244 0.154962485957,
245 0.0976503099009,
246 0.33619746008,
247 -0.312902806374,
248 0.0140051435466,
249 -0.190085542485,
250 0.123111359938,
251 -0.168127163542,
252 0.242451056895,
253 -0.232220701345 },
254 { -0.0763295458047, -0.00283945283275, 0.0171718091121, 0.228776139817,
255 0.091693504433, -0.296339376122, 0.16427616005, 1,
256 0.129840657268, 0.373604952144, -0.18155715237, 0.184536654159,
257 -0.12285053934, -0.103909813725, 0.178625377032, -0.127501582044,
258 0.184446540159, -0.127735616891, 0.147895324128, -0.0107588297873,
259 -0.0821799717041, -0.151013843371, 0.390822002417, -0.164177564227,
260 -0.199345876795, 0.154417641829, 0.00493479680788, 0.264074419131,
261 -0.106509969327, 0.132504591079, 0.118207101753 },
262 { 0.212498186632, -0.116431730925, -0.161928720878,
263 -0.0408638740298, -0.037767000351, 0.222818035874,
264 0.187114559514, 0.129840657268, 1,
265 0.108639498651, -0.111431570017, -0.132299603334,
266 0.129609578068, -0.277997943625, 0.0906182176236,
267 -0.0864325336051, 0.186001578615, -0.113884465526,
268 -0.0294749190212, 0.454853572071, -0.246249803796,
269 -0.0266738922467, 0.0933959821836, 0.224461162875,
270 0.0357834934973, 0.0616445434762, -0.276568357088,
271 -0.393316724461, -0.223125458693, 0.133084418997,
272 -0.0221629196894 },
273 { 0.118054743124, -0.0716820259802, -0.223807424589, 0.139994885856, -0.235460535367,
274 -0.333383472886, -0.128567362633, 0.373604952144, 0.108639498651, 1,
275 -0.095793838259, 0.190541253672, -0.107707903939, 0.12756217432, -0.117262111977,
276 -0.509787601852, -0.108689074131, -0.324588172992, 0.051847818326, 0.0322332954595,
277 -0.386223228013, -0.124632351583, 0.106212483012, -0.0762653306681, 0.014765861204,
278 -0.150505016721, 0.311501433571, -0.177761397412, -0.0501147422963, -0.288372982612,
279 -0.185072823068 },
280 { -0.224766256083,
281 0.00544003244763,
282 0.227847712733,
283 0.010428290396,
284 0.0676834096513,
285 0.045665647834,
286 -0.0298087283209,
287 -0.18155715237,
288 -0.111431570017,
289 -0.095793838259,
290 1,
291 0.0693613681381,
292 0.14249383007,
293 0.096010698022,
294 0.0329554088922,
295 0.167604841583,
296 -0.109041125342,
297 0.00514826039023,
298 -0.340130764259,
299 0.182645718058,
300 0.321991863536,
301 0.214142882681,
302 -0.0987553659026,
303 0.150628401488,
304 0.00422661848883,
305 0.109346488736,
306 0.23059270105,
307 0.140534087809,
308 -0.0173708508572,
309 0.0528427482968,
310 0.0182217569681 },
311 { 0.0853451819853, -0.0758559072172, -0.129833355428, -0.0266321253259,
312 -0.36550450905, -0.178734828838, 0.310220353467, 0.184536654159,
313 -0.132299603334, 0.190541253672, 0.0693613681381, 1,
314 -0.0132125282718, 0.0140768369271, 0.310955525226, -0.189708953222,
315 0.0488388998416, -0.0181791685819, 0.11515442249, -0.0712393291188,
316 -0.0911379512289, -0.117558064762, 0.0978226722782, 0.0494832889518,
317 -0.0176606846725, 0.250581766454, 0.209191012806, -0.143815875961,
318 -0.00668495669111, 0.0976950082078, 0.0252520373904 },
319 { -0.0511995874871,
320 -0.237919974947,
321 -0.0765470112144,
322 0.235772909297,
323 0.013058702437,
324 0.233294477666,
325 -0.155650952549,
326 -0.12285053934,
327 0.129609578068,
328 -0.107707903939,
329 0.14249383007,
330 -0.0132125282718,
331 1,
332 -0.101546509191,
333 0.145043037821,
334 0.0141222526045,
335 -0.239190286473,
336 -0.219267351706,
337 0.0493026087034,
338 -0.145364905371,
339 0.0244975164846,
340 0.187668533638,
341 -0.216542028379,
342 0.0784389764486,
343 0.207793807098,
344 -0.0149171885526,
345 0.154689284382,
346 0.0874179510403,
347 0.197509990962,
348 -0.0438009094431,
349 -0.00831859585832 },
350 { 0.174426283844, 0.000824706024761,
351 0.0603061533934, -0.0550148577982,
352 0.173947911446, 0.00914551279587,
353 -0.0907943245024, -0.103909813725,
354 -0.277997943625, 0.12756217432,
355 0.096010698022, 0.0140768369271,
356 -0.101546509191, 1,
357 -0.254967689473, 0.023478890628,
358 0.115201664433, -0.0570864596218,
359 -0.0552759708479, -0.147365625016,
360 0.0461995467521, -0.0168974295344,
361 -0.205845653683, -0.0381073980444,
362 -0.0927040293872, 0.0821202714574,
363 -0.0171498152037, -0.0834025047453,
364 -0.187260914639, -0.348707805644,
365 -0.364440606696 },
366 { -0.115460813133, 0.179058963744, -0.184873264163, 0.011581957914, -0.0894751146898,
367 0.16991477323, 0.150077574282, 0.178625377032, 0.0906182176236, -0.117262111977,
368 0.0329554088922, 0.310955525226, 0.145043037821, -0.254967689473, 1,
369 0.0748037899029, 0.294695159049, -0.213228245006, 0.128441907683, -0.0150217790452,
370 0.0480199310254, -0.0713509454034, 0.197367018953, -0.243142199375, -0.029497320023,
371 0.433216618742, 0.0396133169903, 0.103851408345, -0.219874832922, 0.296174894116,
372 0.168545305888 },
373 { -0.0721582349166, 0.132955192962, -0.0392532615883, -0.0958782780357,
374 -0.0697842787023, 0.237871041338, 0.233831100752, -0.127501582044,
375 -0.0864325336051, -0.509787601852, 0.167604841583, -0.189708953222,
376 0.0141222526045, 0.023478890628, 0.0748037899029, 1,
377 -0.010499616039, 0.0804925210972, -0.325690654432, -0.060487358233,
378 0.538581289688, 0.196496308155, -0.00839726071219, -0.0306510212363,
379 -0.060101906245, 0.0793563779709, -0.14609815746, 0.186079456094,
380 0.230110905512, 0.143609506491, -0.0255809432735 },
381 { -0.214211359774,
382 -0.167456315193,
383 0.103720246234,
384 -0.0356439790974,
385 0.330415682457,
386 -0.107953837139,
387 0.14510564225,
388 0.184446540159,
389 0.186001578615,
390 -0.108689074131,
391 -0.109041125342,
392 0.0488388998416,
393 -0.239190286473,
394 0.115201664433,
395 0.294695159049,
396 -0.010499616039,
397 1,
398 0.0636415350089,
399 0.198977446582,
400 0.102363853401,
401 0.145107868245,
402 -0.386835660762,
403 0.0923139397147,
404 0.200427396567,
405 -0.510849948347,
406 0.492499933089,
407 -0.221537617801,
408 -0.0594708004309,
409 -0.372450613443,
410 -0.0359700742084,
411 0.102546226539 },
412 { -0.372084086492, -0.140212134815, 0.185194385726, 0.167623910315, 0.105948381112, -0.196472981313,
413 -0.106158234925, -0.127735616891, -0.113884465526, -0.324588172992, 0.00514826039023, -0.0181791685819,
414 -0.219267351706, -0.0570864596218, -0.213228245006, 0.0804925210972, 0.0636415350089, 1,
415 -0.245275780278, -0.052398080821, -0.0188922810343, 0.0085014187696, -0.0457942205268, 0.161812363359,
416 0.236909237629, 0.244605289825, -0.20847963897, -0.0224010202566, 0.184642764044, 0.0383411294219,
417 -0.107154013475 },
418 { 0.0469382929157,
419 0.270173086657,
420 0.00352650332331,
421 0.282668618187,
422 0.213956029639,
423 -0.197667927622,
424 -0.186638489406,
425 0.147895324128,
426 -0.0294749190212,
427 0.051847818326,
428 -0.340130764259,
429 0.11515442249,
430 0.0493026087034,
431 -0.0552759708479,
432 0.128441907683,
433 -0.325690654432,
434 0.198977446582,
435 -0.245275780278,
436 1,
437 -0.247362833882,
438 -0.193578615193,
439 -0.0105721360587,
440 0.14336132262,
441 -0.112587281635,
442 -0.171469357693,
443 0.100772472825,
444 0.0751101396305,
445 0.0700089923819,
446 -0.248914435569,
447 0.0263247635683,
448 0.451050068349 },
449 { 0.30664207438, 0.0461584452481, 0.147170801505, -0.116049244115, -0.306516644502,
450 0.243660580044, 0.108493899313, -0.0107588297873, 0.454853572071, 0.0322332954595,
451 0.182645718058, -0.0712393291188, -0.145364905371, -0.147365625016, -0.0150217790452,
452 -0.060487358233, 0.102363853401, -0.052398080821, -0.247362833882, 1,
453 0.136263767432, -0.137495220906, -0.127307183268, 0.0972788938582, 0.00258934288855,
454 -0.130331299046, -0.428102669619, -0.263740815975, 0.0737931248832, 0.301730685794,
455 -0.110280327757 },
456 { -0.133293417835, 0.174592984613, 0.138074664199,
457 0.0378447443195, 0.03156673834, 0.283222098211,
458 0.186677617029, -0.0821799717041, -0.246249803796,
459 -0.386223228013, 0.321991863536, -0.0911379512289,
460 0.0244975164846, 0.0461995467521, 0.0480199310254,
461 0.538581289688, 0.145107868245, -0.0188922810343,
462 -0.193578615193, 0.136263767432, 1,
463 0.0250867014821, -0.207548146929, 0.141487666396,
464 -0.332927391225, 0.043757104046, -0.26277621567,
465 0.28995584194, 0.13757556845, -0.061923788279,
466 0.0464984161357 },
467 { 0.0548758513486, 0.479050202449,
468 -0.0750107965393, 0.416830955389,
469 -0.0438700627351, 0.255181424113,
470 0.154962485957, -0.151013843371,
471 -0.0266738922467, -0.124632351583,
472 0.214142882681, -0.117558064762,
473 0.187668533638, -0.0168974295344,
474 -0.0713509454034, 0.196496308155,
475 -0.386835660762, 0.0085014187696,
476 -0.0105721360587, -0.137495220906,
477 0.0250867014821, 1,
478 0.148426221032, -0.0796451648888,
479 0.121998419258, -0.120561962297,
480 0.0039300328991, -0.0616564684715,
481 0.0834127185137, -0.194091860738,
482 -0.0540900287065 },
483 { 0.189912198964,
484 0.231241635614,
485 -0.075044498716,
486 0.125613729312,
487 -0.0471934284693,
488 0.0738214833113,
489 0.0976503099009,
490 0.390822002417,
491 0.0933959821836,
492 0.106212483012,
493 -0.0987553659026,
494 0.0978226722782,
495 -0.216542028379,
496 -0.205845653683,
497 0.197367018953,
498 -0.00839726071219,
499 0.0923139397147,
500 -0.0457942205268,
501 0.14336132262,
502 -0.127307183268,
503 -0.207548146929,
504 0.148426221032,
505 1,
506 -0.197544922079,
507 -0.0620733221402,
508 0.337598014925,
509 0.115127292041,
510 -0.191005066833,
511 -0.0542551151481,
512 -0.150856466315,
513 0.287965489293 },
514 { -0.0998094066064, -0.365940995584, -0.135712263795, 0.0751289225199, -0.0479093575566, -0.0875506146088,
515 0.33619746008, -0.164177564227, 0.224461162875, -0.0762653306681, 0.150628401488, 0.0494832889518,
516 0.0784389764486, -0.0381073980444, -0.243142199375, -0.0306510212363, 0.200427396567, 0.161812363359,
517 -0.112587281635, 0.0972788938582, 0.141487666396, -0.0796451648888, -0.197544922079, 1,
518 -0.455928132901, -0.0349650249016, -0.147487712981, -0.123072528825, 0.0016310683966, -0.0929856384075,
519 -0.0844827518471 },
520 { 0.116105136048, -0.0300723876502, 0.0435965536933, 0.0474611193829, -0.191764263322,
521 0.0228176567117, -0.312902806374, -0.199345876795, 0.0357834934973, 0.014765861204,
522 0.00422661848883, -0.0176606846725, 0.207793807098, -0.0927040293872, -0.029497320023,
523 -0.060101906245, -0.510849948347, 0.236909237629, -0.171469357693, 0.00258934288855,
524 -0.332927391225, 0.121998419258, -0.0620733221402, -0.455928132901, 1,
525 -0.0366860627562, 0.0789958683979, -0.130701036026, 0.25671818269, 0.0196168003514,
526 -0.102190074804 },
527 { -0.199567439204, -0.0105021785277,
528 -0.196699468487, 0.119515798352,
529 0.0691491923609, -0.021839186816,
530 0.0140051435466, 0.154417641829,
531 0.0616445434762, -0.150505016721,
532 0.109346488736, 0.250581766454,
533 -0.0149171885526, 0.0821202714574,
534 0.433216618742, 0.0793563779709,
535 0.492499933089, 0.244605289825,
536 0.100772472825, -0.130331299046,
537 0.043757104046, -0.120561962297,
538 0.337598014925, -0.0349650249016,
539 -0.0366860627562, 1,
540 -0.0794978681331, -0.0982755084996,
541 -0.206145124721, 0.084681240391,
542 -0.0748773856947 },
543 { -0.179792210522, -0.0793226259723, -0.133209415874,
544 -0.186354768062, -0.0169112375186, -0.200983147135,
545 -0.190085542485, 0.00493479680788, -0.276568357088,
546 0.311501433571, 0.23059270105, 0.209191012806,
547 0.154689284382, -0.0171498152037, 0.0396133169903,
548 -0.14609815746, -0.221537617801, -0.20847963897,
549 0.0751101396305, -0.428102669619, -0.26277621567,
550 0.0039300328991, 0.115127292041, -0.147487712981,
551 0.0789958683979, -0.0794978681331, 1,
552 0.166530515474, -0.00626506702444, -0.105755638618,
553 0.17213920952 },
554 { -0.453605090893, 0.0364552498451, 0.0669018267551, 0.00463486576889,
555 0.418856276254, 0.118339983121, 0.123111359938, 0.264074419131,
556 -0.393316724461, -0.177761397412, 0.140534087809, -0.143815875961,
557 0.0874179510403, -0.0834025047453, 0.103851408345, 0.186079456094,
558 -0.0594708004309, -0.0224010202566, 0.0700089923819, -0.263740815975,
559 0.28995584194, -0.0616564684715, -0.191005066833, -0.123072528825,
560 -0.130701036026, -0.0982755084996, 0.166530515474, 1,
561 -0.170804441061, 0.392158807614, -0.0667901382994 },
562 { 0.0344684113421,
563 -0.0428313590286,
564 0.0411062492118,
565 0.0895319580574,
566 -0.587952407744,
567 -0.0380308812843,
568 -0.168127163542,
569 -0.106509969327,
570 -0.223125458693,
571 -0.0501147422963,
572 -0.0173708508572,
573 -0.00668495669111,
574 0.197509990962,
575 -0.187260914639,
576 -0.219874832922,
577 0.230110905512,
578 -0.372450613443,
579 0.184642764044,
580 -0.248914435569,
581 0.0737931248832,
582 0.13757556845,
583 0.0834127185137,
584 -0.0542551151481,
585 0.0016310683966,
586 0.25671818269,
587 -0.206145124721,
588 -0.00626506702444,
589 -0.170804441061,
590 1,
591 -0.0642244501279,
592 0.116777659542 },
593 { -0.132400972608, 0.00045179600518, 0.10827807138, -0.42296528782, -0.11074678055, 0.0697554664965,
594 0.242451056895, 0.132504591079, 0.133084418997, -0.288372982612, 0.0528427482968, 0.0976950082078,
595 -0.0438009094431, -0.348707805644, 0.296174894116, 0.143609506491, -0.0359700742084, 0.0383411294219,
596 0.0263247635683, 0.301730685794, -0.061923788279, -0.194091860738, -0.150856466315, -0.0929856384075,
597 0.0196168003514, 0.084681240391, -0.105755638618, 0.392158807614, -0.0642244501279, 1,
598 0.0494702308271 },
599 { -0.0805829297654,
600 0.157958640397,
601 0.285547544897,
602 -0.0250457680104,
603 0.118830155093,
604 -0.290573412107,
605 -0.232220701345,
606 0.118207101753,
607 -0.0221629196894,
608 -0.185072823068,
609 0.0182217569681,
610 0.0252520373904,
611 -0.00831859585832,
612 -0.364440606696,
613 0.168545305888,
614 -0.0255809432735,
615 0.102546226539,
616 -0.107154013475,
617 0.451050068349,
618 -0.110280327757,
619 0.0464984161357,
620 -0.0540900287065,
621 0.287965489293,
622 -0.0844827518471,
623 -0.102190074804,
624 -0.0748773856947,
625 0.17213920952,
626 -0.0667901382994,
627 0.116777659542,
628 0.0494702308271,
629 1 },
630 };
631
632 rho = Matrix(31, 31);
633 for (Size i = 0; i < 31; ++i) {
634 for (Size j = 0; j < 31; ++j) {
635 rho[mapping[i]][mapping[j]] = cTmp[i][j];
636 }
637 }
638
639 // =========================================
640 // IR components
641 // =========================================
642
643 Period irTen[] = { 3 * Months, 6 * Months, 1 * Years, 4 * Years, 6 * Years, 8 * Years,
644 10 * Years, 12 * Years, 14 * Years, 16 * Years, 24 * Years, 28 * Years,
645 30 * Years, 35 * Years, 40 * Years, 45 * Years, 50 * Years };
646
647 Array irTimes(LENGTH(irTen));
648 for (Size i = 0; i < LENGTH(irTen); ++i) {
649 irTimes[i] = ActualActual(ActualActual::ISDA).yearFraction(refDate, TARGET().advance(refDate, irTen[i]));
650 }
651 // for parametrization set up (without last time)
652 Array irTimes2(irTimes.begin(), irTimes.end() - 1);
653
654 QuantLib::ext::shared_ptr<IrLgm1fParametrization> tmpIr;
655
656 // dummy yts (we check covariances here for which the yts does not
657 // matter)
658 Handle<YieldTermStructure> yts(
659 QuantLib::ext::make_shared<FlatForward>(refDate, 0.02, ActualActual(ActualActual::ISDA)));
660
661 Array alpha(LENGTH(irTen)), lambda(LENGTH(irTen));
662
663 // IR #1 EUR
664 Real H_EUR[] = { 0.24842958, 0.49885636, 0.99512038, 3.9210561, 5.8235466, 7.6883654,
665 9.5162582, 11.307956, 13.064176, 14.785621, 21.337214, 24.421626,
666 25.918178, 29.531191, 32.967995, 36.237252, 39.346934 };
667 Real zeta_EUR[] = { 9.0701982e-06, 1.0608339e-05, 1.1620875e-05, 0.00015177493, 0.00031122807, 0.00046892033,
668 0.00061743761, 0.00075125711, 0.00089906517, 0.001101485, 0.0016151376, 0.0018395256,
669 0.0020329435, 0.0026210991, 0.0032963998, 0.004125193, 0.0045825323 };
670 for (Size i = 0; i < LENGTH(irTen); ++i) {
671 alpha[i] = std::sqrt((zeta_EUR[i] - (i == 0 ? 0.0 : zeta_EUR[i - 1])) /
672 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
673 lambda[i] =
674 std::sqrt((H_EUR[i] - (i == 0 ? 0.0 : H_EUR[i - 1])) / (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
675 }
676 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(EURCurrency(), yts, irTimes2, alpha, irTimes2,
677 lambda);
678 parametrizations.push_back(tmpIr);
679
680 // IR #2 GBP (H is shared between all currencies)
681 Real zeta_GBP[] = { 5.3989367e-06, 9.8331458e-06, 4.6388054e-05, 0.00040863507, 0.00062437912, 0.00076368123,
682 0.00083880053, 0.00097274237, 0.0011247902, 0.0011807996, 0.0016212442, 0.0016897153,
683 0.0019250142, 0.0023629707, 0.0028444473, 0.0033775638, 0.0035846398 };
684 for (Size i = 0; i < LENGTH(irTen); ++i) {
685 alpha[i] = std::sqrt((zeta_GBP[i] - (i == 0 ? 0.0 : zeta_GBP[i - 1])) /
686 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
687 }
688 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(GBPCurrency(), yts, irTimes2, alpha, irTimes2,
689 lambda);
690 parametrizations.push_back(tmpIr);
691
692 // IR #3 USD
693 Real zeta_USD[] = { 2.0116489e-06, 9.869679e-06, 3.8294263e-05, 0.00035235619, 0.00056544819, 0.00071428218,
694 0.00086773977, 0.00096413044, 0.0010223302, 0.0011499527, 0.0015443309, 0.0017400941,
695 0.0019520896, 0.0024675239, 0.0030556253, 0.0037297585, 0.0040647036 };
696 for (Size i = 0; i < LENGTH(irTen); ++i) {
697 alpha[i] = std::sqrt((zeta_USD[i] - (i == 0 ? 0.0 : zeta_USD[i - 1])) /
698 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
699 }
700 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(USDCurrency(), yts, irTimes2, alpha, irTimes2,
701 lambda);
702 parametrizations.push_back(tmpIr);
703
704 // IR #4 JPY
705 Real zeta_JPY[] = { 2.3553293e-07, 4.7232546e-07, 1.6760723e-06, 2.7562061e-05, 7.5069821e-05, 0.00016052372,
706 0.00032273232, 0.00070327448, 0.00082690882, 0.0014144869, 0.0019465284, 0.0019707646,
707 0.00219778, 0.0026321698, 0.0030966507, 0.0035997538, 0.0037455693 };
708 for (Size i = 0; i < LENGTH(irTen); ++i) {
709 alpha[i] = std::sqrt((zeta_JPY[i] - (i == 0 ? 0.0 : zeta_JPY[i - 1])) /
710 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
711 }
712 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(JPYCurrency(), yts, irTimes2, alpha, irTimes2,
713 lambda);
714 parametrizations.push_back(tmpIr);
715
716 // IR #5 AUD
717 Real zeta_AUD[] = { 7.7367295e-06, 1.3455117e-05, 3.6148337e-05, 0.00035739546, 0.0006449375, 0.0010106854,
718 0.0014263234, 0.001839049, 0.0021976553, 0.0027602048, 0.0038615771, 0.0038724338,
719 0.0043593179, 0.0054144983, 0.0065917297, 0.0079097947, 0.0086340945 };
720 for (Size i = 0; i < LENGTH(irTen); ++i) {
721 alpha[i] = std::sqrt((zeta_AUD[i] - (i == 0 ? 0.0 : zeta_AUD[i - 1])) /
722 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
723 }
724 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(AUDCurrency(), yts, irTimes2, alpha, irTimes2,
725 lambda);
726 parametrizations.push_back(tmpIr);
727
728 // IR #6 CAD
729 Real zeta_CAD[] = { 7.1764671e-06, 1.199943e-05, 3.0336942e-05, 0.00023188566, 0.00038850625, 0.00050854554,
730 0.0005611467, 0.00071498642, 0.0008629815, 0.00087117906, 0.0010263932, 0.0011534502,
731 0.0013161557, 0.0016666467, 0.0020675357, 0.0025277164, 0.00275934 };
732 for (Size i = 0; i < LENGTH(irTen); ++i) {
733 alpha[i] = std::sqrt((zeta_CAD[i] - (i == 0 ? 0.0 : zeta_CAD[i - 1])) /
734 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
735 }
736 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(CADCurrency(), yts, irTimes2, alpha, irTimes2,
737 lambda);
738 parametrizations.push_back(tmpIr);
739
740 // IR #7 CHF
741 Real zeta_CHF[] = { 2.0285111e-06, 1.1611047e-05, 1.4434095e-05, 4.6520687e-05, 0.00031520268, 0.00067093245,
742 0.00078748667, 0.0010554702, 0.0011654964, 0.0014978801, 0.0018047495, 0.0018047762,
743 0.0019504756, 0.0022601499, 0.0025871501, 0.0029619175, 0.0031895455 };
744 for (Size i = 0; i < LENGTH(irTen); ++i) {
745 alpha[i] = std::sqrt((zeta_CHF[i] - (i == 0 ? 0.0 : zeta_CHF[i - 1])) /
746 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
747 }
748 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(CHFCurrency(), yts, irTimes2, alpha, irTimes2,
749 lambda);
750 parametrizations.push_back(tmpIr);
751
752 // IR #8 DKK
753 Real zeta_DKK[] = { 3.95942e-06, 1.6524019e-05, 2.7177507e-05, 0.00029766543, 0.00065437464, 0.001221066,
754 0.0017487336, 0.0021895397, 0.0025464983, 0.0027541051, 0.0027541403, 0.0028892292,
755 0.0031707705, 0.0037313519, 0.0043215627, 0.0049612987, 0.0052460193 };
756 for (Size i = 0; i < LENGTH(irTen); ++i) {
757 alpha[i] = std::sqrt((zeta_DKK[i] - (i == 0 ? 0.0 : zeta_DKK[i - 1])) /
758 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
759 }
760 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(DKKCurrency(), yts, irTimes2, alpha, irTimes2,
761 lambda);
762 parametrizations.push_back(tmpIr);
763
764 // IR #9 NOK
765 Real zeta_NOK[] = { 2.1747207e-05, 4.2144995e-05, 4.2145974e-05, 0.00036357391, 0.00054458124, 0.00074627758,
766 0.00081604641, 0.00092208188, 0.0011002273, 0.0012189063, 0.0018979681, 0.0019753582,
767 0.0022190637, 0.0027605153, 0.0033563053, 0.0040315714, 0.0044332994 };
768 for (Size i = 0; i < LENGTH(irTen); ++i) {
769 alpha[i] = std::sqrt((zeta_NOK[i] - (i == 0 ? 0.0 : zeta_NOK[i - 1])) /
770 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
771 }
772 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(NOKCurrency(), yts, irTimes2, alpha, irTimes2,
773 lambda);
774 parametrizations.push_back(tmpIr);
775
776 // IR #10 PLN
777 Real zeta_PLN[] = { 9.0701982e-06, 1.0608339e-05, 1.1620875e-05, 0.00015177493, 0.00031122807, 0.00046892033,
778 0.00061743761, 0.00075125711, 0.00089906517, 0.001101485, 0.0016151376, 0.0018395256,
779 0.0020329435, 0.0026210991, 0.0032963998, 0.004125193, 0.0045825323 };
780 for (Size i = 0; i < LENGTH(irTen); ++i) {
781 alpha[i] = std::sqrt((zeta_PLN[i] - (i == 0 ? 0.0 : zeta_PLN[i - 1])) /
782 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
783 }
784 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(PLNCurrency(), yts, irTimes2, alpha, irTimes2,
785 lambda);
786 parametrizations.push_back(tmpIr);
787
788 // IR #11 SEK
789 Real zeta_SEK[] = { 6.330515e-06, 7.5521582e-06, 9.9440922e-06, 0.00032860183, 0.0005331322, 0.00071660054,
790 0.00086542894, 0.0011098021, 0.0013293011, 0.0017246094, 0.0027609916, 0.0027611132,
791 0.0030808796, 0.0038392582, 0.0046789792, 0.005628121, 0.0063423051 };
792 for (Size i = 0; i < LENGTH(irTen); ++i) {
793 alpha[i] = std::sqrt((zeta_SEK[i] - (i == 0 ? 0.0 : zeta_SEK[i - 1])) /
794 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
795 }
796 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(SEKCurrency(), yts, irTimes2, alpha, irTimes2,
797 lambda);
798 parametrizations.push_back(tmpIr);
799
800 // IR #12 SGD
801 Real zeta_SGD[] = { 9.0701982e-06, 1.0608339e-05, 1.1620875e-05, 0.00015177493, 0.00031122807, 0.00046892033,
802 0.00061743761, 0.00075125711, 0.00089906517, 0.001101485, 0.0016151376, 0.0018395256,
803 0.0020329435, 0.0026210991, 0.0032963998, 0.004125193, 0.0045825323 };
804 for (Size i = 0; i < LENGTH(irTen); ++i) {
805 alpha[i] = std::sqrt((zeta_SGD[i] - (i == 0 ? 0.0 : zeta_SGD[i - 1])) /
806 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
807 }
808 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(SGDCurrency(), yts, irTimes2, alpha, irTimes2,
809 lambda);
810 parametrizations.push_back(tmpIr);
811
812 // IR #13 INR
813 Real zeta_INR[] = { 9.0701982e-06, 1.0608339e-05, 1.1620875e-05, 0.00015177493, 0.00031122807, 0.00046892033,
814 0.00061743761, 0.00075125711, 0.00089906517, 0.001101485, 0.0016151376, 0.0018395256,
815 0.0020329435, 0.0026210991, 0.0032963998, 0.004125193, 0.0045825323 };
816 for (Size i = 0; i < LENGTH(irTen); ++i) {
817 alpha[i] = std::sqrt((zeta_INR[i] - (i == 0 ? 0.0 : zeta_INR[i - 1])) /
818 (irTimes[i] - (i == 0 ? 0.0 : irTimes[i - 1])));
819 }
820 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(INRCurrency(), yts, irTimes2, alpha, irTimes2,
821 lambda);
822 parametrizations.push_back(tmpIr);
823
824 // =========================================
825 // Inflation RR (as IR component here)
826 // =========================================
827
828 Period inflTen[] = { 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years,
829 12 * Years, 15 * Years, 20 * Years, 30 * Years };
830
831 Array inflTimes(LENGTH(inflTen));
832 for (Size i = 0; i < LENGTH(inflTen); ++i) {
833 inflTimes[i] = ActualActual(ActualActual::ISDA).yearFraction(refDate, TARGET().advance(refDate, inflTen[i]));
834 }
835 // for parametrization set up (without last time)
836 Array inflTimes2(inflTimes.begin(), inflTimes.end() - 1);
837 Array alphaInfl(LENGTH(inflTen)), lambdaInfl(LENGTH(inflTen));
838
839 // IR #14 BGL = RR INFL EUR
840
841 Real H_BGL[] = { 0.473128, 1.068300, 1.555252, 2.527081, 3.611487, 6.076270, 7.369295, 9.429210, 13.319564 };
842 Real alpha_BGL[] = { 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 };
843 for (Size i = 0; i < LENGTH(inflTen); ++i) {
844 lambdaInfl[i] = std::sqrt((H_BGL[i] - (i == 0 ? 0.0 : H_BGL[i - 1])) /
845 (inflTimes[i] - (i == 0 ? 0.0 : inflTimes[i - 1])));
846 alphaInfl[i] = alpha_BGL[i];
847 }
848 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(BGLCurrency(), yts, inflTimes2, alphaInfl,
849 inflTimes2, lambdaInfl);
850 parametrizations.push_back(tmpIr);
851
852 // IR #16 BYR = RR INFL UK
853
854 Real H_BYR[] = { 1.062214, 2.161263, 3.073939, 4.861583, 6.515747, 10.324476, 12.390876, 15.568734, 21.145007 };
855 Real alpha_BYR[] = { 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 };
856 for (Size i = 0; i < LENGTH(inflTen); ++i) {
857 lambdaInfl[i] = std::sqrt((H_BYR[i] - (i == 0 ? 0.0 : H_BYR[i - 1])) /
858 (inflTimes[i] - (i == 0 ? 0.0 : inflTimes[i - 1])));
859 alphaInfl[i] = alpha_BYR[i];
860 }
861 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(BYRCurrency(), yts, inflTimes2, alphaInfl,
862 inflTimes2, lambdaInfl);
863 parametrizations.push_back(tmpIr);
864
865 // IR #17 BYR = RR INFL FR
866
867 Real H_CZK[] = { 1.024666, 1.290138, 1.655453, 2.250962, 2.843277, 3.684875, 3.842543, 4.000118, 4.000213 };
868 Real alpha_CZK[] = { 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02, 0.02 };
869 for (Size i = 0; i < LENGTH(inflTen); ++i) {
870 lambdaInfl[i] = std::sqrt((H_CZK[i] - (i == 0 ? 0.0 : H_CZK[i - 1])) /
871 (inflTimes[i] - (i == 0 ? 0.0 : inflTimes[i - 1])));
872 alphaInfl[i] = alpha_CZK[i];
873 }
874 tmpIr = QuantLib::ext::make_shared<IrLgm1fPiecewiseLinearParametrization>(CZKCurrency(), yts, inflTimes2, alphaInfl,
875 inflTimes2, lambdaInfl);
876 parametrizations.push_back(tmpIr);
877
878 // =========================================
879 // FX components
880 // =========================================
881
882 Period fxTen[] = { 3 * Months, 6 * Months, 9 * Months, 12 * Months,
883 15 * Months, 18 * Months, 2 * Years, 3 * Years };
884
885 Array fxTimes(LENGTH(fxTen));
886 for (Size i = 0; i < LENGTH(fxTen); ++i) {
887 fxTimes[i] = ActualActual(ActualActual::ISDA).yearFraction(refDate, TARGET().advance(refDate, fxTen[i]));
888 }
889 // for parametrization set up (without last time)
890 Array fxTimes2(fxTimes.begin(), fxTimes.end() - 1);
891
892 QuantLib::ext::shared_ptr<FxBsParametrization> tmpFx;
893 Array sigma(LENGTH(fxTen));
894
895 Handle<Quote> dummyFxSpot(QuantLib::ext::make_shared<SimpleQuote>(1.0));
896
897 // FX #1 GBP
898
899 Real sigma_GBP[] = { 0.080781, 0.088930, 0.098602, 0.105432, 0.100682, 0.100443, 0.100033, 0.103945 };
900 for (Size i = 0; i < LENGTH(fxTen); ++i) {
901 sigma[i] = sigma_GBP[i];
902 }
903 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(GBPCurrency(), dummyFxSpot, fxTimes2, sigma);
904 parametrizations.push_back(tmpFx);
905
906 // FX #2 USD
907
908 Real sigma_USD[] = { 0.100489, 0.100483, 0.101916, 0.100875, 0.099272, 0.099088, 0.098720, 0.105264 };
909 for (Size i = 0; i < LENGTH(fxTen); ++i) {
910 sigma[i] = sigma_USD[i];
911 }
912 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(USDCurrency(), dummyFxSpot, fxTimes2, sigma);
913 parametrizations.push_back(tmpFx);
914
915 // FX #3 JPY
916
917 Real sigma_JPY[] = { 0.088486, 0.100977, 0.109587, 0.112013, 0.115858, 0.115846, 0.115711, 0.122524 };
918 for (Size i = 0; i < LENGTH(fxTen); ++i) {
919 sigma[i] = sigma_JPY[i];
920 }
921 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(JPYCurrency(), dummyFxSpot, fxTimes2, sigma);
922 parametrizations.push_back(tmpFx);
923
924 // FX #4 AUD
925
926 Real sigma_AUD[] = { 0.125030, 0.123755, 0.123786, 0.122953, 0.123691, 0.123537, 0.123154, 0.121826 };
927 for (Size i = 0; i < LENGTH(fxTen); ++i) {
928 sigma[i] = sigma_AUD[i];
929 }
930 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(AUDCurrency(), dummyFxSpot, fxTimes2, sigma);
931 parametrizations.push_back(tmpFx);
932
933 // FX #5 CAD
934
935 Real sigma_CAD[] = { 0.113583, 0.109568, 0.108982, 0.109527, 0.110234, 0.110095, 0.109754, 0.108610 };
936 for (Size i = 0; i < LENGTH(fxTen); ++i) {
937 sigma[i] = sigma_CAD[i];
938 }
939 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(CADCurrency(), dummyFxSpot, fxTimes2, sigma);
940 parametrizations.push_back(tmpFx);
941
942 // FX #6 CHF
943
944 Real sigma_CHF[] = { 0.066449, 0.074224, 0.080625, 0.083341, 0.092719, 0.092715, 0.092488, 0.108220 };
945 for (Size i = 0; i < LENGTH(fxTen); ++i) {
946 sigma[i] = sigma_CHF[i];
947 }
948 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(CHFCurrency(), dummyFxSpot, fxTimes2, sigma);
949 parametrizations.push_back(tmpFx);
950
951 // FX #7 DKK
952
953 Real sigma_DKK[] = { 0.012913, 0.013110, 0.012621, 0.015782, 0.024053, 0.023408, 0.021574, 0.000000 };
954 for (Size i = 0; i < LENGTH(fxTen); ++i) {
955 sigma[i] = sigma_DKK[i];
956 }
957 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(DKKCurrency(), dummyFxSpot, fxTimes2, sigma);
958 parametrizations.push_back(tmpFx);
959
960 // FX #8 NOK
961
962 Real sigma_NOK[] = { 0.099987, 0.099916, 0.099795, 0.099668, 0.099532, 0.099321, 0.098811, 0.097166 };
963 for (Size i = 0; i < LENGTH(fxTen); ++i) {
964 sigma[i] = sigma_NOK[i];
965 }
966 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(NOKCurrency(), dummyFxSpot, fxTimes2, sigma);
967 parametrizations.push_back(tmpFx);
968
969 // FX #9 PLN
970
971 Real sigma_PLN[] = { 0.065094, 0.069539, 0.072197, 0.073313, 0.069963, 0.069777, 0.069391, 0.068027 };
972 for (Size i = 0; i < LENGTH(fxTen); ++i) {
973 sigma[i] = sigma_PLN[i];
974 }
975
976 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(PLNCurrency(), dummyFxSpot, fxTimes2, sigma);
977 parametrizations.push_back(tmpFx);
978
979 // FX #10 SEK
980
981 Real sigma_SEK[] = { 0.068977, 0.078492, 0.082604, 0.085282, 0.084029, 0.083851, 0.083398, 0.082871 };
982 for (Size i = 0; i < LENGTH(fxTen); ++i) {
983 sigma[i] = sigma_SEK[i];
984 }
985
986 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(SEKCurrency(), dummyFxSpot, fxTimes2, sigma);
987 parametrizations.push_back(tmpFx);
988
989 // FX #11 SGD
990
991 Real sigma_SGD[] = { 0.149995, 0.149970, 0.149935, 0.149903, 0.149861, 0.149791, 0.149611, 0.148984 };
992 for (Size i = 0; i < LENGTH(fxTen); ++i) {
993 sigma[i] = sigma_SGD[i];
994 }
995
996 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(SGDCurrency(), dummyFxSpot, fxTimes2, sigma);
997 parametrizations.push_back(tmpFx);
998
999 // FX #12 INR
1000
1001 Real sigma_INR[] = { 0.100486, 0.100462, 0.101885, 0.100864, 0.099298, 0.099177, 0.098906, 0.105704 };
1002 for (Size i = 0; i < LENGTH(fxTen); ++i) {
1003 sigma[i] = sigma_INR[i];
1004 }
1005
1006 tmpFx = QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(INRCurrency(), dummyFxSpot, fxTimes2, sigma);
1007 parametrizations.push_back(tmpFx);
1008
1009 // FX #13, 14, 15 Inflation CPI EUR, UK, FR
1010
1011 Array notimes(0);
1012 Array sigma_CPI(1, 0.0075);
1013
1014 tmpFx =
1015 QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(BGLCurrency(), dummyFxSpot, notimes, sigma_CPI);
1016 parametrizations.push_back(tmpFx);
1017 tmpFx =
1018 QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(BYRCurrency(), dummyFxSpot, notimes, sigma_CPI);
1019 parametrizations.push_back(tmpFx);
1020 tmpFx =
1021 QuantLib::ext::make_shared<FxBsPiecewiseConstantParametrization>(CZKCurrency(), dummyFxSpot, notimes, sigma_CPI);
1022 parametrizations.push_back(tmpFx);
1023
1024 // =========================================
1025 // CrossAsset model
1026 // =========================================
1027
1028 xmodelExact =
1029 QuantLib::ext::make_shared<CrossAssetModel>(parametrizations, rho, SalvagingAlgorithm::None, IrModel::Measure::LGM,
1030 CrossAssetModel::Discretization::Exact);
1031 xmodelEuler =
1032 QuantLib::ext::make_shared<CrossAssetModel>(parametrizations, rho, SalvagingAlgorithm::None, IrModel::Measure::LGM,
1033 CrossAssetModel::Discretization::Euler);
1034 }
1035
1036 SavedSettings backup;
1037 Date refDate;
1038 Size mapping[31], invMapping[31];
1039 Real c[31][31];
1040 Matrix rho;
1041 Handle<YieldTermStructure> yts;
1042 std::vector<QuantLib::ext::shared_ptr<Parametrization> > parametrizations;
1043 QuantLib::ext::shared_ptr<CrossAssetModel> xmodelExact, xmodelEuler;
1044};
1045
1046} // namespace
1047
1048BOOST_FIXTURE_TEST_SUITE(QuantExtTestSuite, qle::test::TopLevelFixture)
1049
1050BOOST_AUTO_TEST_SUITE(CrossAssetModelTest2)
1051
1052BOOST_AUTO_TEST_CASE(testLgm31fPositiveCovariance) {
1053
1054 BOOST_TEST_MESSAGE("Testing for positive semidefinite covariance matrices "
1055 "in Ccy LGM 31F model...");
1056
1057 Lgm31fTestData d;
1058
1059 // check eigenvalues of rho (this check is done in the model constructor
1060 // as well, we cross check this here)
1061
1062 SymmetricSchurDecomposition ssd(d.rho);
1063 for (Size i = 0; i < ssd.eigenvalues().size(); ++i) {
1064 if (ssd.eigenvalues()[i] < 0.0) {
1065 BOOST_ERROR("negative eigenvalue in input matrix (#" << i << ", " << ssd.eigenvalues()[i]);
1066 }
1067 }
1068
1069 // =========================================
1070 // time grid for RFE
1071 // =========================================
1072
1073 std::vector<Time> simTimes_;
1074 simTimes_.push_back(0.0);
1075 for (Size i = 1; i <= 118; ++i) {
1076 Date tmp = TARGET().advance(d.refDate, i * Months);
1077 simTimes_.push_back(ActualActual(ActualActual::ISDA).yearFraction(d.refDate, tmp));
1078 }
1079 for (Size i = 1; i <= 40; ++i) {
1080 Date tmp = TARGET().advance(d.refDate, (117 + 3 * i) * Months);
1081 simTimes_.push_back(ActualActual(ActualActual::ISDA).yearFraction(d.refDate, tmp));
1082 }
1083 for (Size i = 1; i <= 31; ++i) {
1084 Date tmp = TARGET().advance(d.refDate, (19 + i) * Years);
1085 simTimes_.push_back(ActualActual(ActualActual::ISDA).yearFraction(d.refDate, tmp));
1086 }
1087 for (Size i = 1; i <= 10; ++i) {
1088 Date tmp = TARGET().advance(d.refDate, (50 + i * 5) * Years);
1089 simTimes_.push_back(ActualActual(ActualActual::ISDA).yearFraction(d.refDate, tmp));
1090 }
1091
1092 QuantLib::ext::shared_ptr<StochasticProcess> p_exact = d.xmodelExact->stateProcess();
1093 QuantLib::ext::shared_ptr<StochasticProcess> p_euler = d.xmodelEuler->stateProcess();
1094
1095 // check that covariance matrices are positive semidefinite
1096
1097 Array x0 = p_exact->initialValues();
1098 for (Size i = 1; i < simTimes_.size(); ++i) {
1099 // x0 does not matter, since covariance does not depend on it
1100 Matrix cov = p_exact->covariance(simTimes_[i - 1], x0, simTimes_[i] - simTimes_[i - 1]);
1101 SymmetricSchurDecomposition ssd(cov);
1102 for (Size j = 0; j < ssd.eigenvalues().size(); ++j) {
1103 if (ssd.eigenvalues()[j] < 0.0) {
1104 BOOST_ERROR("negative eigenvalue at " << j << " in covariance matrix at t=" << simTimes_[i] << " ("
1105 << ssd.eigenvalues()[j] << ")");
1106 }
1107 }
1108 }
1109
1110 // check positive semidefiniteness for one super-large step
1111 Matrix cov = p_exact->covariance(0.0, x0, simTimes_.back());
1112 SymmetricSchurDecomposition ssd2(cov);
1113 for (Size i = 0; i < ssd2.eigenvalues().size(); ++i) {
1114 if (ssd2.eigenvalues()[i] < 0.0) {
1115 BOOST_ERROR("negative eigenvalue at " << i << " in covariance matrix at t=0.0 for dt=100.0"
1116 << " (" << ssd2.eigenvalues()[i] << ")");
1117 }
1118 }
1119
1120} // testLgm31fPositiveCovariance
1121
1122BOOST_AUTO_TEST_CASE(testLgm31fMoments) {
1123
1124 BOOST_TEST_MESSAGE("Check analytical moments against Euler simulation in "
1125 "Ccy LGM 31F model...");
1126
1127 Lgm31fTestData d;
1128
1129 QuantLib::ext::shared_ptr<StochasticProcess> p_exact = d.xmodelExact->stateProcess();
1130 QuantLib::ext::shared_ptr<StochasticProcess> p_euler = d.xmodelEuler->stateProcess();
1131
1132 Array x0 = p_exact->initialValues();
1133
1134 // check the expectation and covariance over 0...T against euler
1135 Real T = 2.0;
1136 Size steps = static_cast<Size>(T * 10.0);
1137 Size paths = 25000;
1138 Size seed = 42;
1139 TimeGrid grid(T, steps);
1140
1141 Array e_an = p_exact->expectation(0.0, x0, T);
1142 Matrix v_an = p_exact->covariance(0.0, x0, T);
1143
1144 const Size dim = 31;
1145
1146 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<CrossAssetStateProcess>(p_euler)) {
1147 tmp->resetCache(grid.size() - 1 - 1);
1148 }
1149 MultiPathGeneratorSobolBrownianBridge pgen(p_euler, grid, SobolBrownianGenerator::Steps, seed);
1150
1151 accumulator_set<double, stats<tag::mean, tag::error_of<tag::mean> > > e_eu[dim];
1152 accumulator_set<double, stats<tag::covariance<double, tag::covariate1> > > v_eu[dim][dim];
1153
1154 for (Size i = 0; i < paths; ++i) {
1155 Sample<MultiPath> path = pgen.next();
1156 for (Size ii = 0; ii < dim; ++ii) {
1157 Real cii = path.value[ii].back();
1158 e_eu[ii](cii);
1159 for (Size jj = 0; jj <= ii; ++jj) {
1160 Real cjj = path.value[jj].back();
1161 v_eu[ii][jj](cii, covariate1 = cjj);
1162 }
1163 }
1164 }
1165
1166 Real tol1 = 2.0E-4; // ir
1167 Real tol2 = 15.0E-4; // fx
1168 Real tol3 = 2.0E-4; // ir-ir
1169 Real tol4 = 2.0E-4; // ir-fx
1170 Real tol5 = 15.0E-4; // fx-fx
1171
1172 // error checks and output is in new indexes !
1173 Real tol;
1174 // the test cases involving the CPI indices are broken
1175 // this is because of extreme values for H, which seem
1176 // to cause problems in the Euler discretization
1177 for (Size i = 0; i < 28 /*dim*/; ++i) {
1178 if (i < 16) {
1179 tol = tol1;
1180 } else {
1181 tol = tol2;
1182 }
1183 if (std::fabs(mean(e_eu[i]) - e_an[i]) > tol) {
1184 BOOST_ERROR("analytical expectation at " << i << " (" << e_an[i]
1185 << ") is inconsistent with numerical value (Euler "
1186 "discretization, "
1187 << mean(e_eu[i]) << ") error is " << e_an[i] - mean(e_eu[i])
1188 << " tolerance is " << tol);
1189 }
1190 for (Size j = 0; j <= i; ++j) {
1191 if (i < 16) {
1192 tol = tol3;
1193 } else {
1194 if (j < 16) {
1195 tol = tol4;
1196 } else {
1197 tol = tol5;
1198 }
1199 }
1200 if (std::fabs(boost::accumulators::covariance(v_eu[i][j]) - v_an[i][j]) > tol) {
1201 BOOST_ERROR("analytical covariance at ("
1202 << i << "," << j << ") (" << v_an[i][j]
1203 << ") is inconsistent with numerical "
1204 "value (Euler discretization, "
1205 << boost::accumulators::covariance(v_eu[i][j]) << "), error is "
1206 << v_an[i][j] - boost::accumulators::covariance(v_eu[i][j]) << " tolerance is " << tol);
1207 }
1208 }
1209 }
1210
1211 // debug output
1212 // std::clog << "EXACT and error expectation" << std::endl;
1213 // for (Size ii = 0; ii < dim; ++ii) {
1214 // std::clog << "#" << ii << " " << e_an[mapping[ii]] << " "
1215 // << mean(e_eu[mapping[ii]]) << " "
1216 // << mean(e_eu[mapping[ii]]) - e_an[mapping[ii]] << " +- "
1217 // << error_of<tag::mean>(e_eu[mapping[ii]]) << " => mult "
1218 // << (mean(e_eu[mapping[ii]]) - e_an[mapping[ii]]) /
1219 // error_of<tag::mean>(e_eu[mapping[ii]])
1220 // << std::endl;
1221 // }
1222
1223 // std::clog << "EXACT covariance" << std::endl;
1224 // for (Size ii = 0; ii < dim; ++ii) {
1225 // std::clog << "| ";
1226 // for (Size jj = 0; jj < ii; ++jj) {
1227 // std::clog << v_an[mapping[ii]][mapping[jj]] << " ";
1228 // }
1229 // std::clog << " |" << std::endl;
1230 // }
1231 // std::clog << std::endl;
1232
1233 // std::clog << "EULER covariance error" << std::endl;
1234 // for (Size ii = 0; ii < dim; ++ii) {
1235 // std::clog << "| ";
1236 // for (Size jj = 0; jj <= ii; ++jj) {
1237 // std::clog << covariance(v_eu[mapping[ii]][mapping[jj]]) -
1238 // v_an[mapping[ii]][mapping[jj]]
1239 // << " ";
1240 // }
1241 // std::clog << " |" << std::endl;
1242 // }
1243 // std::clog << std::endl;
1244 // end debug output
1245
1246} // testLgm31fMoments
1247
1248BOOST_AUTO_TEST_CASE(testLgm31fMartingaleProperty) {
1249
1250 BOOST_TEST_MESSAGE("Check martingale property in Ccy LGM 31F model...");
1251
1252 Lgm31fTestData d;
1253
1254 QuantLib::ext::shared_ptr<StochasticProcess> p_exact = d.xmodelExact->stateProcess();
1255 QuantLib::ext::shared_ptr<StochasticProcess> p_euler = d.xmodelEuler->stateProcess();
1256
1257 Real T = 2.0;
1258 Size steps = static_cast<Size>(T * 10.0);
1259 Size paths = 25000;
1260 Size seed = 42;
1261 TimeGrid grid(T, steps);
1262
1263 const Size dim = 31, nIr = 13 + 3;
1264
1265 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<CrossAssetStateProcess>(p_euler)) {
1266 tmp->resetCache(grid.size() - 1);
1267 }
1268 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<CrossAssetStateProcess>(p_exact)) {
1269 tmp->resetCache(grid.size() - 1);
1270 }
1271 MultiPathGeneratorSobolBrownianBridge pgen(p_euler, grid, SobolBrownianGenerator::Steps, seed);
1272 MultiPathGeneratorSobolBrownianBridge pgen2(p_exact, grid, SobolBrownianGenerator::Steps, seed);
1273
1274 accumulator_set<double, stats<tag::mean, tag::error_of<tag::mean> > > e_eu2[dim];
1275
1276 for (Size i = 0; i < paths; ++i) {
1277 Sample<MultiPath> path = pgen.next();
1278 for (Size ii = 0; ii < nIr; ++ii) {
1279 if (ii == 0) {
1280 // domestic currency
1281 e_eu2[ii](1.0 / d.xmodelExact->numeraire(0, T, path.value[0].back()));
1282 } else {
1283 // foreign currencies
1284 e_eu2[ii](std::exp(path.value[nIr + (ii - 1)].back()) /
1285 d.xmodelExact->numeraire(0, T, path.value[0].back()));
1286 }
1287 }
1288 }
1289
1290 // as before we have to exclude the inflation indices
1291 Real tol = 0.5E-4;
1292 for (Size ii = 0; ii < nIr - 3; ++ii) {
1293 if (std::fabs(-std::log(mean(e_eu2[ii])) / T + std::log(d.yts->discount(T)) / T) > tol) {
1294 BOOST_ERROR("failed to verify martingale property for ccy "
1295 << ii << ", equivalent simulated zero yield is " << -std::log(mean(e_eu2[ii])) / T
1296 << " while theoretical value is " << -std::log(d.yts->discount(T)) / T << " difference is "
1297 << -std::log(mean(e_eu2[ii])) / T + std::log(d.yts->discount(T)) / T << ", tolerance is "
1298 << tol);
1299 }
1300 }
1301
1302} // testLgm13fMartingaleProperty
1303
1304BOOST_AUTO_TEST_SUITE_END()
1305
1306BOOST_AUTO_TEST_SUITE_END()
analytic cc lgm fx option engine
analytic dk cpi cap floor engine
analytic lgm cds option engine
analytic engine for european swaptions in the LGM model
analytic cross-asset lgm eq option engine
Black credit default swap option engine.
cds option calibration helper
const Sample< MultiPath > & next() const override
Instantiation using SobolBrownianGenerator from models/marketmodels/browniangenerators.
CPI Cap Floor calibration helper.
Credit Linear Gaussian Markov 1 factor parametrization.
analytics for the cross asset model
basic functions for analytics in the cross asset model
BOOST_AUTO_TEST_CASE(testLgm31fPositiveCovariance)
cross asset model
dynamic black volatility term structure
dynamic black volatility term structure
Cross currency swap engine.
deposit engine
Engine to value a commodity forward contract.
discounting currency swap engine
Engine to value an Equity Forward contract.
Engine to value an FX Forward off two yield curves.
Swap engine employing assumptions to speed up calculation.
year on year inflation term structure implied by a Dodgson Kainth (DK) model
zero inflation term structure implied by a Dodgson Kainth (DK) model
Constant equity model parametrization.
EQ Black Scholes parametrization.
piecewise constant model parametrization
Constant FX model parametrization.
FX Black Scholes parametrization.
piecewise constant model parametrization
calibration helper for Black-Scholes options
adaptor class that extracts one irlgm1f component
Inflation Dodgson Kainth parametrization.
constant model parametrization
Interest Rate Linear Gaussian Markov 1 factor parametrization.
adaptor to emulate piecewise constant Hull White parameters
piecewise constant model parametrization
piecewise linear model parametrization
lgm model class
default probability structure implied by a LGM model
yield term structure implied by a LGM model
calibrated model class with linkable parameters
base class for multi path generators
Overnight Indexed Cross Currency Basis Swap Engine.
base class for model parametrizations
Single payment discounting engine.
helper classes for piecewise constant parametrizations
parameter giving access to calibration machinery
std::vector< Size > steps
Fixture that can be used at top level.
helper macros and methods for tests
#define LENGTH(a)
Definition: utilities.hpp:27