Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
sensitivityperformanceplus.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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
21#include "testmarket.hpp"
22#include "testportfolio.hpp"
23
24#include <boost/timer/timer.hpp>
27#include <orea/cube/npvcube.hpp>
55#include <ql/math/randomnumbers/mt19937uniformrng.hpp>
56#include <ql/time/calendars/target.hpp>
57#include <ql/time/date.hpp>
58#include <ql/time/daycounters/actualactual.hpp>
60
61using namespace std;
62using namespace QuantLib;
63using namespace QuantExt;
64using namespace boost::unit_test_framework;
65using namespace ore;
66using namespace ore::data;
67using namespace ore::analytics;
68
69namespace {
70
71// Returns an int in the interval [min, max]. Inclusive.
72inline unsigned long randInt(MersenneTwisterUniformRng& rng, Size min, Size max) {
73 return min + (rng.nextInt32() % (max + 1 - min));
74}
75
76inline const string& randString(MersenneTwisterUniformRng& rng, const vector<string>& strs) {
77 return strs[randInt(rng, 0, strs.size() - 1)];
78}
79
80inline bool randBoolean(MersenneTwisterUniformRng& rng) { return randInt(rng, 0, 1) == 1; }
81
82QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> setupSimMarketData5() {
83 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData(
85
86 simMarketData->baseCcy() = "EUR";
87 simMarketData->setDiscountCurveNames({"EUR", "GBP", "USD", "CHF", "JPY"});
88 simMarketData->setYieldCurveTenors("", {1 * Months, 6 * Months, 1 * Years, 2 * Years, 3 * Years, 4 * Years,
89 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years, 30 * Years});
90 simMarketData->setIndices(
91 {"EUR-EURIBOR-6M", "USD-LIBOR-3M", "USD-LIBOR-6M", "GBP-LIBOR-6M", "CHF-LIBOR-6M", "JPY-LIBOR-6M"});
92 simMarketData->interpolation() = "LogLinear";
93
94 simMarketData->setSwapVolTerms("", {1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 20 * Years});
95 simMarketData->setSwapVolExpiries(
96 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 20 * Years});
97 simMarketData->setSwapVolKeys({"EUR", "GBP", "USD", "CHF", "JPY"});
98 simMarketData->swapVolDecayMode() = "ForwardVariance";
99 simMarketData->setSimulateSwapVols(true); // false;
100
101 simMarketData->setFxVolExpiries("",
102 vector<Period>{1 * Months, 3 * Months, 6 * Months, 2 * Years, 3 * Years, 4 * Years, 5 * Years});
103 simMarketData->setFxVolDecayMode(string("ConstantVariance"));
104 simMarketData->setSimulateFXVols(true); // false;
105 simMarketData->setFxVolCcyPairs({"EURUSD", "EURGBP", "EURCHF", "EURJPY"});
106 simMarketData->setFxVolIsSurface(true);
107 simMarketData->setFxVolMoneyness(vector<Real>{0.1, 0.5, 1, 1.5, 2, 2.5, 2});
108
109 simMarketData->setFxCcyPairs({"EURUSD", "EURGBP", "EURCHF", "EURJPY"});
110
111 simMarketData->setSimulateCapFloorVols(true);
112 simMarketData->capFloorVolDecayMode() = "ForwardVariance";
113 simMarketData->setCapFloorVolKeys({"EUR", "USD"});
114 simMarketData->setCapFloorVolExpiries(
115 "", {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years, 7 * Years, 10 * Years, 15 * Years, 20 * Years});
116 simMarketData->setCapFloorVolStrikes("", {0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06});
117
118 return simMarketData;
119}
120
121QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> setupSimMarketData7() {
122 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData(
124
125 simMarketData->baseCcy() = "EUR";
126 simMarketData->setDiscountCurveNames({"EUR", "GBP", "USD", "CHF", "JPY", "SEK", "CAD"});
127 simMarketData->setYieldCurveTenors("", {2 * Weeks, 1 * Months, 3 * Months, 6 * Months, 1 * Years, 2 * Years,
128 3 * Years, 5 * Years, 10 * Years, 15 * Years, 20 * Years, 30 * Years});
129 simMarketData->setIndices({"EUR-EONIA", "EUR-EURIBOR-6M", "EUR-EURIBOR-3M", "USD-FedFunds", "USD-LIBOR-3M",
130 "USD-LIBOR-6M", "USD-LIBOR-1M", "GBP-SONIA", "GBP-LIBOR-6M", "GBP-LIBOR-3M", "CHF-TOIS",
131 "CHF-LIBOR-3M", "CHF-LIBOR-6M", "JPY-TONAR", "JPY-LIBOR-3M", "JPY-LIBOR-6M",
132 "CAD-CDOR-3M", "CAD-CORRA", "SEK-STIBOR-3M"});
133 simMarketData->interpolation() = "LogLinear";
134
135
136 simMarketData->swapIndices()["USD-CMS-1Y"] = "USD-LIBOR-3M";
137 simMarketData->swapIndices()["USD-CMS-30Y"] = "USD-LIBOR-6M";
138 simMarketData->swapIndices()["JPY-CMS-1Y"] = "JPY-LIBOR-6M";
139 simMarketData->swapIndices()["JPY-CMS-30Y"] = "JPY-LIBOR-6M";
140 simMarketData->setFxCcyPairs({"EURUSD", "EURGBP", "EURCHF", "EURJPY", "EURSEK", "EURCAD"});
141
142 return simMarketData;
143}
144
145QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> setupSimMarketData5Big() {
146 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData(
148
149 simMarketData->baseCcy() = "EUR";
150 simMarketData->setDiscountCurveNames({"EUR", "GBP", "USD", "CHF", "JPY"});
151 simMarketData->setYieldCurveTenors(
152 "", {1 * Weeks, 2 * Weeks, 1 * Months, 2 * Months, 3 * Months, 4 * Months, 5 * Months, 6 * Months,
153 9 * Months, 10 * Months, 11 * Months, 1 * Years, 13 * Months, 14 * Months, 15 * Months, 16 * Months,
154 17 * Months, 18 * Months, 19 * Months, 20 * Months, 21 * Months, 22 * Months, 23 * Months, 2 * Years,
155 25 * Months, 26 * Months, 27 * Months, 28 * Months, 29 * Months, 30 * Months, 31 * Months, 32 * Months,
156 3 * Years, 40 * Months, 41 * Months, 42 * Months, 43 * Months, 44 * Months, 4 * Years, 52 * Months,
157 53 * Months, 54 * Months, 55 * Months, 56 * Months, 5 * Years, 64 * Months, 65 * Months, 66 * Months,
158 67 * Months, 68 * Months, 6 * Years, 76 * Months, 77 * Months, 78 * Months, 79 * Months, 80 * Months,
159 7 * Years, 88 * Months, 89 * Months, 90 * Months, 91 * Months, 92 * Months, 10 * Years, 15 * Years,
160 20 * Years, 25 * Years, 30 * Years, 50 * Years});
161 simMarketData->setIndices(
162 {"EUR-EURIBOR-6M", "USD-LIBOR-3M", "USD-LIBOR-6M", "GBP-LIBOR-6M", "CHF-LIBOR-6M", "JPY-LIBOR-6M"});
163 simMarketData->interpolation() = "LogLinear";
164
165 simMarketData->setSwapVolTerms(
166 "", {3 * Months, 4 * Months, 5 * Months, 6 * Months, 9 * Months, 10 * Months, 11 * Months, 1 * Years,
167 13 * Months, 14 * Months, 15 * Months, 16 * Months, 17 * Months, 18 * Months, 19 * Months, 20 * Months,
168 21 * Months, 22 * Months, 23 * Months, 2 * Years, 25 * Months, 26 * Months, 27 * Months, 28 * Months,
169 29 * Months, 30 * Months, 31 * Months, 32 * Months, 3 * Years, 40 * Months, 41 * Months, 42 * Months,
170 43 * Months, 44 * Months, 4 * Years, 52 * Months, 53 * Months, 54 * Months, 55 * Months, 56 * Months,
171 5 * Years, 64 * Months, 65 * Months, 66 * Months, 67 * Months, 68 * Months, 6 * Years, 76 * Months,
172 77 * Months, 78 * Months, 79 * Months, 80 * Months, 7 * Years, 88 * Months, 89 * Months, 90 * Months,
173 91 * Months, 92 * Months, 10 * Years, 15 * Years, 20 * Years, 25 * Years, 30 * Years, 50 * Years});
174 simMarketData->setSwapVolExpiries(
175 "", {1 * Weeks, 2 * Weeks, 1 * Months, 2 * Months, 3 * Months, 4 * Months, 5 * Months, 6 * Months,
176 9 * Months, 10 * Months, 11 * Months, 1 * Years, 13 * Months, 14 * Months, 15 * Months, 16 * Months,
177 17 * Months, 18 * Months, 19 * Months, 20 * Months, 21 * Months, 22 * Months, 23 * Months, 2 * Years,
178 25 * Months, 26 * Months, 27 * Months, 28 * Months, 29 * Months, 30 * Months, 31 * Months, 32 * Months,
179 3 * Years, 40 * Months, 41 * Months, 42 * Months, 43 * Months, 44 * Months, 4 * Years, 52 * Months,
180 53 * Months, 54 * Months, 55 * Months, 56 * Months, 5 * Years, 64 * Months, 65 * Months, 66 * Months,
181 67 * Months, 68 * Months, 6 * Years, 76 * Months, 77 * Months, 78 * Months, 79 * Months, 80 * Months,
182 7 * Years, 88 * Months, 89 * Months, 90 * Months, 91 * Months, 92 * Months, 10 * Years, 15 * Years,
183 20 * Years, 25 * Years, 30 * Years, 50 * Years});
184 simMarketData->setSwapVolKeys({"EUR", "GBP", "USD", "CHF", "JPY"});
185 simMarketData->swapVolDecayMode() = "ForwardVariance";
186 simMarketData->setSimulateSwapVols(true); // false;
187 vector<Period> tmpFxVolExpiries = {
188 1 * Weeks, 2 * Weeks, 1 * Months, 2 * Months, 3 * Months, 4 * Months, 5 * Months, 6 * Months,
189 9 * Months, 10 * Months, 11 * Months, 1 * Years, 13 * Months, 14 * Months, 15 * Months, 16 * Months,
190 17 * Months, 18 * Months, 19 * Months, 20 * Months, 21 * Months, 22 * Months, 23 * Months, 2 * Years,
191 25 * Months, 26 * Months, 27 * Months, 28 * Months, 29 * Months, 30 * Months, 31 * Months, 32 * Months,
192 3 * Years, 40 * Months, 41 * Months, 42 * Months, 43 * Months, 44 * Months, 4 * Years, 52 * Months,
193 53 * Months, 54 * Months, 55 * Months, 56 * Months, 5 * Years, 64 * Months, 65 * Months, 66 * Months,
194 67 * Months, 68 * Months, 6 * Years, 76 * Months, 77 * Months, 78 * Months, 79 * Months, 80 * Months,
195 7 * Years, 88 * Months, 89 * Months, 90 * Months, 91 * Months, 92 * Months, 10 * Years, 15 * Years,
196 20 * Years, 25 * Years, 30 * Years, 50 * Years};
197 simMarketData->setFxVolExpiries("", tmpFxVolExpiries);
198 simMarketData->setFxVolDecayMode(string("ConstantVariance"));
199 simMarketData->setSimulateFXVols(true); // false;
200 simMarketData->setFxVolCcyPairs({"EURUSD", "EURGBP", "EURCHF", "EURJPY"});
201 simMarketData->setFxVolIsSurface(false);
202 simMarketData->setFxVolMoneyness(vector<Real>{0});
203
204 simMarketData->setFxCcyPairs({"EURUSD", "EURGBP", "EURCHF", "EURJPY"});
205
206 simMarketData->setSimulateCapFloorVols(true);
207 simMarketData->capFloorVolDecayMode() = "ForwardVariance";
208 simMarketData->setCapFloorVolKeys({"EUR", "USD"});
209 simMarketData->setCapFloorVolExpiries(
210 "", {3 * Months, 4 * Months, 5 * Months, 6 * Months, 9 * Months, 10 * Months, 11 * Months, 1 * Years,
211 13 * Months, 14 * Months, 15 * Months, 16 * Months, 17 * Months, 18 * Months, 19 * Months, 20 * Months,
212 21 * Months, 22 * Months, 23 * Months, 2 * Years, 25 * Months, 26 * Months, 27 * Months, 28 * Months,
213 29 * Months, 30 * Months, 31 * Months, 32 * Months, 3 * Years, 40 * Months, 41 * Months, 42 * Months,
214 43 * Months, 44 * Months, 4 * Years, 52 * Months, 53 * Months, 54 * Months, 55 * Months, 56 * Months,
215 5 * Years, 64 * Months, 65 * Months, 66 * Months, 67 * Months, 68 * Months, 6 * Years, 76 * Months,
216 77 * Months, 78 * Months, 79 * Months, 80 * Months, 7 * Years, 88 * Months, 89 * Months, 90 * Months,
217 91 * Months, 92 * Months, 10 * Years, 15 * Years, 20 * Years, 25 * Years, 30 * Years, 50 * Years});
218 simMarketData->setCapFloorVolStrikes("", {0.00, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06});
219
220 return simMarketData;
221}
222
223QuantLib::ext::shared_ptr<SensitivityScenarioData> setupSensitivityScenarioData5Big() {
224 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = QuantLib::ext::make_shared<SensitivityScenarioData>();
225
226 QuantLib::ext::shared_ptr<SensitivityScenarioData::CurveShiftData> cvsData =
227 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftData>();
228 cvsData->shiftTenors = {
229 1 * Weeks, 2 * Weeks, 1 * Months, 2 * Months, 3 * Months, 4 * Months, 5 * Months, 6 * Months,
230 9 * Months, 10 * Months, 11 * Months, 1 * Years, 13 * Months, 14 * Months, 15 * Months, 16 * Months,
231 17 * Months, 18 * Months, 19 * Months, 20 * Months, 21 * Months, 22 * Months, 23 * Months, 2 * Years,
232 25 * Months, 26 * Months, 27 * Months, 28 * Months, 29 * Months, 30 * Months, 31 * Months, 32 * Months,
233 3 * Years, 40 * Months, 41 * Months, 42 * Months, 43 * Months, 44 * Months, 4 * Years, 52 * Months,
234 53 * Months, 54 * Months, 55 * Months, 56 * Months, 5 * Years, 64 * Months, 65 * Months, 66 * Months,
235 67 * Months, 68 * Months, 6 * Years, 76 * Months, 77 * Months, 78 * Months, 79 * Months, 80 * Months,
236 7 * Years, 88 * Months, 89 * Months, 90 * Months, 91 * Months, 92 * Months, 10 * Years, 15 * Years,
237 20 * Years, 25 * Years, 30 * Years, 50 * Years}; // multiple tenors: triangular shifts
238 cvsData->shiftType = ShiftType::Absolute;
239 cvsData->shiftSize = 0.0001;
240
242 fxsData.shiftType = ShiftType::Relative;
243 fxsData.shiftSize = 0.01;
244
246 fxvsData.shiftType = ShiftType::Relative;
247 fxvsData.shiftSize = 1.0;
248 fxvsData.shiftExpiries = {1 * Weeks, 2 * Weeks, 1 * Months, 2 * Months, 3 * Months, 4 * Months, 5 * Months,
249 6 * Months, 9 * Months, 10 * Months, 11 * Months, 1 * Years, 13 * Months, 14 * Months,
250 15 * Months, 16 * Months, 17 * Months, 18 * Months, 19 * Months, 20 * Months, 21 * Months,
251 22 * Months, 23 * Months, 2 * Years, 25 * Months, 26 * Months, 27 * Months, 28 * Months,
252 29 * Months, 30 * Months, 31 * Months, 32 * Months, 3 * Years, 40 * Months, 41 * Months,
253 42 * Months, 43 * Months, 44 * Months, 4 * Years, 52 * Months, 53 * Months, 54 * Months,
254 55 * Months, 56 * Months, 5 * Years, 64 * Months, 65 * Months, 66 * Months, 67 * Months,
255 68 * Months, 6 * Years, 76 * Months, 77 * Months, 78 * Months, 79 * Months, 80 * Months,
256 7 * Years, 88 * Months, 89 * Months, 90 * Months, 91 * Months, 92 * Months, 10 * Years,
257 15 * Years, 20 * Years, 25 * Years, 30 * Years, 50 * Years};
258
260 cfvsData.shiftType = ShiftType::Absolute;
261 cfvsData.shiftSize = 0.0001;
262 cfvsData.shiftExpiries = {
263 3 * Months, 4 * Months, 5 * Months, 6 * Months, 9 * Months, 10 * Months, 11 * Months, 1 * Years,
264 13 * Months, 14 * Months, 15 * Months, 16 * Months, 17 * Months, 18 * Months, 19 * Months, 20 * Months,
265 21 * Months, 22 * Months, 23 * Months, 2 * Years, 25 * Months, 26 * Months, 27 * Months, 28 * Months,
266 29 * Months, 30 * Months, 31 * Months, 32 * Months, 3 * Years, 40 * Months, 41 * Months, 42 * Months,
267 43 * Months, 44 * Months, 4 * Years, 52 * Months, 53 * Months, 54 * Months, 55 * Months, 56 * Months,
268 5 * Years, 64 * Months, 65 * Months, 66 * Months, 67 * Months, 68 * Months, 6 * Years, 76 * Months,
269 77 * Months, 78 * Months, 79 * Months, 80 * Months, 7 * Years, 88 * Months, 89 * Months, 90 * Months,
270 91 * Months, 92 * Months, 10 * Years, 15 * Years, 20 * Years, 25 * Years, 30 * Years, 50 * Years};
271 cfvsData.shiftStrikes = {0.01, 0.02, 0.03, 0.04, 0.05};
272
274 swvsData.shiftType = ShiftType::Relative;
275 swvsData.shiftSize = 0.01;
276 swvsData.shiftExpiries = {1 * Weeks, 2 * Weeks, 1 * Months, 2 * Months, 3 * Months, 4 * Months, 5 * Months,
277 6 * Months, 9 * Months, 10 * Months, 11 * Months, 1 * Years, 13 * Months, 14 * Months,
278 15 * Months, 16 * Months, 17 * Months, 18 * Months, 19 * Months, 20 * Months, 21 * Months,
279 22 * Months, 23 * Months, 2 * Years, 25 * Months, 26 * Months, 27 * Months, 28 * Months,
280 29 * Months, 30 * Months, 31 * Months, 32 * Months, 3 * Years, 40 * Months, 41 * Months,
281 42 * Months, 43 * Months, 44 * Months, 4 * Years, 52 * Months, 53 * Months, 54 * Months,
282 55 * Months, 56 * Months, 5 * Years, 64 * Months, 65 * Months, 66 * Months, 67 * Months,
283 68 * Months, 6 * Years, 76 * Months, 77 * Months, 78 * Months, 79 * Months, 80 * Months,
284 7 * Years, 88 * Months, 89 * Months, 90 * Months, 91 * Months, 92 * Months, 10 * Years,
285 15 * Years, 20 * Years, 25 * Years, 30 * Years, 50 * Years};
286 swvsData.shiftTerms = {
287 3 * Months, 4 * Months, 5 * Months, 6 * Months, 9 * Months, 10 * Months, 11 * Months, 1 * Years,
288 13 * Months, 14 * Months, 15 * Months, 16 * Months, 17 * Months, 18 * Months, 19 * Months, 20 * Months,
289 21 * Months, 22 * Months, 23 * Months, 2 * Years, 25 * Months, 26 * Months, 27 * Months, 28 * Months,
290 29 * Months, 30 * Months, 31 * Months, 32 * Months, 3 * Years, 40 * Months, 41 * Months, 42 * Months,
291 43 * Months, 44 * Months, 4 * Years, 52 * Months, 53 * Months, 54 * Months, 55 * Months, 56 * Months,
292 5 * Years, 64 * Months, 65 * Months, 66 * Months, 67 * Months, 68 * Months, 6 * Years, 76 * Months,
293 77 * Months, 78 * Months, 79 * Months, 80 * Months, 7 * Years, 88 * Months, 89 * Months, 90 * Months,
294 91 * Months, 92 * Months, 10 * Years, 15 * Years, 20 * Years, 25 * Years, 30 * Years, 50 * Years};
295
296 sensiData->discountCurveShiftData()["EUR"] = cvsData;
297
298 sensiData->discountCurveShiftData()["USD"] = cvsData;
299
300 sensiData->discountCurveShiftData()["GBP"] = cvsData;
301
302 sensiData->discountCurveShiftData()["JPY"] = cvsData;
303
304 sensiData->discountCurveShiftData()["CHF"] = cvsData;
305
306 sensiData->indexCurveShiftData()["EUR-EURIBOR-6M"] = cvsData;
307
308 sensiData->indexCurveShiftData()["USD-LIBOR-3M"] = cvsData;
309
310 sensiData->indexCurveShiftData()["USD-LIBOR-6M"] = cvsData;
311
312 sensiData->indexCurveShiftData()["GBP-LIBOR-6M"] = cvsData;
313
314 sensiData->indexCurveShiftData()["JPY-LIBOR-6M"] = cvsData;
315
316 sensiData->indexCurveShiftData()["CHF-LIBOR-6M"] = cvsData;
317
318 sensiData->fxShiftData()["EURUSD"] = fxsData;
319 sensiData->fxShiftData()["EURGBP"] = fxsData;
320 sensiData->fxShiftData()["EURJPY"] = fxsData;
321 sensiData->fxShiftData()["EURCHF"] = fxsData;
322
323 sensiData->fxVolShiftData()["EURUSD"] = fxvsData;
324 sensiData->fxVolShiftData()["EURGBP"] = fxvsData;
325 sensiData->fxVolShiftData()["EURJPY"] = fxvsData;
326 sensiData->fxVolShiftData()["EURCHF"] = fxvsData;
327
328 sensiData->swaptionVolShiftData()["EUR"] = swvsData;
329 sensiData->swaptionVolShiftData()["GBP"] = swvsData;
330 sensiData->swaptionVolShiftData()["USD"] = swvsData;
331 sensiData->swaptionVolShiftData()["JPY"] = swvsData;
332 sensiData->swaptionVolShiftData()["CHF"] = swvsData;
333
334 sensiData->capFloorVolShiftData()["EUR"] =
335 QuantLib::ext::make_shared<SensitivityScenarioData::CapFloorVolShiftData>(cfvsData);
336 sensiData->capFloorVolShiftData()["EUR"]->indexName = "EUR-EURIBOR-6M";
337 sensiData->capFloorVolShiftData()["USD"] =
338 QuantLib::ext::make_shared<SensitivityScenarioData::CapFloorVolShiftData>(cfvsData);
339 sensiData->capFloorVolShiftData()["USD"]->indexName = "USD-LIBOR-3M";
340
341 return sensiData;
342}
343
344QuantLib::ext::shared_ptr<SensitivityScenarioData> setupSensitivityScenarioData5() {
345 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = QuantLib::ext::make_shared<SensitivityScenarioData>();
346
347 QuantLib::ext::shared_ptr<SensitivityScenarioData::CurveShiftData> cvsData =
348 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftData>();
349 cvsData->shiftTenors = {6 * Months, 1 * Years, 2 * Years, 3 * Years, 5 * Years,
350 7 * Years, 10 * Years, 15 * Years, 20 * Years}; // multiple tenors: triangular shifts
351 cvsData->shiftType = ShiftType::Absolute;
352 cvsData->shiftSize = 0.0001;
353
355 fxsData.shiftType = ShiftType::Relative;
356 fxsData.shiftSize = 0.01;
357
359 fxvsData.shiftType = ShiftType::Relative;
360 fxvsData.shiftSize = 1.0;
361 fxvsData.shiftExpiries = {5 * Years};
362
364 cfvsData.shiftType = ShiftType::Absolute;
365 cfvsData.shiftSize = 0.0001;
366 cfvsData.shiftExpiries = {1 * Years, 2 * Years, 3 * Years, 5 * Years, 10 * Years};
367 cfvsData.shiftStrikes = {0.01, 0.02, 0.03, 0.04, 0.05};
368
370 swvsData.shiftType = ShiftType::Relative;
371 swvsData.shiftSize = 0.01;
372 swvsData.shiftExpiries = {6 * Months, 1 * Years, 3 * Years, 5 * Years, 10 * Years};
373 swvsData.shiftTerms = {1 * Years, 3 * Years, 5 * Years, 10 * Years, 20 * Years};
374 sensiData->discountCurveShiftData()["EUR"] = cvsData;
375
376 sensiData->discountCurveShiftData()["USD"] = cvsData;
377
378 sensiData->discountCurveShiftData()["GBP"] = cvsData;
379
380 sensiData->discountCurveShiftData()["JPY"] = cvsData;
381
382 sensiData->discountCurveShiftData()["CHF"] = cvsData;
383
384 sensiData->indexCurveShiftData()["EUR-EURIBOR-6M"] = cvsData;
385
386 sensiData->indexCurveShiftData()["USD-LIBOR-3M"] = cvsData;
387
388 sensiData->indexCurveShiftData()["USD-LIBOR-6M"] = cvsData;
389
390 sensiData->indexCurveShiftData()["GBP-LIBOR-6M"] = cvsData;
391
392 sensiData->indexCurveShiftData()["JPY-LIBOR-6M"] = cvsData;
393
394 sensiData->indexCurveShiftData()["CHF-LIBOR-6M"] = cvsData;
395
396 sensiData->fxShiftData()["EURUSD"] = fxsData;
397 sensiData->fxShiftData()["EURGBP"] = fxsData;
398 sensiData->fxShiftData()["EURJPY"] = fxsData;
399 sensiData->fxShiftData()["EURCHF"] = fxsData;
400
401 sensiData->fxVolShiftData()["EURUSD"] = fxvsData;
402 sensiData->fxVolShiftData()["EURGBP"] = fxvsData;
403 sensiData->fxVolShiftData()["EURJPY"] = fxvsData;
404 sensiData->fxVolShiftData()["EURCHF"] = fxvsData;
405
406 sensiData->swaptionVolShiftData()["EUR"] = swvsData;
407 sensiData->swaptionVolShiftData()["GBP"] = swvsData;
408 sensiData->swaptionVolShiftData()["USD"] = swvsData;
409 sensiData->swaptionVolShiftData()["JPY"] = swvsData;
410 sensiData->swaptionVolShiftData()["CHF"] = swvsData;
411
412 sensiData->capFloorVolShiftData()["EUR"] =
413 QuantLib::ext::make_shared<SensitivityScenarioData::CapFloorVolShiftData>(cfvsData);
414 sensiData->capFloorVolShiftData()["EUR"]->indexName = "EUR-EURIBOR-6M";
415 sensiData->capFloorVolShiftData()["USD"] =
416 QuantLib::ext::make_shared<SensitivityScenarioData::CapFloorVolShiftData>(cfvsData);
417 sensiData->capFloorVolShiftData()["USD"]->indexName = "USD-LIBOR-3M";
418
419 return sensiData;
420}
421
422QuantLib::ext::shared_ptr<SensitivityScenarioData> setupSensitivityScenarioData7() {
423 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = QuantLib::ext::make_shared<SensitivityScenarioData>();
424
425 QuantLib::ext::shared_ptr<SensitivityScenarioData::CurveShiftData> cvsData =
426 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftData>();
427 cvsData->shiftTenors = {
428 2 * Weeks, 1 * Months, 3 * Months, 6 * Months, 1 * Years, 2 * Years,
429 3 * Years, 5 * Years, 10 * Years, 15 * Years, 20 * Years, 30 * Years}; // multiple tenors: triangular shifts
430 cvsData->shiftType = ShiftType::Absolute;
431 cvsData->shiftSize = 0.0001;
432
434 fxsData.shiftType = ShiftType::Relative;
435 fxsData.shiftSize = 0.01;
436
437 sensiData->discountCurveShiftData()["EUR"] = cvsData;
438
439 sensiData->discountCurveShiftData()["USD"] = cvsData;
440
441 sensiData->discountCurveShiftData()["GBP"] = cvsData;
442
443 sensiData->discountCurveShiftData()["JPY"] = cvsData;
444
445 sensiData->discountCurveShiftData()["CHF"] = cvsData;
446
447 sensiData->discountCurveShiftData()["CAD"] = cvsData;
448
449 sensiData->discountCurveShiftData()["SEK"] = cvsData;
450
451 sensiData->indexCurveShiftData()["EUR-EONIA"] = cvsData;
452
453 sensiData->indexCurveShiftData()["EUR-EURIBOR-3M"] = cvsData;
454
455 sensiData->indexCurveShiftData()["EUR-EURIBOR-6M"] = cvsData;
456
457 sensiData->indexCurveShiftData()["GBP-SONIA"] = cvsData;
458
459 sensiData->indexCurveShiftData()["GBP-LIBOR-3M"] = cvsData;
460
461 sensiData->indexCurveShiftData()["USD-FedFunds"] = cvsData;
462
463 sensiData->indexCurveShiftData()["USD-LIBOR-1M"] = cvsData;
464
465 sensiData->indexCurveShiftData()["USD-LIBOR-3M"] = cvsData;
466
467 sensiData->indexCurveShiftData()["USD-LIBOR-6M"] = cvsData;
468
469 sensiData->indexCurveShiftData()["GBP-LIBOR-6M"] = cvsData;
470
471 sensiData->indexCurveShiftData()["JPY-TONAR"] = cvsData;
472
473 sensiData->indexCurveShiftData()["JPY-LIBOR-3M"] = cvsData;
474
475 sensiData->indexCurveShiftData()["JPY-LIBOR-6M"] = cvsData;
476
477 sensiData->indexCurveShiftData()["CHF-TOIS"] = cvsData;
478
479 sensiData->indexCurveShiftData()["CHF-LIBOR-3M"] = cvsData;
480
481 sensiData->indexCurveShiftData()["CHF-LIBOR-6M"] = cvsData;
482
483 sensiData->indexCurveShiftData()["CAD-CDOR-3M"] = cvsData;
484
485 sensiData->indexCurveShiftData()["CAD-CORRA"] = cvsData;
486
487 sensiData->indexCurveShiftData()["SEK-STIBOR-3M"] = cvsData;
488
489 sensiData->fxShiftData()["EURUSD"] = fxsData;
490 sensiData->fxShiftData()["EURGBP"] = fxsData;
491 sensiData->fxShiftData()["EURJPY"] = fxsData;
492 sensiData->fxShiftData()["EURCHF"] = fxsData;
493 sensiData->fxShiftData()["EURCAD"] = fxsData;
494 sensiData->fxShiftData()["EURSEK"] = fxsData;
495
496 return sensiData;
497}
498
499void addCrossGammas(vector<pair<string, string>>& cgFilter) {
500 BOOST_CHECK_EQUAL(cgFilter.size(), 0);
501 cgFilter.push_back(pair<string, string>("DiscountCurve/EUR", "DiscountCurve/EUR"));
502 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/USD"));
503 cgFilter.push_back(pair<string, string>("DiscountCurve/GBP", "DiscountCurve/GBP"));
504 cgFilter.push_back(pair<string, string>("DiscountCurve/CHF", "DiscountCurve/CHF"));
505 cgFilter.push_back(pair<string, string>("DiscountCurve/JPY", "DiscountCurve/JPY"));
506 cgFilter.push_back(pair<string, string>("IndexCurve/EUR", "DiscountCurve/EUR"));
507 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/USD"));
508 cgFilter.push_back(pair<string, string>("IndexCurve/GBP", "DiscountCurve/GBP"));
509 cgFilter.push_back(pair<string, string>("IndexCurve/CHF", "DiscountCurve/CHF"));
510 cgFilter.push_back(pair<string, string>("IndexCurve/JPY", "DiscountCurve/JPY"));
511 cgFilter.push_back(pair<string, string>("IndexCurve/EUR", "IndexCurve/EUR"));
512 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/USD"));
513 cgFilter.push_back(pair<string, string>("IndexCurve/GBP", "IndexCurve/GBP"));
514 cgFilter.push_back(pair<string, string>("IndexCurve/CHF", "IndexCurve/CHF"));
515 cgFilter.push_back(pair<string, string>("IndexCurve/JPY", "IndexCurve/JPY"));
516 cgFilter.push_back(pair<string, string>("SwaptionVolatility/EUR", "SwaptionVolatility/EUR"));
517 cgFilter.push_back(pair<string, string>("SwaptionVolatility/USD", "SwaptionVolatility/USD"));
518 cgFilter.push_back(pair<string, string>("SwaptionVolatility/GBP", "SwaptionVolatility/GBP"));
519}
520
521void addCrossGammas7(vector<pair<string, string>>& cgFilter) {
522 BOOST_CHECK_EQUAL(cgFilter.size(), 0);
523 cgFilter.push_back(pair<string, string>("DiscountCurve/EUR", "DiscountCurve/EUR"));
524 cgFilter.push_back(pair<string, string>("DiscountCurve/JPY", "DiscountCurve/JPY"));
525 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/USD"));
526 cgFilter.push_back(pair<string, string>("DiscountCurve/GBP", "DiscountCurve/GBP"));
527 cgFilter.push_back(pair<string, string>("DiscountCurve/CHF", "DiscountCurve/CHF"));
528 cgFilter.push_back(pair<string, string>("DiscountCurve/SEK", "DiscountCurve/SEK"));
529 cgFilter.push_back(pair<string, string>("DiscountCurve/CAD", "DiscountCurve/CAD"));
530
531 cgFilter.push_back(pair<string, string>("IndexCurve/EUR", "IndexCurve/EUR"));
532 cgFilter.push_back(pair<string, string>("IndexCurve/JPY", "IndexCurve/JPY"));
533 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/USD"));
534 cgFilter.push_back(pair<string, string>("IndexCurve/GBP", "IndexCurve/GBP"));
535 cgFilter.push_back(pair<string, string>("IndexCurve/CHF", "IndexCurve/CHF"));
536 cgFilter.push_back(pair<string, string>("IndexCurve/SEK", "IndexCurve/SEK"));
537 cgFilter.push_back(pair<string, string>("IndexCurve/CAD", "IndexCurve/CAD"));
538
539 cgFilter.push_back(pair<string, string>("DiscountCurve/EUR", "IndexCurve/EUR"));
540 cgFilter.push_back(pair<string, string>("DiscountCurve/JPY", "IndexCurve/JPY"));
541 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/USD"));
542 cgFilter.push_back(pair<string, string>("DiscountCurve/GBP", "IndexCurve/GBP"));
543 cgFilter.push_back(pair<string, string>("DiscountCurve/CHF", "IndexCurve/CHF"));
544 cgFilter.push_back(pair<string, string>("DiscountCurve/SEK", "IndexCurve/SEK"));
545 cgFilter.push_back(pair<string, string>("DiscountCurve/CAD", "IndexCurve/CAD"));
546
547 cgFilter.push_back(pair<string, string>("DiscountCurve/EUR", "SwaptionVolatility/EUR"));
548 cgFilter.push_back(pair<string, string>("DiscountCurve/JPY", "SwaptionVolatility/JPY"));
549 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "SwaptionVolatility/USD"));
550 cgFilter.push_back(pair<string, string>("DiscountCurve/GBP", "SwaptionVolatility/GBP"));
551 cgFilter.push_back(pair<string, string>("DiscountCurve/CHF", "SwaptionVolatility/CHF"));
552 cgFilter.push_back(pair<string, string>("DiscountCurve/SEK", "SwaptionVolatility/SEK"));
553 cgFilter.push_back(pair<string, string>("DiscountCurve/CAD", "SwaptionVolatility/CAD"));
554
555 cgFilter.push_back(pair<string, string>("IndexCurve/EUR", "SwaptionVolatility/EUR"));
556 cgFilter.push_back(pair<string, string>("IndexCurve/JPY", "SwaptionVolatility/JPY"));
557 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "SwaptionVolatility/USD"));
558 cgFilter.push_back(pair<string, string>("IndexCurve/GBP", "SwaptionVolatility/GBP"));
559 cgFilter.push_back(pair<string, string>("IndexCurve/CHF", "SwaptionVolatility/CHF"));
560 cgFilter.push_back(pair<string, string>("IndexCurve/SEK", "SwaptionVolatility/SEK"));
561 cgFilter.push_back(pair<string, string>("IndexCurve/CAD", "SwaptionVolatility/CAD"));
562
563 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "DiscountCurve/EUR"));
564 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "IndexCurve/EUR"));
565 cgFilter.push_back(pair<string, string>("FXSpot/JPYUSD", "DiscountCurve/JPY"));
566 cgFilter.push_back(pair<string, string>("FXSpot/JPYUSD", "IndexCurve/JPY"));
567 cgFilter.push_back(pair<string, string>("FXSpot/GBPUSD", "DiscountCurve/GBP"));
568 cgFilter.push_back(pair<string, string>("FXSpot/GBPUSD", "IndexCurve/GBP"));
569 cgFilter.push_back(pair<string, string>("FXSpot/CHFUSD", "DiscountCurve/CHF"));
570 cgFilter.push_back(pair<string, string>("FXSpot/CHFUSD", "IndexCurve/CHF"));
571 cgFilter.push_back(pair<string, string>("FXSpot/SEKUSD", "DiscountCurve/SEK"));
572 cgFilter.push_back(pair<string, string>("FXSpot/SEKUSD", "IndexCurve/SEK"));
573 cgFilter.push_back(pair<string, string>("FXSpot/CADUSD", "DiscountCurve/CAD"));
574 cgFilter.push_back(pair<string, string>("FXSpot/CADUSD", "IndexCurve/CAD"));
575
576 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "SwaptionVolatility/EUR"));
577 cgFilter.push_back(pair<string, string>("FXSpot/JPYUSD", "SwaptionVolatility/JPY"));
578 cgFilter.push_back(pair<string, string>("FXSpot/GBPUSD", "SwaptionVolatility/GBP"));
579 cgFilter.push_back(pair<string, string>("FXSpot/CHFUSD", "SwaptionVolatility/CHF"));
580 cgFilter.push_back(pair<string, string>("FXSpot/SEKUSD", "SwaptionVolatility/SEK"));
581 cgFilter.push_back(pair<string, string>("FXSpot/CADUSD", "SwaptionVolatility/CAD"));
582
583 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "DiscountCurve/USD"));
584 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "IndexCurve/USD"));
585 cgFilter.push_back(pair<string, string>("FXSpot/JPYUSD", "DiscountCurve/USD"));
586 cgFilter.push_back(pair<string, string>("FXSpot/JPYUSD", "IndexCurve/USD"));
587 cgFilter.push_back(pair<string, string>("FXSpot/GBPUSD", "DiscountCurve/USD"));
588 cgFilter.push_back(pair<string, string>("FXSpot/GBPUSD", "IndexCurve/USD"));
589 cgFilter.push_back(pair<string, string>("FXSpot/CHFUSD", "DiscountCurve/USD"));
590 cgFilter.push_back(pair<string, string>("FXSpot/CHFUSD", "IndexCurve/USD"));
591 cgFilter.push_back(pair<string, string>("FXSpot/SEKUSD", "DiscountCurve/USD"));
592 cgFilter.push_back(pair<string, string>("FXSpot/SEKUSD", "IndexCurve/USD"));
593 cgFilter.push_back(pair<string, string>("FXSpot/CADUSD", "DiscountCurve/USD"));
594 cgFilter.push_back(pair<string, string>("FXSpot/CADUSD", "IndexCurve/USD"));
595
596 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/EUR"));
597 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/JPY"));
598 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/GBP"));
599 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/CHF"));
600 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/SEK"));
601 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/CAD"));
602
603 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/EUR"));
604 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/JPY"));
605 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/GBP"));
606 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/CHF"));
607 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/SEK"));
608 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "DiscountCurve/CAD"));
609 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/EUR"));
610
611 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/JPY"));
612 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/GBP"));
613 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/CHF"));
614 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/SEK"));
615 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "IndexCurve/CAD"));
616
617 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/EUR"));
618 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/JPY"));
619 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/GBP"));
620 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/CHF"));
621 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/SEK"));
622 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/CAD"));
623}
624
625QuantLib::ext::shared_ptr<Portfolio> buildPortfolio(Size portfolioSize, bool swapsOnly = false,
626 QuantLib::ext::shared_ptr<EngineFactory> factory = {}) {
627
628 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
629
630 vector<string> ccys = {"EUR", "USD", "GBP", "JPY", "CHF"};
631
632 map<string, vector<string>> indices = {{"EUR", {"EUR-EURIBOR-6M"}},
633 {"USD", {"USD-LIBOR-3M"}},
634 {"GBP", {"GBP-LIBOR-6M"}},
635 {"CHF", {"CHF-LIBOR-6M"}},
636 {"JPY", {"JPY-LIBOR-6M"}}};
637
638 vector<string> fixedTenors = {"6M", "1Y"};
639
640 Size minStart = 0;
641 Size maxStart = 5;
642 Size minTerm = 2;
643 Size maxTerm = 30;
644
645 Size minFixedBps = 10;
646 Size maxFixedBps = 400;
647
648 Size seed = 5; // keep this constant to ensure portfolio doesn't change
649 MersenneTwisterUniformRng rng(seed);
650
651 Calendar cal = TARGET();
652 string fixDC = "30/360";
653 string floatDC = "ACT/365";
654
655 Real notional = 1000000;
656 Real spread = 0.0;
657
658 for (Size i = 0; i < portfolioSize; i++) {
659
660 // ccy + index
661 string ccy = portfolioSize == 1 ? "EUR" : randString(rng, ccys);
662 string index = portfolioSize == 1 ? "EUR-EURIBOR-6M" : randString(rng, indices[ccy]);
663 string floatFreq = portfolioSize == 1 ? "6M" : index.substr(index.find('-', 4) + 1);
664
665 // fixed details
666 Real fixedRate = portfolioSize == 1 ? 0.02 : randInt(rng, minFixedBps, maxFixedBps) / 100.0;
667 string fixFreq = portfolioSize == 1 ? "1Y" : randString(rng, fixedTenors);
668
669 bool isPayer = randBoolean(rng);
670
671 // id
672 std::ostringstream oss;
673 oss.clear();
674 oss.str("");
675 oss << "Trade_" << i + 1;
676 string id = oss.str();
677
678 if (i % 2 == 0 && !swapsOnly) {
679 int start = randInt(rng, minTerm, maxTerm);
680 Size term = portfolioSize == 1 ? 20 : randInt(rng, minTerm, maxTerm);
681 string longShort = randBoolean(rng) ? "Long" : "Short";
682 portfolio->add(testsuite::buildEuropeanSwaption(id, longShort, ccy, isPayer, notional,
683 start, term, fixedRate, spread, fixFreq,
684 fixDC, floatFreq, floatDC, index));
685 } else {
686 int start = randInt(rng, minStart, maxStart);
687 Size end = randInt(rng, minTerm, maxTerm);
688 portfolio->add(testsuite::buildSwap(id, ccy, isPayer, notional, start, end, fixedRate,
689 spread, fixFreq, fixDC, floatFreq, floatDC, index));
690 }
691 }
692 if (factory)
693 portfolio->build(factory);
694
695 BOOST_CHECK_MESSAGE(portfolio->size() == portfolioSize,
696 "Failed to build portfolio (got " << portfolio->size() << " expected " << portfolioSize << ")");
697
698 return portfolio;
699}
700
701void test_performance(bool bigPortfolio, bool bigScenario, bool lotsOfSensis, bool crossGammas,
703 Size portfolioSize = bigPortfolio ? 100 : 1;
704 string om_str = (om == ObservationMode::Mode::None) ? "None"
705 : (om == ObservationMode::Mode::Disable) ? "Disable"
706 : (om == ObservationMode::Mode::Defer) ? "Defer"
707 : (om == ObservationMode::Mode::Unregister) ? "Unregister"
708 : "???";
709 string bigPfolioStr = bigPortfolio ? "big" : "small";
710 string bigScenarioStr = bigScenario ? "big" : "small";
711 string lotsOfSensisStr = lotsOfSensis ? "lots" : "few";
712 string crossGammasStr = crossGammas ? "included" : "excluded";
713
714 BOOST_TEST_MESSAGE("Testing Sensitivity Performance "
715 << "(portfolio=" << bigPfolioStr << ")"
716 << "(scenarioSize=" << bigScenarioStr << ")"
717 << "(numSensis=" << lotsOfSensisStr << ")"
718 << "(crossGammas=" << crossGammasStr << ")"
719 << "(observation=" << om_str << ")...");
720
721 SavedSettings backup;
722 ObservationMode::instance().setMode(om);
723
724 Date today = Date(14, April, 2016);
725 Settings::instance().evaluationDate() = today;
726
727 // Init market
728 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<testsuite::TestMarket>(today);
729
730 // build scenario sim market parameters
731 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData = setupSimMarketData5();
732 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = setupSensitivityScenarioData5();
733 if (bigScenario) {
734 simMarketData = setupSimMarketData5Big();
735 }
736 if (lotsOfSensis) {
737 sensiData = setupSensitivityScenarioData5Big();
738 }
739 if (crossGammas) {
740 addCrossGammas(sensiData->crossGammaFilter());
741 }
742
743 // build scenario sim market
744
745 // build porfolio
746 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
747 data->model("Swap") = "DiscountedCashflows";
748 data->engine("Swap") = "DiscountingSwapEngine";
749 data->model("EuropeanSwaption") = "BlackBachelier";
750 data->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
751
752 QuantLib::ext::shared_ptr<Portfolio> portfolio = buildPortfolio(portfolioSize);
753
754 boost::timer::cpu_timer timer;
755 QuantLib::ext::shared_ptr<SensitivityAnalysis> sa = QuantLib::ext::make_shared<SensitivityAnalysis>(
756 portfolio, initMarket, Market::defaultConfiguration, data, simMarketData, sensiData, false);
757 sa->generateSensitivities();
758 timer.stop();
759 Real elapsed = timer.elapsed().wall * 1e-9;
760 Size numScenarios = sa->scenarioGenerator()->samples();
761 Size scenarioSize = sa->scenarioGenerator()->scenarios().front()->keys().size();
762 BOOST_TEST_MESSAGE("number of scenarios=" << numScenarios);
763 BOOST_TEST_MESSAGE("Size of scenario = " << scenarioSize << " keys");
764 BOOST_TEST_MESSAGE("time = " << elapsed << " seconds");
765 Real avTime = (elapsed / ((Real)(numScenarios * portfolioSize)));
766 BOOST_TEST_MESSAGE("Average pricing time = " << avTime << " seconds");
767 BOOST_TEST_MESSAGE("Memory usage - " << os::getMemoryUsage());
768}
769
770void BT_Benchmark(bool crossGammas, ObservationMode::Mode om) {
771 Size portfolioSize = 100;
772 string om_str = (om == ObservationMode::Mode::None) ? "None"
773 : (om == ObservationMode::Mode::Disable) ? "Disable"
774 : (om == ObservationMode::Mode::Defer) ? "Defer"
775 : (om == ObservationMode::Mode::Unregister) ? "Unregister"
776 : "???";
777
778 SavedSettings backup;
779 ObservationMode::instance().setMode(om);
780
781 Date today = Date(13, April, 2016);
782 Settings::instance().evaluationDate() = today;
783
784 // Init market
785 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<testsuite::TestMarket>(today, true);
786
787 // build scenario sim market parameters
788 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData = setupSimMarketData7();
789 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = setupSensitivityScenarioData7();
790 if (crossGammas) {
791 addCrossGammas7(sensiData->crossGammaFilter());
792 }
793
794 // build porfolio
795 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
796 data->model("Swap") = "DiscountedCashflows";
797 data->engine("Swap") = "DiscountingSwapEngine";
798 data->model("EuropeanSwaption") = "BlackBachelier";
799 data->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
800
801 QuantLib::ext::shared_ptr<Portfolio> portfolio = buildPortfolio(portfolioSize, true);
802
803 boost::timer::cpu_timer timer;
804 QuantLib::ext::shared_ptr<SensitivityAnalysis> sa = QuantLib::ext::make_shared<SensitivityAnalysis>(
805 portfolio, initMarket, Market::defaultConfiguration, data, simMarketData, sensiData, false);
806 sa->generateSensitivities();
807
808 // TODO: do we really want to write a report in the unit tests?
809 // Create a stream from the sensitivity cube
810 CSVFileReport cgReport("crossgammReport");
811 auto baseCurrency = sa->simMarketData()->baseCcy();
812 auto ss = QuantLib::ext::make_shared<SensitivityCubeStream>(sa->sensiCube(), baseCurrency);
813 ReportWriter().writeSensitivityReport(cgReport, ss, 0.000001);
814 timer.stop();
815
816 Real elapsed = timer.elapsed().wall * 1e-9;
817 Size numScenarios = sa->scenarioGenerator()->samples();
818 Size scenarioSize = sa->scenarioGenerator()->scenarios().front()->keys().size();
819 BOOST_TEST_MESSAGE("number of scenarios=" << numScenarios);
820 BOOST_TEST_MESSAGE("Size of scenario = " << scenarioSize << " keys");
821 BOOST_TEST_MESSAGE("time = " << elapsed << " seconds");
822 Real avTime = (elapsed / ((Real)(numScenarios * portfolioSize)));
823 BOOST_TEST_MESSAGE("Average pricing time = " << avTime << " seconds");
824 BOOST_TEST_MESSAGE("Memory usage - " << os::getMemoryUsage());
825}
826} // namespace
827
828namespace testsuite {
829
831 boost::timer::cpu_timer timer;
832 ObservationMode::Mode om = ObservationMode::Mode::None;
833 test_performance(false, false, false, false, om);
834 timer.stop();
835 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
836}
837
839 boost::timer::cpu_timer timer;
840 ObservationMode::Mode om = ObservationMode::Mode::Disable;
841 test_performance(false, false, false, false, om);
842 timer.stop();
843 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
844}
845
847 boost::timer::cpu_timer timer;
848 ObservationMode::Mode om = ObservationMode::Mode::Defer;
849 test_performance(false, false, false, false, om);
850 timer.stop();
851 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
852}
853
855 boost::timer::cpu_timer timer;
856 ObservationMode::Mode om = ObservationMode::Mode::Unregister;
857 test_performance(false, false, false, false, om);
858 timer.stop();
859 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
860}
861
863 boost::timer::cpu_timer timer;
864 ObservationMode::Mode om = ObservationMode::Mode::None;
865 test_performance(false, false, false, true, om);
866 timer.stop();
867 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
868}
869
871 boost::timer::cpu_timer timer;
872 ObservationMode::Mode om = ObservationMode::Mode::None;
873 test_performance(false, true, false, false, om);
874 timer.stop();
875 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
876}
877
879 boost::timer::cpu_timer timer;
880 ObservationMode::Mode om = ObservationMode::Mode::None;
881 test_performance(true, false, false, false, om);
882 timer.stop();
883 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
884}
885
887 boost::timer::cpu_timer timer;
888 ObservationMode::Mode om = ObservationMode::Mode::None;
889 test_performance(true, true, false, false, om);
890 timer.stop();
891 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
892}
893
895 boost::timer::cpu_timer timer;
896 ObservationMode::Mode om = ObservationMode::Mode::None;
897 test_performance(true, false, false, true, om);
898 timer.stop();
899 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
900}
901
903 boost::timer::cpu_timer timer;
904 ObservationMode::Mode om = ObservationMode::Mode::None;
905 test_performance(false, true, false, true, om);
906 timer.stop();
907 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
908}
909
911 boost::timer::cpu_timer timer;
912 ObservationMode::Mode om = ObservationMode::Mode::None;
913 test_performance(true, true, false, true, om);
914 timer.stop();
915 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
916}
917
919 boost::timer::cpu_timer timer;
920 ObservationMode::Mode om = ObservationMode::Mode::None;
921 BT_Benchmark(true, om);
922 timer.stop();
923 BOOST_TEST_MESSAGE("total time = " << timer.format(boost::timer::default_places, "%w") << " seconds");
924}
925
926BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
927BOOST_AUTO_TEST_SUITE(SensitivityPerformanceTest)
928
929BOOST_AUTO_TEST_CASE(SensiPerformanceNoneObs) {
930 BOOST_TEST_MESSAGE("Testing Sensitivity Performance NoneObs");
932}
933
934BOOST_AUTO_TEST_CASE(SensiPerformanceDisableObs) {
935 BOOST_TEST_MESSAGE("Testing Sensitivity Performance DisableObs");
937}
938
939BOOST_AUTO_TEST_CASE(SensiPerformanceDeferObs) {
940 BOOST_TEST_MESSAGE("Testing Sensitivity Performance DeferObs");
942}
943
944BOOST_AUTO_TEST_CASE(SensiPerformanceUnregisterObs) {
945 BOOST_TEST_MESSAGE("Testing Sensitivity Performance UnregisterObs");
947}
948
949BOOST_AUTO_TEST_CASE(SensiPerformanceCrossGammaNoneObs) {
950 BOOST_TEST_MESSAGE("Testing Sensitivity Performance CrossGammaNoneObs");
952}
953
954BOOST_AUTO_TEST_CASE(SensiPerformanceBigScenarioNoneObs) {
955 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BigScenarioNoneObs");
957}
958
959BOOST_AUTO_TEST_SUITE_END()
960BOOST_AUTO_TEST_SUITE_END()
961
962BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
963BOOST_AUTO_TEST_SUITE(SensitivityPerformanceBigPortfolioTest)
964
965BOOST_AUTO_TEST_CASE(SensiPerformanceBigPortfolioObs) {
966 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BigPortfolioNoneObs");
968}
969
970BOOST_AUTO_TEST_CASE(SensiPerformanceBigPortfolioBigScenarioNoneObs) {
971 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BigPortfolioBigScenarioNoneObs");
973}
974
975BOOST_AUTO_TEST_CASE(SensiPerformanceBigPortfolioCrossGammaNoneObs) {
976 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BigPortfolioCrossGammaNoneObs");
978}
979
980BOOST_AUTO_TEST_SUITE_END()
981BOOST_AUTO_TEST_SUITE_END()
982
983BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
984BOOST_AUTO_TEST_SUITE(SensitivityPerformanceBigScenarioTest)
985
986BOOST_AUTO_TEST_CASE(SensiPerformanceBigScenarioCrossGammaNoneObs) {
987 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BigScenarioCrossGammaNoneObs");
989}
990
991BOOST_AUTO_TEST_SUITE_END()
992BOOST_AUTO_TEST_SUITE_END()
993
994BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
995BOOST_AUTO_TEST_SUITE(SensitivityPerformanceBigPortfolioBigScenarioTest)
996
997BOOST_AUTO_TEST_CASE(SensiPerformanceBigPortfolioBigScenarioCrossGammaNoneObs) {
998 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BigPortfolioBigScenarioCrossGammaNoneObs");
1000}
1001
1002BOOST_AUTO_TEST_SUITE_END()
1003BOOST_AUTO_TEST_SUITE_END()
1004
1005BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
1006BOOST_AUTO_TEST_SUITE(SensitivityPerformanceBTSetupTest)
1007
1008BOOST_AUTO_TEST_CASE(SensiPerformanceBTSetupNoneObs) {
1009 BOOST_TEST_MESSAGE("Testing Sensitivity Performance BTSetupNoneObs");
1011}
1012
1013BOOST_AUTO_TEST_SUITE_END()
1014BOOST_AUTO_TEST_SUITE_END()
1015
1016} // namespace testsuite
Write ORE outputs to reports.
virtual void writeSensitivityReport(ore::data::Report &report, const QuantLib::ext::shared_ptr< SensitivityStream > &ss, QuantLib::Real outputThreshold=0.0, QuantLib::Size outputPrecision=2)
static const string defaultConfiguration
OREAnalytics Top level fixture.
static void testSensiPerformanceDisableObs()
Test performance of sensitivities run ("Disable" observation mode)
static void testSensiPerformanceCrossGammaNoneObs()
Test performance of sensitivities run (including cross-gammas) ("None" observation mode)
static void testSensiPerformanceUnregisterObs()
Test performance of sensitivities run ("Unregister" observation mode)
static void testSensiPerformanceDeferObs()
Test performance of sensitivities run ("Defer" observation mode)
static void testSensiPerformanceNoneObs()
Test performance of sensitivities run ("None" observation mode)
static void testSensiPerformanceBigPortfolioNoneObs()
Test performance of sensitivities run for a large portfolio ("None" observation mode)
static void testSensiPerformanceBigScenarioNoneObs()
Test performance of sensitivities run with lots of buckets ("None" observation mode)
static void testSensiPerformanceBigPortfolioBigScenarioCrossGammaNoneObs()
Test performance of sensitivities run (including cross-gammas) for a large portfolio,...
static void testSensiPerformanceBigPortfolioCrossGammaNoneObs()
Test performance of sensitivities run (including cross-gammas) for a large portfolio ("None" observat...
static void testSensiPerformanceBigPortfolioBigScenarioNoneObs()
Test performance of sensitivities run for a large portfolio, with lots of buckets ("None" observation...
static void testSensiPerformanceBigScenarioCrossGammaNoneObs()
Test performance of sensitivities run (including cross-gammas) for a single-trade portfolio,...
Scenario generation using cross asset model paths.
unsigned long randInt(MersenneTwisterUniformRng &rng, Size min, Size max)
Definition: cube.cpp:255
bool randBoolean(MersenneTwisterUniformRng &rng)
Definition: cube.cpp:262
const string & randString(MersenneTwisterUniformRng &rng, const vector< string > &strs)
Definition: cube.cpp:259
QuantLib::ext::shared_ptr< Portfolio > buildPortfolio(Size portfolioSize, QuantLib::ext::shared_ptr< EngineFactory > &factory)
Definition: cube.cpp:264
Class that wraps a sensitivity stream and filters out negligible records.
string getMemoryUsage()
A cube implementation that stores the cube in memory.
data
RandomVariable max(RandomVariable x, const RandomVariable &y)
RandomVariable min(RandomVariable x, const RandomVariable &y)
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 > 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)
The base NPV cube class.
Singleton class to hold global Observation Mode.
Fixture that can be used at top level of OREAnalytics test suites.
Perform parametric var calculation for a given portfolio.
A Class to write ORE outputs to reports.
risk class and type filter
A Market class that can be updated by Scenarios.
A class to hold Scenario parameters for scenarioSimMarket.
Class for aggregating SensitivityRecords.
Perform sensitivity analysis for a given portfolio.
Class for streaming SensitivityRecords from a SensitivityCube.
Class for streaming SensitivityRecords from file.
Class for streaming SensitivityRecords from in-memory container.
Extended sensitivity preformance test.
Struct for holding a sensitivity record.
Base class for sensitivity record streamer.
factory classes for simple scenarios
perform a stress testing analysis for a given portfolio.
void test_performance(Size portfolioSize, ObservationMode::Mode om, double nonZeroPVRatio, vector< Real > &epe_archived, vector< Real > &ene_archived)
QuantLib::ext::shared_ptr< SensitivityScenarioData > setupSensitivityScenarioData5(bool parConversion)
QuantLib::ext::shared_ptr< analytics::ScenarioSimMarketParameters > setupSimMarketData5()
The counterparty cube calculator interface.
The cube valuation core.