53#include <ql/termstructures/yield/piecewiseyieldcurve.hpp>
54#include <ql/time/calendars/target.hpp>
55#include <ql/time/date.hpp>
56#include <ql/time/daycounters/actualactual.hpp>
60#include <boost/timer/timer.hpp>
65using namespace boost::unit_test_framework;
71 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData(
73 simMarketData->baseCcy() =
"EUR";
74 simMarketData->ccys() = {
"EUR",
"GBP",
"USD"};
75 simMarketData->setDiscountCurveNames({
"EUR",
"GBP",
"USD"});
76 simMarketData->setYieldCurveTenors(
"", {1 * Months, 6 * Months, 1 * Years, 2 * Years, 3 * Years, 4 * Years,
77 5 * Years, 6 * Years, 7 * Years, 8 * Years, 9 * Years, 10 * Years,
78 12 * Years, 15 * Years, 20 * Years, 25 * Years, 30 * Years});
79 simMarketData->setIndices({
"EUR-EURIBOR-6M",
"GBP-LIBOR-6M"});
80 simMarketData->interpolation() =
"LogLinear";
82 simMarketData->setDefaultNames({
"BondIssuer1"});
84 simMarketData->setDefaultTenors(
85 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
86 simMarketData->setSimulateSurvivalProbabilities(
true);
87 simMarketData->setDefaultCurveCalendars(
"",
"TARGET");
89 simMarketData->setSwapVolTerms(
90 "", {1 * Years, 2 * Years, 3 * Years, 4 * Years, 5 * Years, 7 * Years, 10 * Years, 20 * Years});
91 simMarketData->setSwapVolExpiries(
92 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 20 * Years});
93 simMarketData->setSwapVolKeys({
"EUR",
"GBP"});
94 simMarketData->swapVolDecayMode() =
"ForwardVariance";
95 simMarketData->setSimulateSwapVols(
true);
97 simMarketData->setFxVolExpiries(
"",
98 vector<Period>{1 * Months, 3 * Months, 6 * Months, 2 * Years, 3 * Years, 4 * Years, 5 * Years});
99 simMarketData->setFxVolDecayMode(
string(
"ConstantVariance"));
100 simMarketData->setSimulateFXVols(
true);
101 simMarketData->setFxVolCcyPairs({
"EURGBP"});
102 simMarketData->setFxVolIsSurface(
true);
103 simMarketData->setFxVolMoneyness(vector<Real>{0.1, 0.5, 1, 1.5, 2, 2.5, 2});
105 simMarketData->setFxCcyPairs({
"EURGBP"});
107 simMarketData->setSimulateCapFloorVols(
false);
108 simMarketData->setEquityNames({
"SP5",
"Lufthansa"});
109 simMarketData->setEquityDividendTenors(
"SP5", {6 * Months, 1 * Years, 2 * Years});
110 simMarketData->setEquityDividendTenors(
"Lufthansa", {6 * Months, 1 * Years, 2 * Years});
112 simMarketData->setSimulateEquityVols(
true);
113 simMarketData->setEquityVolDecayMode(
"ForwardVariance");
114 simMarketData->setEquityVolNames({
"SP5",
"Lufthansa"});
115 simMarketData->setEquityVolExpiries(
"", {2 * Weeks, 1 * Months, 3 * Months, 6 * Months, 1 * Years,
116 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years,
117 13 * Years, 15 * Years, 20 * Years, 30 * Years});
118 simMarketData->setEquityVolIsSurface(
"",
true);
119 simMarketData->setEquityVolMoneyness(
"", {0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1.0, 1.05, 1.1, 1.2,
120 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0});
122 simMarketData->setYoyInflationIndices({
"UKRP1"});
123 simMarketData->setYoyInflationTenors(
124 "UKRP1", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
126 simMarketData->setSimulateYoYInflationCapFloorVols(
true);
127 simMarketData->setYoYInflationCapFloorVolNames({
"UKRP1"});
128 simMarketData->setYoYInflationCapFloorVolExpiries(
129 "UKRP1", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
130 simMarketData->setYoYInflationCapFloorVolStrikes(
"", {-0.02, -0.01, 0.00, 0.01, 0.02, 0.03});
131 simMarketData->yoyInflationCapFloorVolDecayMode() =
"ForwardVariance";
133 return simMarketData;
137 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData(
140 simMarketData->baseCcy() =
"EUR";
142 simMarketData->setDiscountCurveNames({
"EUR",
"GBP",
"USD",
"CHF",
"JPY"});
143 simMarketData->setYieldCurveNames({
"BondCurve1"});
144 simMarketData->yieldCurveCurrencies()[
"BondCurve1"] =
"EUR";
145 simMarketData->setYieldCurveTenors(
"", {1 * Months, 6 * Months, 1 * Years, 2 * Years, 3 * Years, 4 * Years,
146 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years, 30 * Years});
147 simMarketData->setIndices(
148 {
"EUR-EURIBOR-6M",
"USD-LIBOR-3M",
"USD-LIBOR-6M",
"GBP-LIBOR-6M",
"CHF-LIBOR-6M",
"JPY-LIBOR-6M"});
149 simMarketData->interpolation() =
"LogLinear";
151 simMarketData->setDefaultNames({
"BondIssuer1",
"dc"});
152 simMarketData->setDefaultTenors(
153 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
154 simMarketData->setSimulateSurvivalProbabilities(
true);
155 simMarketData->setSecurities({
"Bond1"});
156 simMarketData->setDefaultCurveCalendars(
"",
"TARGET");
158 simMarketData->setSwapVolTerms(
"", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 20 * Years});
159 simMarketData->setSwapVolExpiries(
160 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 20 * Years});
161 simMarketData->setSwapVolKeys({
"EUR",
"GBP",
"USD",
"CHF",
"JPY"});
162 simMarketData->swapVolDecayMode() =
"ForwardVariance";
163 simMarketData->setSimulateSwapVols(
true);
165 simMarketData->setFxVolExpiries(
"",
166 vector<Period>{1 * Months, 3 * Months, 6 * Months, 2 * Years, 3 * Years, 4 * Years, 5 * Years});
167 simMarketData->setFxVolDecayMode(
string(
"ConstantVariance"));
168 simMarketData->setSimulateFXVols(
true);
169 simMarketData->setFxVolCcyPairs({
"EURUSD",
"EURGBP",
"EURCHF",
"EURJPY"});
170 simMarketData->setFxVolIsSurface(
true);
171 simMarketData->setFxVolMoneyness(vector<Real>{0.1, 0.5, 1, 1.5, 2, 2.5, 3});
173 simMarketData->setFxCcyPairs({
"EURUSD",
"EURGBP",
"EURCHF",
"EURJPY"});
175 simMarketData->setSimulateCapFloorVols(
true);
176 simMarketData->capFloorVolDecayMode() =
"ForwardVariance";
177 simMarketData->setCapFloorVolKeys({
"EUR",
"USD"});
178 simMarketData->setCapFloorVolExpiries(
179 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
180 simMarketData->setCapFloorVolStrikes(
"", {0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06});
182 simMarketData->setSimulateCdsVols(
true);
183 simMarketData->cdsVolExpiries() = {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 10 * Years};
184 simMarketData->cdsVolDecayMode() =
"ForwardVariance";
185 simMarketData->setCdsVolNames({
"dc"});
187 simMarketData->setEquityNames({
"SP5",
"Lufthansa"});
188 simMarketData->setEquityDividendTenors(
"SP5", {6 * Months, 1 * Years, 2 * Years});
189 simMarketData->setEquityDividendTenors(
"Lufthansa", {6 * Months, 1 * Years, 2 * Years});
191 simMarketData->setSimulateEquityVols(
true);
192 simMarketData->setEquityVolDecayMode(
"ForwardVariance");
193 simMarketData->setEquityVolNames({
"SP5",
"Lufthansa"});
194 simMarketData->setEquityVolExpiries(
"", {2 * Weeks, 1 * Months, 3 * Months, 6 * Months, 1 * Years,
195 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years,
196 13 * Years, 15 * Years, 20 * Years, 30 * Years});
197 simMarketData->setEquityVolIsSurface(
"",
true);
198 simMarketData->setEquityVolMoneyness(
"", {0.5, 0.6, 0.7, 0.8, 0.9, 0.95, 1.0, 1.05, 1.1, 1.2,
199 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0, 2.5, 3.0});
201 simMarketData->setYoyInflationIndices({
"UKRP1"});
202 simMarketData->setYoyInflationTenors(
203 "UKRP1", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
205 simMarketData->setSimulateYoYInflationCapFloorVols(
true);
206 simMarketData->setYoYInflationCapFloorVolNames({
"UKRP1"});
207 simMarketData->setYoYInflationCapFloorVolExpiries(
208 "UKRP1", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
209 simMarketData->setYoYInflationCapFloorVolStrikes(
"", {-0.02, -0.01, 0.00, 0.01, 0.02, 0.03});
210 simMarketData->yoyInflationCapFloorVolDecayMode() =
"ForwardVariance";
212 return simMarketData;
217 cvsData.
shiftTenors = {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years,
218 7 * Years, 10 * Years, 15 * Years, 20 * Years};
221 cvsData.
parInstruments = {
"DEP",
"IRS",
"IRS",
"IRS",
"IRS",
"IRS",
"IRS",
"IRS",
"IRS"};
226 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = QuantLib::ext::make_shared<SensitivityScenarioData>(
false);
233 fxvsData.
shiftType = ShiftType::Relative;
238 cfvsData.
shiftType = ShiftType::Absolute;
240 cfvsData.
shiftExpiries = {1 * Years, 2 * Years, 3 * Years, 5 * Years, 10 * Years};
244 swvsData.
shiftType = ShiftType::Relative;
247 swvsData.
shiftTerms = {2 * Years, 5 * Years, 10 * Years};
253 sensiData->discountCurveShiftData()[
"EUR"] =
254 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(eurDiscountData);
260 sensiData->discountCurveShiftData()[
"GBP"] =
261 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(gbpDiscountData);
267 sensiData->indexCurveShiftData()[
"EUR-EURIBOR-6M"] =
268 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(eurIndexData);
274 sensiData->indexCurveShiftData()[
"GBP-LIBOR-6M"] =
275 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(gbpIndexData);
277 sensiData->fxShiftData()[
"EURGBP"] = fxsData;
279 sensiData->fxVolShiftData()[
"EURGBP"] = fxvsData;
281 sensiData->swaptionVolShiftData()[
"EUR"] = swvsData;
282 sensiData->swaptionVolShiftData()[
"GBP"] = swvsData;
284 sensiData->creditCcys()[
"BondIssuer1"] =
"EUR";
286 bondData.
parInstruments = {
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS"};
289 sensiData->creditCurveShiftData()[
"BondIssuer1"] =
290 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(bondData);
297 eqvsData.
shiftType = ShiftType::Relative;
299 eqvsData.
shiftExpiries = {2 * Weeks, 1 * Months, 3 * Months, 6 * Months, 1 * Years, 2 * Years, 3 * Years,
300 5 * Years, 7 * Years, 10 * Years, 13 * Years, 15 * Years, 20 * Years, 30 * Years};
303 eqdivData.
shiftType = ShiftType::Absolute;
305 eqdivData.
shiftTenors = {6 * Months, 1 * Years, 2 * Years};
307 sensiData->equityShiftData()[
"SP5"] = eqsData;
308 sensiData->equityShiftData()[
"Lufthansa"] = eqsData;
310 sensiData->equityVolShiftData()[
"SP5"] = eqvsData;
311 sensiData->equityVolShiftData()[
"Lufthansa"] = eqvsData;
313 QuantLib::ext::shared_ptr<ore::analytics::SensitivityScenarioData::CurveShiftParData> yinfData =
314 QuantLib::ext::make_shared<ore::analytics::SensitivityScenarioData::CurveShiftParData>();
315 yinfData->shiftType = ShiftType::Absolute;
316 yinfData->shiftSize = 0.0001;
317 yinfData->shiftTenors = {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years};
318 yinfData->parInstruments = {
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS"};
319 yinfData->parInstrumentConventions[
"ZIS"] =
"UKRP1";
320 yinfData->parInstrumentConventions[
"YYS"] =
"UKRP1";
321 sensiData->yoyInflationCurveShiftData()[
"UKRP1"] = yinfData;
323 auto yinfCfData = QuantLib::ext::make_shared<ore::analytics::SensitivityScenarioData::CapFloorVolShiftParData>();
324 yinfCfData->shiftType = ShiftType::Absolute;
325 yinfCfData->shiftSize = 0.00001;
326 yinfCfData->shiftExpiries = {1 * Years, 2 * Years, 3 * Years, 5 * Years,
327 7 * Years, 10 * Years, 15 * Years, 20 * Years};
328 yinfCfData->shiftStrikes = {-0.02, -0.01, 0.00, 0.01, 0.02, 0.03};
329 yinfCfData->parInstruments = {
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS"};
330 yinfCfData->parInstrumentSingleCurve =
false;
331 yinfCfData->parInstrumentConventions[
"ZIS"] =
"UKRP1";
332 yinfCfData->parInstrumentConventions[
"YYS"] =
"UKRP1";
333 sensiData->yoyInflationCapFloorVolShiftData()[
"UKRP1"] = yinfCfData;
339 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData =
340 QuantLib::ext::make_shared<SensitivityScenarioData>(parConversion);
348 fxvsData.
shiftType = ShiftType::Relative;
353 cfvsData.
shiftType = ShiftType::Absolute;
355 cfvsData.
shiftExpiries = {1 * Years, 2 * Years, 3 * Years, 5 * Years, 10 * Years};
359 swvsData.
shiftType = ShiftType::Relative;
362 swvsData.
shiftTerms = {5 * Years, 10 * Years};
365 cdsvsData.
shiftType = ShiftType::Relative;
367 cdsvsData.
shiftExpiries = {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 10 * Years};
375 sensiData->discountCurveShiftData()[
"EUR"] =
376 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(eurDiscountData);
382 sensiData->discountCurveShiftData()[
"USD"] =
383 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(usdDiscountData);
389 sensiData->discountCurveShiftData()[
"GBP"] =
390 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(gbpDiscountData);
396 sensiData->discountCurveShiftData()[
"JPY"] =
397 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(jpyDiscountData);
403 sensiData->discountCurveShiftData()[
"CHF"] =
404 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(chfDiscountData);
410 sensiData->yieldCurveShiftData()[
"BondCurve1"] =
411 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(bondData);
417 sensiData->indexCurveShiftData()[
"EUR-EURIBOR-6M"] =
418 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(eurIndexData);
424 sensiData->indexCurveShiftData()[
"USD-LIBOR-3M"] =
425 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(usdIndexData);
431 sensiData->indexCurveShiftData()[
"GBP-LIBOR-6M"] =
432 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(gbpIndexData);
438 sensiData->indexCurveShiftData()[
"JPY-LIBOR-6M"] =
439 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(jpyIndexData);
445 sensiData->indexCurveShiftData()[
"CHF-LIBOR-6M"] =
446 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(chfIndexData);
448 sensiData->fxShiftData()[
"EURUSD"] = fxsData;
449 sensiData->fxShiftData()[
"EURGBP"] = fxsData;
450 sensiData->fxShiftData()[
"EURJPY"] = fxsData;
451 sensiData->fxShiftData()[
"EURCHF"] = fxsData;
453 sensiData->fxVolShiftData()[
"EURUSD"] = fxvsData;
454 sensiData->fxVolShiftData()[
"EURGBP"] = fxvsData;
455 sensiData->fxVolShiftData()[
"EURJPY"] = fxvsData;
456 sensiData->fxVolShiftData()[
"EURCHF"] = fxvsData;
458 sensiData->swaptionVolShiftData()[
"EUR"] = swvsData;
459 sensiData->swaptionVolShiftData()[
"GBP"] = swvsData;
460 sensiData->swaptionVolShiftData()[
"USD"] = swvsData;
461 sensiData->swaptionVolShiftData()[
"JPY"] = swvsData;
462 sensiData->swaptionVolShiftData()[
"CHF"] = swvsData;
464 sensiData->capFloorVolShiftData()[
"EUR"] =
465 QuantLib::ext::make_shared<SensitivityScenarioData::CapFloorVolShiftData>(cfvsData);
466 sensiData->capFloorVolShiftData()[
"EUR"]->indexName =
"EUR-EURIBOR-6M";
467 sensiData->capFloorVolShiftData()[
"USD"] =
468 QuantLib::ext::make_shared<SensitivityScenarioData::CapFloorVolShiftData>(cfvsData);
469 sensiData->capFloorVolShiftData()[
"USD"]->indexName =
"USD-LIBOR-3M";
472 dcData.
parInstruments = {
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS"};
475 sensiData->creditCurveShiftData()[
"dc"] =
476 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(dcData);
477 sensiData->creditCcys()[
"dc"] =
"EUR";
480 bondIssData.
parInstruments = {
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS",
"CDS"};
483 sensiData->creditCurveShiftData()[
"BondIssuer1"] =
484 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftParData>(bondIssData);
485 sensiData->creditCcys()[
"BondIssuer1"] =
"EUR";
487 sensiData->cdsVolShiftData()[
"dc"] = cdsvsData;
494 eqvsData.
shiftType = ShiftType::Relative;
496 eqvsData.
shiftExpiries = {2 * Weeks, 1 * Months, 3 * Months, 6 * Months, 1 * Years, 2 * Years, 3 * Years,
497 5 * Years, 10 * Years, 13 * Years, 15 * Years, 20 * Years, 30 * Years};
500 eqdivData.
shiftType = ShiftType::Absolute;
502 eqdivData.
shiftTenors = {6 * Months, 1 * Years, 2 * Years};
504 sensiData->equityShiftData()[
"SP5"] = eqsData;
505 sensiData->equityShiftData()[
"Lufthansa"] = eqsData;
507 sensiData->equityVolShiftData()[
"SP5"] = eqvsData;
508 sensiData->equityVolShiftData()[
"Lufthansa"] = eqvsData;
510 QuantLib::ext::shared_ptr<ore::analytics::SensitivityScenarioData::CurveShiftParData> yinfData =
511 QuantLib::ext::make_shared<ore::analytics::SensitivityScenarioData::CurveShiftParData>();
512 yinfData->shiftType = ShiftType::Absolute;
513 yinfData->shiftSize = 0.0001;
514 yinfData->shiftTenors = {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years};
515 yinfData->parInstruments = {
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS"};
516 yinfData->parInstrumentConventions[
"ZIS"] =
"UKRP1";
517 yinfData->parInstrumentConventions[
"YYS"] =
"UKRP1";
518 sensiData->yoyInflationCurveShiftData()[
"UKRP1"] = yinfData;
520 auto yinfCfData = QuantLib::ext::make_shared<ore::analytics::SensitivityScenarioData::CapFloorVolShiftParData>();
521 yinfCfData->shiftType = ShiftType::Absolute;
522 yinfCfData->shiftSize = 0.00001;
523 yinfCfData->shiftExpiries = {1 * Years, 2 * Years, 3 * Years, 5 * Years,
524 7 * Years, 10 * Years, 15 * Years, 20 * Years};
525 yinfCfData->shiftStrikes = {-0.02, -0.01, 0.00, 0.01, 0.02, 0.03};
526 yinfCfData->parInstruments = {
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS",
"YYS"};
527 yinfCfData->parInstrumentSingleCurve =
false;
528 yinfCfData->parInstrumentConventions[
"ZIS"] =
"UKRP1";
529 yinfCfData->parInstrumentConventions[
"YYS"] =
"UKRP1";
530 sensiData->yoyInflationCapFloorVolShiftData()[
"UKRP1"] = yinfCfData;
538 BOOST_TEST_MESSAGE(
"Testing Portfolio sensitivity");
540 SavedSettings backup;
542 ObservationMode::instance().setMode(ObservationMode::Mode::None);
544 Date today = Date(14, April, 2016);
545 Settings::instance().evaluationDate() = today;
547 BOOST_TEST_MESSAGE(
"Today is " << today);
550 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
553 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
setupSimMarketData5();
558 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket =
559 QuantLib::ext::make_shared<analytics::ScenarioSimMarket>(initMarket, simMarketData);
562 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
563 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory =
564 QuantLib::ext::make_shared<ore::analytics::DeltaScenarioFactory>(baseScenario);
567 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
568 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
569 scenarioFactory,
false);
570 simMarket->scenarioGenerator() = scenarioGenerator;
573 QuantLib::ext::shared_ptr<EngineData>
data = QuantLib::ext::make_shared<EngineData>();
574 data->model(
"Swap") =
"DiscountedCashflows";
575 data->engine(
"Swap") =
"DiscountingSwapEngine";
576 data->model(
"CrossCurrencySwap") =
"DiscountedCashflows";
577 data->engine(
"CrossCurrencySwap") =
"DiscountingCrossCurrencySwapEngine";
578 data->model(
"EuropeanSwaption") =
"BlackBachelier";
579 data->engine(
"EuropeanSwaption") =
"BlackBachelierSwaptionEngine";
580 data->model(
"FxForward") =
"DiscountedCashflows";
581 data->engine(
"FxForward") =
"DiscountingFxForwardEngine";
582 data->model(
"FxOption") =
"GarmanKohlhagen";
583 data->engine(
"FxOption") =
"AnalyticEuropeanEngine";
584 data->model(
"CapFloor") =
"IborCapModel";
585 data->engine(
"CapFloor") =
"IborCapEngine";
586 data->model(
"CapFlooredIborLeg") =
"BlackOrBachelier";
587 data->engine(
"CapFlooredIborLeg") =
"BlackIborCouponPricer";
588 data->model(
"YYCapFloor") =
"YYCapModel";
589 data->engine(
"YYCapFloor") =
"YYCapEngine";
590 data->model(
"IndexCreditDefaultSwapOption") =
"Black";
591 data->engine(
"IndexCreditDefaultSwapOption") =
"BlackIndexCdsOptionEngine";
592 map<string, string> engineParamMap1;
593 engineParamMap1[
"Curve"] =
"Underlying";
594 data->engineParameters(
"IndexCreditDefaultSwapOption") = engineParamMap1;
596 data->model(
"IndexCreditDefaultSwap") =
"DiscountedCashflows";
597 data->engine(
"IndexCreditDefaultSwap") =
"MidPointIndexCdsEngine";
598 map<string, string> engineParamMap2;
599 engineParamMap2[
"Curve"] =
"Underlying";
600 data->engineParameters(
"IndexCreditDefaultSwap") = engineParamMap2;
601 data->model(
"Bond") =
"DiscountedCashflows";
602 data->engine(
"Bond") =
"DiscountingRiskyBondEngine";
603 data->engineParameters(
"Bond")[
"TimestepPeriod"] =
"6M";
604 data->model(
"EquityOption") =
"BlackScholesMerton";
605 data->engine(
"EquityOption") =
"AnalyticEuropeanEngine";
606 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(
data, simMarket);
609 QuantLib::ext::shared_ptr<Portfolio> portfolio(
new Portfolio());
610 portfolio->add(
buildSwap(
"1_Swap_EUR",
"EUR",
true, 10000000.0, 0, 10, 0.03, 0.00,
"1Y",
611 "30/360",
"6M",
"A360",
"EUR-EURIBOR-6M"));
612 portfolio->add(
buildSwap(
"2_Swap_USD",
"USD",
true, 10000000.0, 0, 15, 0.02, 0.00,
"6M",
613 "30/360",
"3M",
"A360",
"USD-LIBOR-3M"));
614 portfolio->add(
buildSwap(
"3_Swap_GBP",
"GBP",
true, 10000000.0, 0, 20, 0.04, 0.00,
"6M",
615 "30/360",
"3M",
"A360",
"GBP-LIBOR-6M"));
616 portfolio->add(
buildSwap(
"4_Swap_JPY",
"JPY",
true, 1000000000.0, 0, 5, 0.01, 0.00,
"6M",
617 "30/360",
"3M",
"A360",
"JPY-LIBOR-6M"));
619 0.02, 0.00,
"1Y",
"30/360",
"6M",
"A360",
"EUR-EURIBOR-6M",
622 0.02, 0.00,
"1Y",
"30/360",
"6M",
"A360",
"EUR-EURIBOR-6M",
624 portfolio->add(
buildFxOption(
"7_FxOption_EUR_USD",
"Long",
"Call", 3,
"EUR", 10000000.0,
"USD",
626 portfolio->add(
buildFxOption(
"8_FxOption_EUR_GBP",
"Long",
"Call", 7,
"EUR", 10000000.0,
"GBP",
628 portfolio->add(
buildCap(
"9_Cap_EUR",
"EUR",
"Long", 0.05, 1000000.0, 0, 10,
"6M",
"A360",
630 portfolio->add(
buildFloor(
"10_Floor_USD",
"USD",
"Long", 0.01, 1000000.0, 0, 10,
"3M",
"A360",
643 buildEquityOption(
"12_EquityOption_SP5",
"Long",
"Call", 2,
"SP5",
"USD", 2147.56, 1000));
644 portfolio->add(
buildEquityOption(
"13_EquityOption_Lufthansa",
"Long",
"Call", 2,
"Lufthansa",
648 0.02, 0, 10,
"1Y",
"ACT/ACT",
"UKRP1",
"2M", 2));
649 portfolio->build(factory);
651 BOOST_TEST_MESSAGE(
"Portfolio size after build: " << portfolio->size());
653 QuantLib::ext::shared_ptr<DateGrid> dg = QuantLib::ext::make_shared<DateGrid>(
655 vector<QuantLib::ext::shared_ptr<ValuationCalculator>> calculators;
656 calculators.push_back(QuantLib::ext::make_shared<NPVCalculator>(simMarketData->baseCcy()));
659 boost::timer::cpu_timer t;
660 QuantLib::ext::shared_ptr<NPVCube> cube = QuantLib::ext::make_shared<DoublePrecisionInMemoryCube>(
661 today, portfolio->ids(), vector<Date>(1, today), scenarioGenerator->samples());
662 engine.
buildCube(portfolio, cube, calculators);
663 double elapsed = t.elapsed().wall * 1e-9;
672 std::vector<Results> cachedResults = {
673 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/0/6M", -928826, -2.51631},
674 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/1/1Y", -928826, 14.6846},
675 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/2/2Y", -928826, 19.0081},
676 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/3/3Y", -928826, 46.1186},
677 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/4/5Y", -928826, 85.1033},
678 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/5/7Y", -928826, 149.43},
679 {
"1_Swap_EUR",
"Up:DiscountCurve/EUR/6/10Y", -928826, 205.064},
680 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/0/6M", -928826, 2.51644},
681 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/1/1Y", -928826, -14.6863},
682 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/2/2Y", -928826, -19.0137},
683 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/3/3Y", -928826, -46.1338},
684 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/4/5Y", -928826, -85.1406},
685 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/5/7Y", -928826, -149.515},
686 {
"1_Swap_EUR",
"Down:DiscountCurve/EUR/6/10Y", -928826, -205.239},
687 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/0/6M", -928826, -495.013},
688 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/1/1Y", -928826, 14.7304},
689 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", -928826, 38.7816},
690 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", -928826, 94.186},
691 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", -928826, 173.125},
692 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", -928826, 304.648},
693 {
"1_Swap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", -928826, 8479.55},
694 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/0/6M", -928826, 495.037},
695 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/1/1Y", -928826, -14.5864},
696 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", -928826, -38.4045},
697 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", -928826, -93.532},
698 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", -928826, -171.969},
699 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", -928826, -302.864},
700 {
"1_Swap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", -928826, -8478.14},
701 {
"2_Swap_USD",
"Up:DiscountCurve/USD/0/6M", 980404, -1.04797},
702 {
"2_Swap_USD",
"Up:DiscountCurve/USD/1/1Y", 980404, -6.06931},
703 {
"2_Swap_USD",
"Up:DiscountCurve/USD/2/2Y", 980404, -15.8605},
704 {
"2_Swap_USD",
"Up:DiscountCurve/USD/3/3Y", 980404, -38.0708},
705 {
"2_Swap_USD",
"Up:DiscountCurve/USD/4/5Y", 980404, -68.7288},
706 {
"2_Swap_USD",
"Up:DiscountCurve/USD/5/7Y", 980404, -118.405},
707 {
"2_Swap_USD",
"Up:DiscountCurve/USD/6/10Y", 980404, -244.946},
708 {
"2_Swap_USD",
"Up:DiscountCurve/USD/7/15Y", 980404, -202.226},
709 {
"2_Swap_USD",
"Up:DiscountCurve/USD/8/20Y", 980404, 0.0148314},
710 {
"2_Swap_USD",
"Down:DiscountCurve/USD/0/6M", 980404, 1.04797},
711 {
"2_Swap_USD",
"Down:DiscountCurve/USD/1/1Y", 980404, 6.06959},
712 {
"2_Swap_USD",
"Down:DiscountCurve/USD/2/2Y", 980404, 15.8623},
713 {
"2_Swap_USD",
"Down:DiscountCurve/USD/3/3Y", 980404, 38.0784},
714 {
"2_Swap_USD",
"Down:DiscountCurve/USD/4/5Y", 980404, 68.7502},
715 {
"2_Swap_USD",
"Down:DiscountCurve/USD/5/7Y", 980404, 118.458},
716 {
"2_Swap_USD",
"Down:DiscountCurve/USD/6/10Y", 980404, 245.108},
717 {
"2_Swap_USD",
"Down:DiscountCurve/USD/7/15Y", 980404, 202.42},
718 {
"2_Swap_USD",
"Down:DiscountCurve/USD/8/20Y", 980404, -0.0148314},
719 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/0/6M", 980404, -201.015},
720 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/1/1Y", 980404, 18.134},
721 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/2/2Y", 980404, 47.3066},
722 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/3/3Y", 980404, 113.4},
723 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/4/5Y", 980404, 205.068},
724 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/5/7Y", 980404, 352.859},
725 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/6/10Y", 980404, 730.076},
726 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/7/15Y", 980404, 8626.78},
727 {
"2_Swap_USD",
"Up:IndexCurve/USD-LIBOR-3M/8/20Y", 980404, 5.86437},
728 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/0/6M", 980404, 201.03},
729 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/1/1Y", 980404, -18.0746},
730 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/2/2Y", 980404, -47.1526},
731 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/3/3Y", 980404, -113.136},
732 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/4/5Y", 980404, -204.611},
733 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/5/7Y", 980404, -352.166},
734 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/6/10Y", 980404, -729.248},
735 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/7/15Y", 980404, -8626.13},
736 {
"2_Swap_USD",
"Down:IndexCurve/USD-LIBOR-3M/8/20Y", 980404, -5.86436},
737 {
"2_Swap_USD",
"Up:FXSpot/EURUSD/0/spot", 980404, -9706.97},
738 {
"2_Swap_USD",
"Down:FXSpot/EURUSD/0/spot", 980404, 9903.07},
739 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/0/6M", 69795.3, 2.12392},
740 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/1/1Y", 69795.3, -0.646097},
741 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/2/2Y", 69795.3, -1.75066},
742 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/3/3Y", 69795.3, -4.24827},
743 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/4/5Y", 69795.3, -7.2252},
744 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/5/7Y", 69795.3, -12.5287},
745 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/6/10Y", 69795.3, -24.7828},
746 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/7/15Y", 69795.3, -39.2456},
747 {
"3_Swap_GBP",
"Up:DiscountCurve/GBP/8/20Y", 69795.3, 31.2081},
748 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/0/6M", 69795.3, -2.12413},
749 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/1/1Y", 69795.3, 0.645698},
750 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/2/2Y", 69795.3, 1.74981},
751 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/3/3Y", 69795.3, 4.2473},
752 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/4/5Y", 69795.3, 7.22426},
753 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/5/7Y", 69795.3, 12.5298},
754 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/6/10Y", 69795.3, 24.7939},
755 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/7/15Y", 69795.3, 39.2773},
756 {
"3_Swap_GBP",
"Down:DiscountCurve/GBP/8/20Y", 69795.3, -31.2925},
757 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/0/6M", 69795.3, -308.49},
758 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/1/1Y", 69795.3, 68.819},
759 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/2/2Y", 69795.3, 81.3735},
760 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/3/3Y", 69795.3, 239.034},
761 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/4/5Y", 69795.3, 372.209},
762 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/5/7Y", 69795.3, 654.949},
763 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/6/10Y", 69795.3, 1343.01},
764 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/7/15Y", 69795.3, 2139.68},
765 {
"3_Swap_GBP",
"Up:IndexCurve/GBP-LIBOR-6M/8/20Y", 69795.3, 12633.8},
766 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/0/6M", 69795.3, 308.513},
767 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/1/1Y", 69795.3, -68.7287},
768 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/2/2Y", 69795.3, -81.1438},
769 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/3/3Y", 69795.3, -238.649},
770 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/4/5Y", 69795.3, -371.553},
771 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/5/7Y", 69795.3, -653.972},
772 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/6/10Y", 69795.3, -1341.88},
773 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/7/15Y", 69795.3, -2138.11},
774 {
"3_Swap_GBP",
"Down:IndexCurve/GBP-LIBOR-6M/8/20Y", 69795.3, -12632.5},
775 {
"3_Swap_GBP",
"Up:FXSpot/EURGBP/0/spot", 69795.3, -691.043},
776 {
"3_Swap_GBP",
"Down:FXSpot/EURGBP/0/spot", 69795.3, 705.003},
777 {
"4_Swap_JPY",
"Up:DiscountCurve/JPY/0/6M", 871.03, -0.00750246},
778 {
"4_Swap_JPY",
"Up:DiscountCurve/JPY/1/1Y", 871.03, -0.00147994},
779 {
"4_Swap_JPY",
"Up:DiscountCurve/JPY/2/2Y", 871.03, -0.020079},
780 {
"4_Swap_JPY",
"Up:DiscountCurve/JPY/3/3Y", 871.03, -0.0667249},
781 {
"4_Swap_JPY",
"Up:DiscountCurve/JPY/4/5Y", 871.03, 4.75708},
782 {
"4_Swap_JPY",
"Down:DiscountCurve/JPY/0/6M", 871.03, 0.00747801},
783 {
"4_Swap_JPY",
"Down:DiscountCurve/JPY/1/1Y", 871.03, 0.00140807},
784 {
"4_Swap_JPY",
"Down:DiscountCurve/JPY/2/2Y", 871.03, 0.0199001},
785 {
"4_Swap_JPY",
"Down:DiscountCurve/JPY/3/3Y", 871.03, 0.0664106},
786 {
"4_Swap_JPY",
"Down:DiscountCurve/JPY/4/5Y", 871.03, -4.75978},
787 {
"4_Swap_JPY",
"Up:IndexCurve/JPY-LIBOR-6M/0/6M", 871.03, -193.514},
788 {
"4_Swap_JPY",
"Up:IndexCurve/JPY-LIBOR-6M/1/1Y", 871.03, 2.95767},
789 {
"4_Swap_JPY",
"Up:IndexCurve/JPY-LIBOR-6M/2/2Y", 871.03, 7.81453},
790 {
"4_Swap_JPY",
"Up:IndexCurve/JPY-LIBOR-6M/3/3Y", 871.03, 19.3576},
791 {
"4_Swap_JPY",
"Up:IndexCurve/JPY-LIBOR-6M/4/5Y", 871.03, 3832.83},
792 {
"4_Swap_JPY",
"Down:IndexCurve/JPY-LIBOR-6M/0/6M", 871.03, 193.528},
793 {
"4_Swap_JPY",
"Down:IndexCurve/JPY-LIBOR-6M/1/1Y", 871.03, -2.90067},
794 {
"4_Swap_JPY",
"Down:IndexCurve/JPY-LIBOR-6M/2/2Y", 871.03, -7.6631},
795 {
"4_Swap_JPY",
"Down:IndexCurve/JPY-LIBOR-6M/3/3Y", 871.03, -19.0907},
796 {
"4_Swap_JPY",
"Down:IndexCurve/JPY-LIBOR-6M/4/5Y", 871.03, -3832.59},
797 {
"4_Swap_JPY",
"Up:FXSpot/EURJPY/0/spot", 871.03, -8.62406},
798 {
"4_Swap_JPY",
"Down:FXSpot/EURJPY/0/spot", 871.03, 8.79829},
799 {
"5_Swaption_EUR",
"Up:DiscountCurve/EUR/6/10Y", 37524.3, -10.0118},
800 {
"5_Swaption_EUR",
"Up:DiscountCurve/EUR/7/15Y", 37524.3, -28.0892},
801 {
"5_Swaption_EUR",
"Up:DiscountCurve/EUR/8/20Y", 37524.3, -17.527},
802 {
"5_Swaption_EUR",
"Down:DiscountCurve/EUR/6/10Y", 37524.3, 10.0186},
803 {
"5_Swaption_EUR",
"Down:DiscountCurve/EUR/7/15Y", 37524.3, 28.117},
804 {
"5_Swaption_EUR",
"Down:DiscountCurve/EUR/8/20Y", 37524.3, 17.5502},
805 {
"5_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 37524.3, -395.215},
806 {
"5_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/7/15Y", 37524.3, 56.7319},
807 {
"5_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/8/20Y", 37524.3, 722.287},
808 {
"5_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 37524.3, 397.907},
809 {
"5_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/7/15Y", 37524.3, -56.508},
810 {
"5_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/8/20Y", 37524.3, -713.45},
811 {
"5_Swaption_EUR",
"Up:SwaptionVolatility/EUR/5/10Y/10Y/ATM", 37524.3, 367.609},
812 {
"5_Swaption_EUR",
"Down:SwaptionVolatility/EUR/5/10Y/10Y/ATM", 37524.3, -367.608},
813 {
"6_Swaption_EUR",
"Up:DiscountCurve/EUR/2/2Y", 10738, -0.485552},
814 {
"6_Swaption_EUR",
"Up:DiscountCurve/EUR/3/3Y", 10738, -1.09018},
815 {
"6_Swaption_EUR",
"Up:DiscountCurve/EUR/4/5Y", 10738, -1.98726},
816 {
"6_Swaption_EUR",
"Up:DiscountCurve/EUR/5/7Y", 10738, -0.591243},
817 {
"6_Swaption_EUR",
"Up:DiscountCurve/EUR/6/10Y", 10738, 0.00670807},
818 {
"6_Swaption_EUR",
"Down:DiscountCurve/EUR/2/2Y", 10738, 0.485614},
819 {
"6_Swaption_EUR",
"Down:DiscountCurve/EUR/3/3Y", 10738, 1.09029},
820 {
"6_Swaption_EUR",
"Down:DiscountCurve/EUR/4/5Y", 10738, 1.9877},
821 {
"6_Swaption_EUR",
"Down:DiscountCurve/EUR/5/7Y", 10738, 0.591282},
822 {
"6_Swaption_EUR",
"Down:DiscountCurve/EUR/6/10Y", 10738, -0.00670808},
823 {
"6_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", 10738, -97.3791},
824 {
"6_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", 10738, 4.0232},
825 {
"6_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", 10738, 8.90271},
826 {
"6_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", 10738, 322.893},
827 {
"6_Swaption_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 10738, 1.23647},
828 {
"6_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", 10738, 97.9474},
829 {
"6_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", 10738, -3.98874},
830 {
"6_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", 10738, -8.83916},
831 {
"6_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", 10738, -316.846},
832 {
"6_Swaption_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 10738, -1.23638},
833 {
"6_Swaption_EUR",
"Up:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 10738, 102.503},
834 {
"6_Swaption_EUR",
"Up:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 10738, 0.187152},
835 {
"6_Swaption_EUR",
"Down:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 10738, -102.502},
836 {
"6_Swaption_EUR",
"Down:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 10738, -0.187152},
837 {
"7_FxOption_EUR_USD",
"Up:DiscountCurve/EUR/3/3Y", 1.36968e+06, -2107.81},
838 {
"7_FxOption_EUR_USD",
"Up:DiscountCurve/EUR/4/5Y", 1.36968e+06, -3.85768},
839 {
"7_FxOption_EUR_USD",
"Up:DiscountCurve/USD/3/3Y", 1.36968e+06, 1698.91},
840 {
"7_FxOption_EUR_USD",
"Up:DiscountCurve/USD/4/5Y", 1.36968e+06, 3.10717},
841 {
"7_FxOption_EUR_USD",
"Down:DiscountCurve/EUR/3/3Y", 1.36968e+06, 2109.74},
842 {
"7_FxOption_EUR_USD",
"Down:DiscountCurve/EUR/4/5Y", 1.36968e+06, 3.85768},
843 {
"7_FxOption_EUR_USD",
"Down:DiscountCurve/USD/3/3Y", 1.36968e+06, -1698.12},
844 {
"7_FxOption_EUR_USD",
"Down:DiscountCurve/USD/4/5Y", 1.36968e+06, -3.10717},
845 {
"7_FxOption_EUR_USD",
"Up:FXSpot/EURUSD/0/spot", 1.36968e+06, 56850.7},
846 {
"7_FxOption_EUR_USD",
"Down:FXSpot/EURUSD/0/spot", 1.36968e+06, -56537.6},
847 {
"7_FxOption_EUR_USD",
"Up:FXVolatility/EURUSD/0/5Y/ATM", 1.36968e+06, 672236},
848 {
"7_FxOption_EUR_USD",
"Down:FXVolatility/EURUSD/0/5Y/ATM", 1.36968e+06, -329688},
849 {
"8_FxOption_EUR_GBP",
"Up:DiscountCurve/EUR/5/7Y", 798336, -2435.22},
850 {
"8_FxOption_EUR_GBP",
"Up:DiscountCurve/GBP/5/7Y", 798336, 1880.89},
851 {
"8_FxOption_EUR_GBP",
"Down:DiscountCurve/EUR/5/7Y", 798336, 2441.08},
852 {
"8_FxOption_EUR_GBP",
"Down:DiscountCurve/GBP/5/7Y", 798336, -1878.05},
853 {
"8_FxOption_EUR_GBP",
"Up:FXSpot/EURGBP/0/spot", 798336, 27009.9},
854 {
"8_FxOption_EUR_GBP",
"Down:FXSpot/EURGBP/0/spot", 798336, -26700.2},
855 {
"8_FxOption_EUR_GBP",
"Up:FXVolatility/EURGBP/0/5Y/ATM", 798336, 1.36635e+06},
856 {
"8_FxOption_EUR_GBP",
"Down:FXVolatility/EURGBP/0/5Y/ATM", 798336, -798336},
857 {
"9_Cap_EUR",
"Up:DiscountCurve/EUR/2/2Y", 289.105, -7.28588e-07},
858 {
"9_Cap_EUR",
"Up:DiscountCurve/EUR/3/3Y", 289.105, -0.000381869},
859 {
"9_Cap_EUR",
"Up:DiscountCurve/EUR/4/5Y", 289.105, -0.00790528},
860 {
"9_Cap_EUR",
"Up:DiscountCurve/EUR/5/7Y", 289.105, -0.0764893},
861 {
"9_Cap_EUR",
"Up:DiscountCurve/EUR/6/10Y", 289.105, -0.162697},
862 {
"9_Cap_EUR",
"Down:DiscountCurve/EUR/2/2Y", 289.105, 7.28664e-07},
863 {
"9_Cap_EUR",
"Down:DiscountCurve/EUR/3/3Y", 289.105, 0.000381934},
864 {
"9_Cap_EUR",
"Down:DiscountCurve/EUR/4/5Y", 289.105, 0.00790776},
865 {
"9_Cap_EUR",
"Down:DiscountCurve/EUR/5/7Y", 289.105, 0.0765231},
866 {
"9_Cap_EUR",
"Down:DiscountCurve/EUR/6/10Y", 289.105, 0.162824},
867 {
"9_Cap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/1/1Y", 289.105, -1.81582e-05},
868 {
"9_Cap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", 289.105, -0.00670729},
869 {
"9_Cap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", 289.105, -0.330895},
870 {
"9_Cap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", 289.105, -2.03937},
871 {
"9_Cap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", 289.105, -6.42991},
872 {
"9_Cap_EUR",
"Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 289.105, 15.5182},
873 {
"9_Cap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/1/1Y", 289.105, 1.97218e-05},
874 {
"9_Cap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", 289.105, 0.00746096},
875 {
"9_Cap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", 289.105, 0.353405},
876 {
"9_Cap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", 289.105, 2.24481},
877 {
"9_Cap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", 289.105, 7.1522},
878 {
"9_Cap_EUR",
"Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 289.105, -14.6675},
879 {
"9_Cap_EUR",
"Up:OptionletVolatility/EUR/4/1Y/0.05", 289.105, 8.49293e-05},
880 {
"9_Cap_EUR",
"Up:OptionletVolatility/EUR/9/2Y/0.05", 289.105, 0.0150901},
881 {
"9_Cap_EUR",
"Up:OptionletVolatility/EUR/14/3Y/0.05", 289.105, 0.620393},
882 {
"9_Cap_EUR",
"Up:OptionletVolatility/EUR/19/5Y/0.05", 289.105, 17.2057},
883 {
"9_Cap_EUR",
"Up:OptionletVolatility/EUR/24/10Y/0.05", 289.105, 24.4267},
884 {
"9_Cap_EUR",
"Down:OptionletVolatility/EUR/4/1Y/0.05", 289.105, -6.97789e-05},
885 {
"9_Cap_EUR",
"Down:OptionletVolatility/EUR/9/2Y/0.05", 289.105, -0.0125099},
886 {
"9_Cap_EUR",
"Down:OptionletVolatility/EUR/14/3Y/0.05", 289.105, -0.554344},
887 {
"9_Cap_EUR",
"Down:OptionletVolatility/EUR/19/5Y/0.05", 289.105, -16.1212},
888 {
"9_Cap_EUR",
"Down:OptionletVolatility/EUR/24/10Y/0.05", 289.105, -23.0264},
889 {
"10_Floor_USD",
"Up:DiscountCurve/USD/0/6M", 3406.46, -7.03494e-09},
890 {
"10_Floor_USD",
"Up:DiscountCurve/USD/1/1Y", 3406.46, -8.41429e-05},
891 {
"10_Floor_USD",
"Up:DiscountCurve/USD/2/2Y", 3406.46, -0.00329744},
892 {
"10_Floor_USD",
"Up:DiscountCurve/USD/3/3Y", 3406.46, -0.053884},
893 {
"10_Floor_USD",
"Up:DiscountCurve/USD/4/5Y", 3406.46, -0.269714},
894 {
"10_Floor_USD",
"Up:DiscountCurve/USD/5/7Y", 3406.46, -0.989583},
895 {
"10_Floor_USD",
"Up:DiscountCurve/USD/6/10Y", 3406.46, -1.26544},
896 {
"10_Floor_USD",
"Down:DiscountCurve/USD/0/6M", 3406.46, 7.0354e-09},
897 {
"10_Floor_USD",
"Down:DiscountCurve/USD/1/1Y", 3406.46, 8.41464e-05},
898 {
"10_Floor_USD",
"Down:DiscountCurve/USD/2/2Y", 3406.46, 0.00329786},
899 {
"10_Floor_USD",
"Down:DiscountCurve/USD/3/3Y", 3406.46, 0.0538949},
900 {
"10_Floor_USD",
"Down:DiscountCurve/USD/4/5Y", 3406.46, 0.269802},
901 {
"10_Floor_USD",
"Down:DiscountCurve/USD/5/7Y", 3406.46, 0.990038},
902 {
"10_Floor_USD",
"Down:DiscountCurve/USD/6/10Y", 3406.46, 1.26635},
903 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/0/6M", 3406.46, 0.00150733},
904 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/1/1Y", 3406.46, 0.240284},
905 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/2/2Y", 3406.46, 2.17175},
906 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/3/3Y", 3406.46, 7.77249},
907 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/4/5Y", 3406.46, 12.9642},
908 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/5/7Y", 3406.46, 16.8269},
909 {
"10_Floor_USD",
"Up:IndexCurve/USD-LIBOR-3M/6/10Y", 3406.46, -81.4363},
910 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/0/6M", 3406.46, -0.00139804},
911 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/1/1Y", 3406.46, -0.230558},
912 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/2/2Y", 3406.46, -2.00123},
913 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/3/3Y", 3406.46, -7.14862},
914 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/4/5Y", 3406.46, -11.2003},
915 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/5/7Y", 3406.46, -13.7183},
916 {
"10_Floor_USD",
"Down:IndexCurve/USD-LIBOR-3M/6/10Y", 3406.46, 84.0113},
917 {
"10_Floor_USD",
"Up:FXSpot/EURUSD/0/spot", 3406.46, -33.7273},
918 {
"10_Floor_USD",
"Down:FXSpot/EURUSD/0/spot", 3406.46, 34.4087},
919 {
"10_Floor_USD",
"Up:OptionletVolatility/USD/0/1Y/0.01", 3406.46, 0.402913},
920 {
"10_Floor_USD",
"Up:OptionletVolatility/USD/5/2Y/0.01", 3406.46, 3.32861},
921 {
"10_Floor_USD",
"Up:OptionletVolatility/USD/10/3Y/0.01", 3406.46, 16.8798},
922 {
"10_Floor_USD",
"Up:OptionletVolatility/USD/15/5Y/0.01", 3406.46, 96.415},
923 {
"10_Floor_USD",
"Up:OptionletVolatility/USD/20/10Y/0.01", 3406.46, 92.2212},
924 {
"10_Floor_USD",
"Down:OptionletVolatility/USD/0/1Y/0.01", 3406.46, -0.37428},
925 {
"10_Floor_USD",
"Down:OptionletVolatility/USD/5/2Y/0.01", 3406.46, -3.14445},
926 {
"10_Floor_USD",
"Down:OptionletVolatility/USD/10/3Y/0.01", 3406.46, -16.3074},
927 {
"10_Floor_USD",
"Down:OptionletVolatility/USD/15/5Y/0.01", 3406.46, -94.5309},
928 {
"10_Floor_USD",
"Down:OptionletVolatility/USD/20/10Y/0.01", 3406.46, -90.9303},
955 {
"12_EquityOption_SP5",
"Up:DiscountCurve/USD/2/2Y", 278936, 158.718 },
956 {
"12_EquityOption_SP5",
"Up:DiscountCurve/USD/3/3Y", 278936, 1.31198 },
957 {
"12_EquityOption_SP5",
"Down:DiscountCurve/USD/2/2Y", 278936, -158.676 },
958 {
"12_EquityOption_SP5",
"Down:DiscountCurve/USD/3/3Y", 278936, -1.31197 },
959 {
"12_EquityOption_SP5",
"Up:FXSpot/EURUSD/0/spot", 278936, -2761.74 },
960 {
"12_EquityOption_SP5",
"Down:FXSpot/EURUSD/0/spot", 278936, 2817.53 },
961 {
"12_EquityOption_SP5",
"Up:EquitySpot/SP5/0/spot", 278936, 10869.4 },
962 {
"12_EquityOption_SP5",
"Down:EquitySpot/SP5/0/spot", 278936, -10681 },
963 {
"12_EquityOption_SP5",
"Up:EquityVolatility/SP5/5/2Y/ATM", 278936, 2388.21 },
964 {
"12_EquityOption_SP5",
"Down:EquityVolatility/SP5/5/2Y/ATM", 278936, -2388.67 },
965 {
"13_EquityOption_Lufthansa",
"Up:DiscountCurve/EUR/2/2Y", 1830.8, 0.854602 },
966 {
"13_EquityOption_Lufthansa",
"Up:DiscountCurve/EUR/3/3Y", 1830.8, 0.0070644 },
967 {
"13_EquityOption_Lufthansa",
"Down:DiscountCurve/EUR/2/2Y", 1830.8, -0.854422 },
968 {
"13_EquityOption_Lufthansa",
"Down:DiscountCurve/EUR/3/3Y", 1830.8, -0.00706439 },
969 {
"13_EquityOption_Lufthansa",
"Up:EquitySpot/Lufthansa/0/spot", 1830.8, 61.7512 },
970 {
"13_EquityOption_Lufthansa",
"Down:EquitySpot/Lufthansa/0/spot", 1830.8, -60.866 },
971 {
"13_EquityOption_Lufthansa",
"Up:EquityVolatility/Lufthansa/5/2Y/ATM", 1830.8, 15.975 },
972 {
"13_EquityOption_Lufthansa",
"Down:EquityVolatility/Lufthansa/5/2Y/ATM", 1830.8, -15.9808 },
973 {
"14_YoYInflationCap_UKRPI",
"Up:DiscountCurve/GBP/1/1Y", 3495.36, -0.0190824},
974 {
"14_YoYInflationCap_UKRPI",
"Up:DiscountCurve/GBP/2/2Y", 3495.36, -0.0518755},
975 {
"14_YoYInflationCap_UKRPI",
"Up:DiscountCurve/GBP/3/3Y", 3495.36, -0.159743},
976 {
"14_YoYInflationCap_UKRPI",
"Up:DiscountCurve/GBP/4/5Y", 3495.36, -0.346412},
977 {
"14_YoYInflationCap_UKRPI",
"Up:DiscountCurve/GBP/5/7Y", 3495.36, -0.701974},
978 {
"14_YoYInflationCap_UKRPI",
"Up:DiscountCurve/GBP/6/10Y", 3495.36, -0.837257},
979 {
"14_YoYInflationCap_UKRPI",
"Down:DiscountCurve/GBP/1/1Y", 3495.36, 0.0190843},
980 {
"14_YoYInflationCap_UKRPI",
"Down:DiscountCurve/GBP/2/2Y", 3495.36, 0.0518857},
981 {
"14_YoYInflationCap_UKRPI",
"Down:DiscountCurve/GBP/3/3Y", 3495.36, 0.159784},
982 {
"14_YoYInflationCap_UKRPI",
"Down:DiscountCurve/GBP/4/5Y", 3495.36, 0.346541},
983 {
"14_YoYInflationCap_UKRPI",
"Down:DiscountCurve/GBP/5/7Y", 3495.36, 0.702328},
984 {
"14_YoYInflationCap_UKRPI",
"Down:DiscountCurve/GBP/6/10Y", 3495.36, 0.83791},
985 {
"14_YoYInflationCap_UKRPI",
"Up:FXSpot/EURGBP/0/spot", 3495.36, -34.6075},
986 {
"14_YoYInflationCap_UKRPI",
"Down:FXSpot/EURGBP/0/spot", 3495.36, 35.3067},
987 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCurve/UKRP1/0/1Y", 3495.36, 6.11718},
988 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCurve/UKRP1/1/2Y", 3495.36, 5.77751},
989 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCurve/UKRP1/2/3Y", 3495.36, 8.22785},
990 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCurve/UKRP1/3/5Y", 3495.36, 10.2605},
991 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCurve/UKRP1/4/7Y", 3495.36, 11.7006},
992 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCurve/UKRP1/5/10Y", 3495.36, 8.6242},
993 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCurve/UKRP1/0/1Y", 3495.36, -5.99639},
994 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCurve/UKRP1/1/2Y", 3495.36, -5.6966},
995 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCurve/UKRP1/2/3Y", 3495.36, -8.15092},
996 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCurve/UKRP1/3/5Y", 3495.36, -10.1917},
997 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCurve/UKRP1/4/7Y", 3495.36, -11.6375},
998 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCurve/UKRP1/5/10Y", 3495.36, -8.58138},
999 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCapFloorVolatility/UKRP1/4/1Y/0.02", 3495.36, 0.706362},
1000 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCapFloorVolatility/UKRP1/10/2Y/0.02", 3495.36, 0.575052},
1001 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCapFloorVolatility/UKRP1/16/3Y/0.02", 3495.36, 1.21162},
1002 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCapFloorVolatility/UKRP1/22/5Y/0.02", 3495.36, 1.83575},
1003 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCapFloorVolatility/UKRP1/28/7Y/0.02", 3495.36, 2.52242},
1004 {
"14_YoYInflationCap_UKRPI",
"Up:YoYInflationCapFloorVolatility/UKRP1/34/10Y/0.02", 3495.36, 1.8872},
1005 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCapFloorVolatility/UKRP1/4/1Y/0.02", 3495.36, -0.706362},
1006 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCapFloorVolatility/UKRP1/10/2Y/0.02", 3495.36, -0.575052},
1007 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCapFloorVolatility/UKRP1/16/3Y/0.02", 3495.36, -1.21162},
1008 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCapFloorVolatility/UKRP1/22/5Y/0.02", 3495.36, -1.83575},
1009 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCapFloorVolatility/UKRP1/28/7Y/0.02", 3495.36, -2.52242},
1010 {
"14_YoYInflationCap_UKRPI",
"Down:YoYInflationCapFloorVolatility/UKRP1/34/10Y/0.02", 3495.36, -1.8872}};
1012 std::map<pair<string, string>, Real> npvMap, sensiMap;
1013 for (Size i = 0; i < cachedResults.size(); ++i) {
1014 pair<string, string> p(cachedResults[i].
id, cachedResults[i].label);
1015 npvMap[p] = cachedResults[i].npv;
1016 sensiMap[p] = cachedResults[i].sensi;
1018 vector<pair<string, string>> ids;
1019 Real tiny = 1.0e-10;
1020 Real tolerance = 0.01;
1022 vector<ShiftScenarioGenerator::ScenarioDescription> desc = scenarioGenerator->scenarioDescriptions();
1023 size_t currentTradeIdx = 0;
1024 for (
const auto& [tradeId, _] : portfolio->trades()) {
1025 Real npv0 = cube->getT0(currentTradeIdx, 0);
1026 for (Size j = 1; j < scenarioGenerator->samples(); ++j) {
1027 Real npv = cube->get(currentTradeIdx, 0, j, 0);
1028 Real sensi = npv - npv0;
1030 if (fabs(sensi) > tiny) {
1033 pair<string, string> p(tradeId, label);
1035 QL_REQUIRE(npvMap.find(p) != npvMap.end(),
1036 "pair (" << p.first <<
", " << p.second <<
") not found in npv map");
1037 QL_REQUIRE(sensiMap.find(p) != sensiMap.end(),
1038 "pair (" << p.first <<
", " << p.second <<
") not found in sensi map");
1039 BOOST_CHECK_MESSAGE(fabs(npv0 - npvMap[p]) < tolerance || fabs((npv0 - npvMap[p]) / npv0) < tolerance,
1040 "npv regression failed for pair (" << p.first <<
", " << p.second <<
"): " << npv0
1041 <<
" vs " << npvMap[p]);
1042 BOOST_CHECK_MESSAGE(fabs(sensi - sensiMap[p]) < tolerance ||
1043 fabs((sensi - sensiMap[p]) / sensi) < tolerance,
1044 "sensitivity regression failed for pair ("
1045 << p.first <<
", " << p.second <<
"): " << sensi <<
" vs " << sensiMap[p]);
1053 BOOST_CHECK_MESSAGE(
count == cachedResults.size(),
"number of non-zero sensitivities ("
1054 <<
count <<
") do not match regression data ("
1055 << cachedResults.size() <<
")");
1057 BOOST_TEST_MESSAGE(
"Cube generated in " << elapsed <<
" seconds");
1058 ObservationMode::instance().setMode(backupMode);
1059 IndexManager::instance().clearHistories();
1064 SavedSettings backup;
1067 ObservationMode::instance().setMode(om);
1069 Date today = Date(14, April, 2016);
1070 Settings::instance().evaluationDate() = today;
1072 BOOST_TEST_MESSAGE(
"Today is " << today);
1075 string baseCcy =
"EUR";
1076 vector<string> ccys;
1077 ccys.push_back(baseCcy);
1078 ccys.push_back(
"GBP");
1079 ccys.push_back(
"CHF");
1080 ccys.push_back(
"USD");
1081 ccys.push_back(
"JPY");
1084 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
1087 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
setupSimMarketData5();
1093 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket =
1094 QuantLib::ext::make_shared<analytics::ScenarioSimMarket>(initMarket, simMarketData);
1097 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
1098 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory =
1099 QuantLib::ext::make_shared<ore::analytics::DeltaScenarioFactory>(baseScenario);
1102 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
1103 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
1104 scenarioFactory,
false);
1105 simMarket->scenarioGenerator() = scenarioGenerator;
1108 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
1109 engineData->model(
"Swap") =
"DiscountedCashflows";
1110 engineData->engine(
"Swap") =
"DiscountingSwapEngine";
1111 engineData->model(
"CrossCurrencySwap") =
"DiscountedCashflows";
1112 engineData->engine(
"CrossCurrencySwap") =
"DiscountingCrossCurrencySwapEngine";
1113 engineData->model(
"EuropeanSwaption") =
"BlackBachelier";
1114 engineData->engine(
"EuropeanSwaption") =
"BlackBachelierSwaptionEngine";
1115 engineData->model(
"FxForward") =
"DiscountedCashflows";
1116 engineData->engine(
"FxForward") =
"DiscountingFxForwardEngine";
1117 engineData->model(
"FxOption") =
"GarmanKohlhagen";
1118 engineData->engine(
"FxOption") =
"AnalyticEuropeanEngine";
1119 engineData->model(
"CapFloor") =
"IborCapModel";
1120 engineData->engine(
"CapFloor") =
"IborCapEngine";
1121 engineData->model(
"CapFlooredIborLeg") =
"BlackOrBachelier";
1122 engineData->engine(
"CapFlooredIborLeg") =
"BlackIborCouponPricer";
1123 engineData->model(
"YYCapFloor") =
"YYCapModel";
1124 engineData->engine(
"YYCapFloor") =
"YYCapEngine";
1125 engineData->model(
"Bond") =
"DiscountedCashflows";
1126 engineData->engine(
"Bond") =
"DiscountingRiskyBondEngine";
1127 engineData->engineParameters(
"Bond")[
"TimestepPeriod"] =
"6M";
1128 engineData->model(
"CreditDefaultSwap") =
"DiscountedCashflows";
1129 engineData->engine(
"CreditDefaultSwap") =
"MidPointCdsEngine";
1130 engineData->model(
"EquityOption") =
"BlackScholesMerton";
1131 engineData->engine(
"EquityOption") =
"AnalyticEuropeanEngine";
1132 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(engineData, simMarket);
1135 QuantLib::ext::shared_ptr<Portfolio> portfolio(
new Portfolio());
1136 portfolio->add(
buildSwap(
"1_Swap_EUR",
"EUR",
true, 10000000.0, 0, 10, 0.03, 0.00,
"1Y",
1137 "30/360",
"6M",
"A360",
"EUR-EURIBOR-6M"));
1138 portfolio->add(
buildSwap(
"2_Swap_USD",
"USD",
true, 10000000.0, 0, 15, 0.02, 0.00,
"6M",
1139 "30/360",
"3M",
"A360",
"USD-LIBOR-3M"));
1140 portfolio->add(
buildCap(
"9_Cap_EUR",
"EUR",
"Long", 0.05, 1000000.0, 0, 10,
"6M",
"A360",
1142 portfolio->add(
buildFloor(
"10_Floor_USD",
"USD",
"Long", 0.01, 1000000.0, 0, 10,
"3M",
"A360",
1144 portfolio->add(
buildZeroBond(
"11_ZeroBond_EUR",
"EUR", 1000000.0, 10));
1145 portfolio->add(
buildZeroBond(
"12_ZeroBond_USD",
"USD", 1000000.0, 10));
1147 buildEquityOption(
"13_EquityOption_SP5",
"Long",
"Call", 2,
"SP5",
"USD", 2147.56, 1000));
1149 0.02, 0, 10,
"1Y",
"ACT/ACT",
"UKRP1",
"2M", 2));
1150 portfolio->build(factory);
1151 BOOST_TEST_MESSAGE(
"Portfolio size after build: " << portfolio->size());
1157 QuantLib::ext::shared_ptr<SensitivityAnalysis> zeroAnalysis = QuantLib::ext::make_shared<SensitivityAnalysis>(
1159 BOOST_TEST_MESSAGE(
"SensitivityAnalysis object built");
1160 zeroAnalysis->overrideTenors(
true);
1161 zeroAnalysis->generateSensitivities();
1162 BOOST_TEST_MESSAGE(
"Raw sensitivity analsis done");
1163 BOOST_TEST_MESSAGE(
"Par sensitivity analsis object built");
1171 QuantLib::ext::shared_ptr<ParSensitivityConverter> parConverter =
1173 QuantLib::ext::shared_ptr<SensitivityCube> sensiCube = zeroAnalysis->sensiCube();
1176 map<pair<string, string>, Real> parDelta;
1177 for (
const auto& tradeId : portfolio->ids()) {
1180 for (
const auto& kv : temp) {
1183 string des = sensiCube->factorDescription(kv.first);
1184 parDelta[make_pair(tradeId, des)] = kv.second;
1195 std::vector<Results> cachedResults = {
1196 {
"10_Floor_USD",
"DiscountCurve/USD/0/6M", -0.00112886},
1197 {
"10_Floor_USD",
"DiscountCurve/USD/1/1Y", 0.00675206},
1198 {
"10_Floor_USD",
"DiscountCurve/USD/2/2Y", 0.00900048},
1199 {
"10_Floor_USD",
"DiscountCurve/USD/3/3Y", -0.0302434},
1200 {
"10_Floor_USD",
"DiscountCurve/USD/4/5Y", -0.262464},
1201 {
"10_Floor_USD",
"DiscountCurve/USD/5/7Y", -1.07006},
1202 {
"10_Floor_USD",
"DiscountCurve/USD/6/10Y", -1.04325},
1203 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/0/6M", 0.00386584},
1204 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/1/1Y", 0.2381},
1205 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/2/2Y", 2.2426},
1206 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/3/3Y", 7.56822},
1207 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/4/5Y", 15.9842},
1208 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/5/7Y", 22.2464},
1209 {
"10_Floor_USD",
"IndexCurve/USD-LIBOR-3M/6/10Y", -89.3588},
1210 {
"10_Floor_USD",
"OptionletVolatility/USD/0/1Y/0.01", -0.622505},
1211 {
"10_Floor_USD",
"OptionletVolatility/USD/10/3Y/0.01", -2.20215},
1212 {
"10_Floor_USD",
"OptionletVolatility/USD/15/5Y/0.01", 1.77487},
1213 {
"10_Floor_USD",
"OptionletVolatility/USD/20/10Y/0.01", 207.854},
1214 {
"10_Floor_USD",
"OptionletVolatility/USD/5/2Y/0.01", 1.78417},
1215 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/0/6M", 1.53634},
1216 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/1/1Y", 3.53444},
1217 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/2/2Y", 8.6117},
1218 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/3/3Y", 18.5064},
1219 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/4/5Y", 39.4197},
1220 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/5/7Y", 36.4505},
1221 {
"11_ZeroBond_EUR",
"SurvivalProbability/BondIssuer1/6/10Y", -600.06},
1222 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/0/6M", -0.657215},
1223 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/1/1Y", 2.95782},
1224 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/2/2Y", 6.06677},
1225 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/3/3Y", 14.1153},
1226 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/4/5Y", 32.8224},
1227 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/5/7Y", 58.069},
1228 {
"11_ZeroBond_EUR",
"YieldCurve/BondCurve1/6/10Y", -690.301},
1229 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/0/6M", 1.28029},
1230 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/1/1Y", 2.94537},
1231 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/2/2Y", 7.17642},
1232 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/3/3Y", 15.422},
1233 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/4/5Y", 32.8498},
1234 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/5/7Y", 30.3754},
1235 {
"12_ZeroBond_USD",
"SurvivalProbability/BondIssuer1/6/10Y", -500.05},
1236 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/0/6M", -0.547679},
1237 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/1/1Y", 2.46485},
1238 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/2/2Y", 5.05564},
1239 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/3/3Y", 11.7627},
1240 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/4/5Y", 27.352},
1241 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/5/7Y", 48.3909},
1242 {
"12_ZeroBond_USD",
"YieldCurve/BondCurve1/6/10Y", -575.251},
1243 {
"13_EquityOption_SP5",
"DiscountCurve/USD/0/6M", 0.270388},
1244 {
"13_EquityOption_SP5",
"DiscountCurve/USD/1/1Y", -1.35418},
1245 {
"13_EquityOption_SP5",
"DiscountCurve/USD/2/2Y", 158.893},
1246 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/0/6M", 0.00347664},
1247 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/1/1Y", -0.00921372},
1248 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/2/2Y", -0.0271867},
1249 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/3/3Y", -0.0973079},
1250 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/4/5Y", -0.298947},
1251 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/5/7Y", -0.69657},
1252 {
"14_YoYInflationCap_UKRPI",
"DiscountCurve/GBP/6/10Y", -0.950666},
1253 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCapFloorVolatility/UKRP1/10/2Y/0.02", 0.131713},
1254 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCapFloorVolatility/UKRP1/16/3Y/0.02", -0.155071},
1255 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCapFloorVolatility/UKRP1/22/5Y/0.02", 0.336249},
1256 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCapFloorVolatility/UKRP1/28/7Y/0.02", -0.585254},
1257 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCapFloorVolatility/UKRP1/34/10Y/0.02", 9.11852},
1258 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCapFloorVolatility/UKRP1/4/1Y/0.02", -0.0981938},
1259 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCurve/UKRP1/0/1Y", -0.501498},
1260 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCurve/UKRP1/1/2Y", 0.104595},
1261 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCurve/UKRP1/2/3Y", -0.258415},
1262 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCurve/UKRP1/3/5Y", 1.13565},
1263 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCurve/UKRP1/4/7Y", -2.64434},
1264 {
"14_YoYInflationCap_UKRPI",
"YoYInflationCurve/UKRP1/5/10Y", 52.8805},
1265 {
"1_Swap_EUR",
"DiscountCurve/EUR/0/6M", 3.55166},
1266 {
"1_Swap_EUR",
"DiscountCurve/EUR/1/1Y", 8.07755},
1267 {
"1_Swap_EUR",
"DiscountCurve/EUR/2/2Y", 15.787},
1268 {
"1_Swap_EUR",
"DiscountCurve/EUR/3/3Y", 36.2307},
1269 {
"1_Swap_EUR",
"DiscountCurve/EUR/4/5Y", 81.6737},
1270 {
"1_Swap_EUR",
"DiscountCurve/EUR/5/7Y", 146.97},
1271 {
"1_Swap_EUR",
"DiscountCurve/EUR/6/10Y", 170.249},
1272 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/0/6M", -492.385},
1273 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/1/1Y", 0.267094},
1274 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.0571774},
1275 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.00710812},
1276 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.201881},
1277 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/5/7Y", 34.3404},
1278 {
"1_Swap_EUR",
"IndexCurve/EUR-EURIBOR-6M/6/10Y", 8928.34},
1279 {
"2_Swap_USD",
"DiscountCurve/USD/0/6M", -1.47948},
1280 {
"2_Swap_USD",
"DiscountCurve/USD/1/1Y", -3.99176},
1281 {
"2_Swap_USD",
"DiscountCurve/USD/2/2Y", -10.9621},
1282 {
"2_Swap_USD",
"DiscountCurve/USD/3/3Y", -25.1411},
1283 {
"2_Swap_USD",
"DiscountCurve/USD/4/5Y", -57.393},
1284 {
"2_Swap_USD",
"DiscountCurve/USD/5/7Y", -103.903},
1285 {
"2_Swap_USD",
"DiscountCurve/USD/6/10Y", -250.483},
1286 {
"2_Swap_USD",
"DiscountCurve/USD/7/15Y", -269.282},
1287 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/0/6M", -198.455},
1288 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/1/1Y", 0.163363},
1289 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/2/2Y", -0.0310057},
1290 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/3/3Y", -0.00237856},
1291 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/4/5Y", -0.126057},
1292 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/5/7Y", 0.117712},
1293 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/6/10Y", 10.6825},
1294 {
"2_Swap_USD",
"IndexCurve/USD-LIBOR-3M/7/15Y", 9972.55},
1295 {
"9_Cap_EUR",
"DiscountCurve/EUR/0/6M", 0.000267715},
1296 {
"9_Cap_EUR",
"DiscountCurve/EUR/1/1Y", 1.93692e-06},
1297 {
"9_Cap_EUR",
"DiscountCurve/EUR/2/2Y", 0.00120582},
1298 {
"9_Cap_EUR",
"DiscountCurve/EUR/3/3Y", 0.0038175},
1299 {
"9_Cap_EUR",
"DiscountCurve/EUR/4/5Y", 0.00870478},
1300 {
"9_Cap_EUR",
"DiscountCurve/EUR/5/7Y", -0.0375854},
1301 {
"9_Cap_EUR",
"DiscountCurve/EUR/6/10Y", -0.25186},
1302 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/0/6M", 0.000685155},
1303 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/1/1Y", -0.00175651},
1304 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.0118899},
1305 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.301921},
1306 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/4/5Y", -2.28152},
1307 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/5/7Y", -7.16938},
1308 {
"9_Cap_EUR",
"IndexCurve/EUR-EURIBOR-6M/6/10Y", 16.3599},
1309 {
"9_Cap_EUR",
"OptionletVolatility/EUR/14/3Y/0.05", -0.0903623},
1310 {
"9_Cap_EUR",
"OptionletVolatility/EUR/19/5Y/0.05", 0.0577696},
1311 {
"9_Cap_EUR",
"OptionletVolatility/EUR/24/10Y/0.05", 41.9784},
1312 {
"9_Cap_EUR",
"OptionletVolatility/EUR/4/1Y/0.05", -0.0489527},
1313 {
"9_Cap_EUR",
"OptionletVolatility/EUR/9/2Y/0.05", 0.0995465}};
1315 std::map<pair<string, string>, Real> sensiMap;
1316 for (Size i = 0; i < cachedResults.size(); ++i) {
1317 pair<string, string> p(cachedResults[i].
id, cachedResults[i].label);
1318 sensiMap[p] = cachedResults[i].sensi;
1321 Real tolerance = 0.01;
1323 for (
auto data : parDelta) {
1324 pair<string, string> p =
data.first;
1325 Real delta =
data.second;
1326 if (fabs(delta) > 0.0) {
1328 BOOST_CHECK_MESSAGE(sensiMap.find(p) != sensiMap.end(),
1329 "pair (" << p.first <<
", " << p.second <<
") not found in sensi map");
1330 if (sensiMap.find(p) != sensiMap.end()) {
1331 BOOST_CHECK_MESSAGE(fabs(delta - sensiMap[p]) < tolerance ||
1332 fabs((delta - sensiMap[p]) / delta) < tolerance,
1333 "sensitivity regression failed for pair ("
1334 << p.first <<
", " << p.second <<
"): " << delta <<
" vs " << sensiMap[p]);
1338 BOOST_CHECK_MESSAGE(
count == cachedResults.size(),
"number of non-zero par sensitivities ("
1339 <<
count <<
") do not match regression data ("
1340 << cachedResults.size() <<
")");
1341 ObservationMode::instance().setMode(backupMode);
1342 IndexManager::instance().clearHistories();
1346 BOOST_TEST_MESSAGE(
"Testing Sensitivity Par Conversion (None observation mode)");
1351 BOOST_TEST_MESSAGE(
"Testing Sensitivity Par Conversion (Disable observation mode)");
1356 BOOST_TEST_MESSAGE(
"Testing Sensitivity Par Conversion (Defer observation mode)");
1361 BOOST_TEST_MESSAGE(
"Testing Sensitivity Par Conversion (Unregister observation mode)");
1366 BOOST_TEST_MESSAGE(
"Testing 1d shifts");
1368 SavedSettings backup;
1370 ObservationMode::instance().setMode(ObservationMode::Mode::None);
1372 Date today = Date(14, April, 2016);
1373 Settings::instance().evaluationDate() = today;
1375 BOOST_TEST_MESSAGE(
"Today is " << today);
1378 string baseCcy =
"EUR";
1379 vector<string> ccys;
1380 ccys.push_back(baseCcy);
1381 ccys.push_back(
"GBP");
1384 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
1387 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
setupSimMarketData2();
1390 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket =
1391 QuantLib::ext::make_shared<analytics::ScenarioSimMarket>(initMarket, simMarketData);
1397 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
1398 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory =
1399 QuantLib::ext::make_shared<ore::analytics::DeltaScenarioFactory>(baseScenario);
1402 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
1403 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
1404 scenarioFactory,
false);
1407 vector<Period> tenors = simMarketData->yieldCurveTenors(
"");
1408 vector<Real> initialZeros(tenors.size());
1409 vector<Real> times(tenors.size());
1410 string ccy = simMarketData->ccys()[0];
1411 Handle<YieldTermStructure> ts = initMarket->discountCurve(ccy);
1412 DayCounter dc = ts->dayCounter();
1413 for (Size j = 0; j < tenors.size(); ++j) {
1414 Date d = today + simMarketData->yieldCurveTenors(
"")[j];
1415 initialZeros[j] = ts->zeroRate(d, dc, Continuous);
1416 times[j] = dc.yearFraction(today, d);
1423 vector<Period> shiftTenors = sensiData->discountCurveShiftData()[
"EUR"]->shiftTenors;
1424 vector<Time> shiftTimes(shiftTenors.size());
1425 for (Size i = 0; i < shiftTenors.size(); ++i)
1426 shiftTimes[i] = dc.yearFraction(today, today + shiftTenors[i]);
1428 vector<Real> shiftedZeros(tenors.size());
1429 vector<Real> diffAbsolute(tenors.size(), 0.0);
1430 vector<Real> diffRelative(tenors.size(), 0.0);
1431 Real shiftSize = 0.01;
1432 ShiftType shiftTypeAbsolute = ShiftType::Absolute;
1433 ShiftType shiftTypeRelative = ShiftType::Relative;
1434 for (Size i = 0; i < shiftTenors.size(); ++i) {
1435 scenarioGenerator->applyShift(i, shiftSize,
true, shiftTypeAbsolute, shiftTimes, initialZeros, times,
1436 shiftedZeros,
true);
1437 for (Size j = 0; j < tenors.size(); ++j)
1438 diffAbsolute[j] += shiftedZeros[j] - initialZeros[j];
1439 scenarioGenerator->applyShift(i, shiftSize,
true, shiftTypeRelative, shiftTimes, initialZeros, times,
1440 shiftedZeros,
true);
1441 for (Size j = 0; j < tenors.size(); ++j)
1442 diffRelative[j] += shiftedZeros[j] / initialZeros[j] - 1.0;
1445 Real tolerance = 1.0e-10;
1446 for (Size j = 0; j < tenors.size(); ++j) {
1448 BOOST_CHECK_MESSAGE(fabs(diffAbsolute[j] - shiftSize) < tolerance,
1449 "inconsistency in absolute 1d shifts at curve tenor point " << j);
1450 BOOST_CHECK_MESSAGE(fabs(diffRelative[j] - shiftSize) < tolerance,
1451 "inconsistency in relative 1d shifts at curve tenor point " << j);
1453 ObservationMode::instance().setMode(backupMode);
1454 IndexManager::instance().clearHistories();
1458 BOOST_TEST_MESSAGE(
"Testing 2d shifts");
1460 SavedSettings backup;
1463 ObservationMode::instance().setMode(ObservationMode::Mode::None);
1465 Date today = Date(14, April, 2016);
1466 Settings::instance().evaluationDate() = today;
1468 BOOST_TEST_MESSAGE(
"Today is " << today);
1471 string baseCcy =
"EUR";
1472 vector<string> ccys;
1473 ccys.push_back(baseCcy);
1474 ccys.push_back(
"GBP");
1477 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
1480 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
setupSimMarketData2();
1483 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket =
1484 QuantLib::ext::make_shared<analytics::ScenarioSimMarket>(initMarket, simMarketData);
1490 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
1491 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory =
1492 QuantLib::ext::make_shared<ore::analytics::DeltaScenarioFactory>(baseScenario);
1495 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
1496 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
1497 scenarioFactory,
false);
1500 vector<Period> expiries = simMarketData->swapVolExpiries(
"");
1501 vector<Period> terms = simMarketData->swapVolTerms(
"");
1502 vector<vector<Real>> initialData(expiries.size(), vector<Real>(terms.size(), 0.0));
1503 vector<Real> expiryTimes(expiries.size());
1504 vector<Real> termTimes(terms.size());
1505 string ccy = simMarketData->ccys()[0];
1506 Handle<SwaptionVolatilityStructure> ts = initMarket->swaptionVol(ccy);
1507 DayCounter dc = ts->dayCounter();
1508 for (Size i = 0; i < expiries.size(); ++i)
1509 expiryTimes[i] = dc.yearFraction(today, today + expiries[i]);
1510 for (Size j = 0; j < terms.size(); ++j)
1511 termTimes[j] = dc.yearFraction(today, today + terms[j]);
1512 for (Size i = 0; i < expiries.size(); ++i) {
1513 for (Size j = 0; j < terms.size(); ++j)
1514 initialData[i][j] = ts->volatility(expiries[i], terms[j], Null<Real>());
1521 vector<Period> expiryShiftTenors = sensiData->swaptionVolShiftData()[
"EUR"].shiftExpiries;
1522 vector<Period> termShiftTenors = sensiData->swaptionVolShiftData()[
"EUR"].shiftTerms;
1523 vector<Real> shiftExpiryTimes(expiryShiftTenors.size());
1524 vector<Real> shiftTermTimes(termShiftTenors.size());
1525 for (Size i = 0; i < expiryShiftTenors.size(); ++i)
1526 shiftExpiryTimes[i] = dc.yearFraction(today, today + expiryShiftTenors[i]);
1527 for (Size j = 0; j < termShiftTenors.size(); ++j)
1528 shiftTermTimes[j] = dc.yearFraction(today, today + termShiftTenors[j]);
1530 vector<vector<Real>> shiftedData(expiries.size(), vector<Real>(terms.size(), 0.0));
1531 vector<vector<Real>> diffAbsolute(expiries.size(), vector<Real>(terms.size(), 0.0));
1532 vector<vector<Real>> diffRelative(expiries.size(), vector<Real>(terms.size(), 0.0));
1533 Real shiftSize = 0.01;
1534 ShiftType shiftTypeAbsolute = ShiftType::Absolute;
1535 ShiftType shiftTypeRelative = ShiftType::Relative;
1536 for (Size i = 0; i < expiryShiftTenors.size(); ++i) {
1537 for (Size j = 0; j < termShiftTenors.size(); ++j) {
1538 scenarioGenerator->applyShift(i, j, shiftSize,
true, shiftTypeAbsolute, shiftExpiryTimes, shiftTermTimes,
1539 expiryTimes, termTimes, initialData, shiftedData,
true);
1540 for (Size k = 0; k < expiries.size(); ++k) {
1541 for (Size l = 0; l < terms.size(); ++l)
1542 diffAbsolute[k][l] += shiftedData[k][l] - initialData[k][l];
1544 scenarioGenerator->applyShift(i, j, shiftSize,
true, shiftTypeRelative, shiftExpiryTimes, shiftTermTimes,
1545 expiryTimes, termTimes, initialData, shiftedData,
true);
1546 for (Size k = 0; k < expiries.size(); ++k) {
1547 for (Size l = 0; l < terms.size(); ++l)
1548 diffRelative[k][l] += shiftedData[k][l] / initialData[k][l] - 1.0;
1553 Real tolerance = 1.0e-10;
1554 for (Size k = 0; k < expiries.size(); ++k) {
1555 for (Size l = 0; l < terms.size(); ++l) {
1558 BOOST_CHECK_MESSAGE(fabs(diffAbsolute[k][l] - shiftSize) < tolerance,
1559 "inconsistency in absolute 2d shifts at grid point (" << k <<
", " << l
1560 <<
"): " << diffAbsolute[k][l]);
1561 BOOST_CHECK_MESSAGE(fabs(diffRelative[k][l] - shiftSize) < tolerance,
1562 "inconsistency in relative 2d shifts at grid point (" << k <<
", " << l
1563 <<
"): " << diffRelative[k][l]);
1566 ObservationMode::instance().setMode(backupMode);
1567 IndexManager::instance().clearHistories();
1575 BOOST_TEST_MESSAGE(
"Testing 1-d Zero Shifts");
1580 BOOST_TEST_MESSAGE(
"Testing 2-d Zero Shifts");
1585 BOOST_TEST_MESSAGE(
"Testing Portfolio Zero Sensitivity");
1590 BOOST_TEST_MESSAGE(
"Testing Par Conversion NoneObs");
1595 BOOST_TEST_MESSAGE(
"Testing Par Conversion DisableObs");
1600 BOOST_TEST_MESSAGE(
"Testing Par Conversion DeferObs");
1605 BOOST_TEST_MESSAGE(
"Testing Par Conversion UnregisterObs");
1609BOOST_AUTO_TEST_SUITE_END()
1611BOOST_AUTO_TEST_SUITE_END()
Par Sensitivity Analysis.
void alignPillars()
align pillars in scenario simulation market parameters with those of the par instruments
const ParContainer & parSensitivities() const
Return computed par sensitivities. Empty if they have not been computed yet.
std::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > shiftSizes() const
Return the zero rate and par rate absolute shift size for each risk factor key.
void computeParInstrumentSensitivities(const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket)
Compute par instrument sensitivities.
static bool isParType(ore::analytics::RiskFactorKey::KeyType type)
Returns true if risk factor type is applicable for par conversion.
ScenarioSimMarket description.
void buildCube(const QuantLib::ext::shared_ptr< data::Portfolio > &portfolio, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCube, std::vector< QuantLib::ext::shared_ptr< ValuationCalculator > > calculators, bool mporStickyDate=true, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCubeNettingSet=nullptr, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCptyCube=nullptr, std::vector< QuantLib::ext::shared_ptr< CounterpartyCalculator > > cptyCalculators={}, bool dryRun=false)
Build NPV cube.
std::map< ore::analytics::RiskFactorKey, QuantLib::Real > parDeltas(const std::string &tradeId) const
Return the non-zero par deltas for the given tradeId.
static const string defaultConfiguration
OREAnalytics Top level fixture.
static void testPortfolioZeroSensitivity()
Test that the portfolio shows the expected sensitivity (regression test)
static void test1dZeroShifts()
Test that shifting all shift curve tenor points by DELTA yields DELTA shifts at all tenor points of t...
static void test2dZeroShifts()
Test that shifting all 2-d shift tenor points by DELTA yields DELTA shifts at all 2-d grid points of ...
static void testParConversionDisableObs()
Test par conversion of sensitivities ("Disable" observation mode)
static void testParConversionDeferObs()
Test par conversion of sensitivities ("Defer" observation mode)
static void testParConversionUnregisterObs()
Test par conversion of sensitivities ("Unregister" observation mode)
static void testParConversionNoneObs()
Test par conversion of sensitivities ("None" observation mode)
factory class for cloning a cached scenario
A cube implementation that stores the cube in memory.
std::string to_string(const LocationInfo &l)
QuantLib::ext::shared_ptr< Trade > buildCap(string id, string ccy, string longShort, Real capRate, Real notional, int start, Size term, string floatFreq, string floatDC, string index, Calendar calendar, Natural spotDays, bool spotStartLag)
QuantLib::ext::shared_ptr< Trade > buildFxOption(string id, string longShort, string putCall, Size expiry, string boughtCcy, Real boughtAmount, string soldCcy, Real soldAmount, Real premium, string premiumCcy, string premiumDate)
QuantLib::ext::shared_ptr< Trade > buildSwap(string id, string ccy, bool isPayer, Real notional, int start, Size term, Real rate, Real spread, string fixedFreq, string fixedDC, string floatFreq, string floatDC, string index, Calendar calendar, Natural spotDays, bool spotStartLag)
QuantLib::ext::shared_ptr< Trade > buildZeroBond(string id, string ccy, Real notional, Size term, string suffix)
QuantLib::ext::shared_ptr< Trade > buildEquityOption(string id, string longShort, string putCall, Size expiry, string equityName, string currency, Real strike, Real quantity, Real premium, string premiumCcy, string premiumDate)
QuantLib::ext::shared_ptr< Trade > buildFloor(string id, string ccy, string longShort, Real floorRate, Real notional, int start, Size term, string floatFreq, string floatDC, string index, Calendar calendar, Natural spotDays, bool spotStartLag)
QuantLib::ext::shared_ptr< Trade > buildEuropeanSwaption(string id, string longShort, string ccy, bool isPayer, Real notional, int start, Size term, Real rate, Real spread, string fixedFreq, string fixedDC, string floatFreq, string floatDC, string index, string cashPhysical, Real premium, string premiumCcy, string premiumDate)
BOOST_AUTO_TEST_CASE(ZeroShifts1d)
QuantLib::ext::shared_ptr< Trade > buildYYInflationCapFloor(string id, string ccy, Real notional, bool isCap, bool isLong, Real capFloorRate, int start, Size term, string yyFreq, string yyDC, string yyIndex, string observationLag, Size fixDays)
void testParConversion(ObservationMode::Mode om)
Singleton class to hold global Observation Mode.
Perfrom sensitivity analysis for a given portfolio.
Fixture that can be used at top level of OREAnalytics test suites.
A Market class that can be updated by Scenarios.
A class to hold Scenario parameters for scenarioSimMarket.
Perform sensitivity analysis for a given portfolio.
A class to hold the parametrisation for building sensitivity scenarios.
Sensitivity scenario generation.
vector< Period > shiftExpiries
vector< Period > shiftTenors
map< string, string > parInstrumentConventions
bool parInstrumentSingleCurve
vector< string > parInstruments
vector< Period > shiftTerms
vector< Real > shiftStrikes
vector< Period > shiftExpiries
QuantLib::ext::shared_ptr< SensitivityScenarioData > setupSensitivityScenarioData2()
QuantLib::ext::shared_ptr< SensitivityScenarioData > setupSensitivityScenarioData5(bool parConversion)
QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > setupSimMarketData5()
QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > setupSimMarketData2()
SensitivityScenarioData::CurveShiftParData createCurveShiftData()
Par Sensitivity analysis tests.
The counterparty cube calculator interface.
Class for converting zero sensitivities to par sensitivities.