Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
sensitivityanalysis.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <boost/test/unit_test.hpp>
20#include <boost/timer/timer.hpp>
59#include <oret/toplevelfixture.hpp>
62
63#include "testmarket.hpp"
64
65using namespace std;
66using namespace QuantLib;
67using namespace QuantExt;
68using namespace boost::unit_test_framework;
69using namespace ore;
70using namespace ore::data;
71using namespace ore::analytics;
72
73using boost::timer::cpu_timer;
74using boost::timer::default_places;
89
90namespace {
91void testPortfolioSensitivity(ObservationMode::Mode om) {
92 SavedSettings backup;
93
94 ObservationMode::Mode backupMode = ObservationMode::instance().mode();
95 ObservationMode::instance().setMode(om);
96
97 Date today = Date(14, April, 2016); // Settings::instance().evaluationDate();
98 Settings::instance().evaluationDate() = today;
99
100 BOOST_TEST_MESSAGE("Today is " << today);
101
102 // Init market
103 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
104
105 // build scenario sim market parameters
106 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
108
109 // sensitivity config
110 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = TestConfigurationObjects::setupSensitivityScenarioData5();
111
112 // build scenario sim market
113 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket =
114 QuantLib::ext::make_shared<analytics::ScenarioSimMarket>(initMarket, simMarketData);
115
116 // build scenario factory
117 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
118 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
119
120 // build scenario generator
121 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
122 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
123 scenarioFactory, false);
124 simMarket->scenarioGenerator() = scenarioGenerator;
125
126 // build portfolio
127 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
128 data->model("Swap") = "DiscountedCashflows";
129 data->engine("Swap") = "DiscountingSwapEngine";
130 data->model("CrossCurrencySwap") = "DiscountedCashflows";
131 data->engine("CrossCurrencySwap") = "DiscountingCrossCurrencySwapEngine";
132 data->model("EuropeanSwaption") = "BlackBachelier";
133 data->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
134 data->model("BermudanSwaption") = "LGM";
135 data->modelParameters("BermudanSwaption")["Calibration"] = "Bootstrap";
136 data->modelParameters("BermudanSwaption")["CalibrationStrategy"] = "CoterminalATM";
137 data->modelParameters("BermudanSwaption")["Reversion"] = "0.03";
138 data->modelParameters("BermudanSwaption")["ReversionType"] = "HullWhite";
139 data->modelParameters("BermudanSwaption")["Volatility"] = "0.01";
140 data->modelParameters("BermudanSwaption")["VolatilityType"] = "Hagan";
141 data->modelParameters("BermudanSwaption")["Tolerance"] = "0.0001";
142 data->engine("BermudanSwaption") = "Grid";
143 data->engineParameters("BermudanSwaption")["sy"] = "3.0";
144 data->engineParameters("BermudanSwaption")["ny"] = "10";
145 data->engineParameters("BermudanSwaption")["sx"] = "3.0";
146 data->engineParameters("BermudanSwaption")["nx"] = "10";
147 data->model("FxForward") = "DiscountedCashflows";
148 data->engine("FxForward") = "DiscountingFxForwardEngine";
149 data->model("FxOption") = "GarmanKohlhagen";
150 data->engine("FxOption") = "AnalyticEuropeanEngine";
151 data->model("CapFloor") = "IborCapModel";
152 data->engine("CapFloor") = "IborCapEngine";
153 data->model("CapFlooredIborLeg") = "BlackOrBachelier";
154 data->engine("CapFlooredIborLeg") = "BlackIborCouponPricer";
155 data->model("Bond") = "DiscountedCashflows";
156 data->engine("Bond") = "DiscountingRiskyBondEngine";
157 data->engineParameters("Bond")["TimestepPeriod"] = "6M";
158 data->model("EquityForward") = "DiscountedCashflows";
159 data->engine("EquityForward") = "DiscountingEquityForwardEngine";
160 data->model("EquityOption") = "BlackScholesMerton";
161 data->engine("EquityOption") = "AnalyticEuropeanEngine";
162 data->model("CommodityForward") = "DiscountedCashflows";
163 data->engine("CommodityForward") = "DiscountingCommodityForwardEngine";
164 data->model("CommodityOption") = "BlackScholes";
165 data->engine("CommodityOption") = "AnalyticEuropeanEngine";
166 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(data, simMarket);
167
168 // QuantLib::ext::shared_ptr<Portfolio> portfolio = buildSwapPortfolio(portfolioSize, factory);
169 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
170 portfolio->add(buildSwap("1_Swap_EUR", "EUR", true, 10000000.0, 0, 10, 0.03, 0.00, "1Y", "30/360", "6M", "A360",
171 "EUR-EURIBOR-6M"));
172 portfolio->add(buildSwap("2_Swap_USD", "USD", true, 10000000.0, 0, 15, 0.02, 0.00, "6M", "30/360", "3M", "A360",
173 "USD-LIBOR-3M"));
174 portfolio->add(buildSwap("3_Swap_GBP", "GBP", true, 10000000.0, 0, 20, 0.04, 0.00, "6M", "30/360", "3M", "A360",
175 "GBP-LIBOR-6M"));
176 portfolio->add(buildSwap("4_Swap_JPY", "JPY", true, 1000000000.0, 0, 5, 0.01, 0.00, "6M", "30/360", "3M", "A360",
177 "JPY-LIBOR-6M"));
178 portfolio->add(buildEuropeanSwaption("5_Swaption_EUR", "Long", "EUR", true, 1000000.0, 10, 10, 0.02, 0.00, "1Y",
179 "30/360", "6M", "A360", "EUR-EURIBOR-6M", "Physical"));
180 portfolio->add(buildEuropeanSwaption("6_Swaption_EUR", "Long", "EUR", true, 1000000.0, 2, 5, 0.02, 0.00, "1Y",
181 "30/360", "6M", "A360", "EUR-EURIBOR-6M", "Physical"));
182 portfolio->add(buildEuropeanSwaption("17_Swaption_EUR", "Long", "EUR", true, 1000000.0, 2, 5, 0.02, 0.00, "1Y",
183 "30/360", "6M", "A360", "EUR-EURIBOR-6M", "Physical", 1200.0, "EUR",
184 "2018-04-14"));
185 portfolio->add(buildBermudanSwaption("13_Swaption_EUR", "Long", "EUR", true, 1000000.0, 5, 2, 10, 0.02, 0.00, "1Y",
186 "30/360", "6M", "A360", "EUR-EURIBOR-6M"));
187 portfolio->add(buildFxOption("7_FxOption_EUR_USD", "Long", "Call", 3, "EUR", 10000000.0, "USD", 11000000.0));
188 portfolio->add(buildFxOption("8_FxOption_EUR_GBP", "Long", "Call", 7, "EUR", 10000000.0, "GBP", 11000000.0));
189 portfolio->add(buildCap("9_Cap_EUR", "EUR", "Long", 0.05, 1000000.0, 0, 10, "6M", "A360", "EUR-EURIBOR-6M"));
190 portfolio->add(buildFloor("10_Floor_USD", "USD", "Long", 0.01, 1000000.0, 0, 10, "3M", "A360", "USD-LIBOR-3M"));
191 portfolio->add(buildZeroBond("11_ZeroBond_EUR", "EUR", 1.0, 10, "0"));
192 portfolio->add(buildZeroBond("12_ZeroBond_USD", "USD", 1.0, 10, "0"));
193 portfolio->add(buildEquityOption("14_EquityOption_SP5", "Long", "Call", 2, "SP5", "USD", 2147.56, 775));
194 portfolio->add(buildCPIInflationSwap("15_CPIInflationSwap_UKRPI", "GBP", true, 100000.0, 0, 10, 0.0, "6M",
195 "ACT/ACT", "GBP-LIBOR-6M", "1Y", "ACT/ACT", "UKRPI", 201.0, "2M", false,
196 0.005));
197 portfolio->add(buildYYInflationSwap("16_YoYInflationSwap_UKRPI", "GBP", true, 100000.0, 0, 10, 0.0, "1Y", "ACT/ACT",
198 "GBP-LIBOR-6M", "1Y", "ACT/ACT", "UKRPI", "2M", 2));
199 portfolio->add(buildCommodityForward("17_CommodityForward_GOLD", "Long", 1, "COMDTY_GOLD_USD", "USD", 1170.0, 100));
200 portfolio->add(buildCommodityForward("18_CommodityForward_OIL", "Short", 4, "COMDTY_WTI_USD", "USD", 46.0, 100000));
201 portfolio->add(
202 buildCommodityOption("19_CommodityOption_GOLD", "Long", "Call", 1, "COMDTY_GOLD_USD", "USD", 1170.0, 100));
203 portfolio->add(
204 buildCommodityOption("20_CommodityOption_OIL", "Short", "Put", 4, "COMDTY_WTI_USD", "USD", 46.0, 100000));
205 portfolio->build(factory);
206
207 BOOST_TEST_MESSAGE("Portfolio size after build: " << portfolio->size());
208
209 // build the scenario valuation engine
210 QuantLib::ext::shared_ptr<DateGrid> dg = QuantLib::ext::make_shared<DateGrid>(
211 "1,0W"); // TODO - extend the DateGrid interface so that it can actually take a vector of dates as input
212 vector<QuantLib::ext::shared_ptr<ValuationCalculator>> calculators;
213 calculators.push_back(QuantLib::ext::make_shared<NPVCalculator>(simMarketData->baseCcy()));
214 ValuationEngine engine(today, dg, simMarket,
215 factory->modelBuilders()); // last argument required for model recalibration
216 // run scenarios and fill the cube
217 cpu_timer t;
218 QuantLib::ext::shared_ptr<NPVCube> cube = QuantLib::ext::make_shared<DoublePrecisionInMemoryCube>(
219 today, portfolio->ids(), vector<Date>(1, today), scenarioGenerator->samples());
220 engine.buildCube(portfolio, cube, calculators);
221 t.stop();
222
223 struct Results {
224 string id;
225 string label;
226 Real npv;
227 Real sensi;
228 };
229
230 // clang-format off
231 std::vector<Results> cachedResults = {
232 {"1_Swap_EUR", "Up:DiscountCurve/EUR/0/6M", -928826, -2.51631},
233 {"1_Swap_EUR", "Up:DiscountCurve/EUR/1/1Y", -928826, 14.6846},
234 {"1_Swap_EUR", "Up:DiscountCurve/EUR/2/2Y", -928826, 19.0081},
235 {"1_Swap_EUR", "Up:DiscountCurve/EUR/3/3Y", -928826, 46.1186},
236 {"1_Swap_EUR", "Up:DiscountCurve/EUR/4/5Y", -928826, 85.1033},
237 {"1_Swap_EUR", "Up:DiscountCurve/EUR/5/7Y", -928826, 149.43},
238 {"1_Swap_EUR", "Up:DiscountCurve/EUR/6/10Y", -928826, 205.064},
239 {"1_Swap_EUR", "Down:DiscountCurve/EUR/0/6M", -928826, 2.51644},
240 {"1_Swap_EUR", "Down:DiscountCurve/EUR/1/1Y", -928826, -14.6863},
241 {"1_Swap_EUR", "Down:DiscountCurve/EUR/2/2Y", -928826, -19.0137},
242 {"1_Swap_EUR", "Down:DiscountCurve/EUR/3/3Y", -928826, -46.1338},
243 {"1_Swap_EUR", "Down:DiscountCurve/EUR/4/5Y", -928826, -85.1406},
244 {"1_Swap_EUR", "Down:DiscountCurve/EUR/5/7Y", -928826, -149.515},
245 {"1_Swap_EUR", "Down:DiscountCurve/EUR/6/10Y", -928826, -205.239},
246 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/0/6M", -928826, -495.013},
247 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/1/1Y", -928826, 14.7304},
248 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", -928826, 38.7816},
249 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", -928826, 94.186},
250 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", -928826, 173.125},
251 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", -928826, 304.648},
252 {"1_Swap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", -928826, 8479.55},
253 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/0/6M", -928826, 495.037},
254 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/1/1Y", -928826, -14.5864},
255 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", -928826, -38.4045},
256 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", -928826, -93.532},
257 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", -928826, -171.969},
258 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", -928826, -302.864},
259 {"1_Swap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", -928826, -8478.14},
260 {"2_Swap_USD", "Up:DiscountCurve/USD/0/6M", 980404, -1.04797},
261 {"2_Swap_USD", "Up:DiscountCurve/USD/1/1Y", 980404, -6.06931},
262 {"2_Swap_USD", "Up:DiscountCurve/USD/2/2Y", 980404, -15.8605},
263 {"2_Swap_USD", "Up:DiscountCurve/USD/3/3Y", 980404, -38.0708},
264 {"2_Swap_USD", "Up:DiscountCurve/USD/4/5Y", 980404, -68.7288},
265 {"2_Swap_USD", "Up:DiscountCurve/USD/5/7Y", 980404, -118.405},
266 {"2_Swap_USD", "Up:DiscountCurve/USD/6/10Y", 980404, -244.946},
267 {"2_Swap_USD", "Up:DiscountCurve/USD/7/15Y", 980404, -202.226},
268 {"2_Swap_USD", "Up:DiscountCurve/USD/8/20Y", 980404, 0.0148314},
269 {"2_Swap_USD", "Down:DiscountCurve/USD/0/6M", 980404, 1.04797},
270 {"2_Swap_USD", "Down:DiscountCurve/USD/1/1Y", 980404, 6.06959},
271 {"2_Swap_USD", "Down:DiscountCurve/USD/2/2Y", 980404, 15.8623},
272 {"2_Swap_USD", "Down:DiscountCurve/USD/3/3Y", 980404, 38.0784},
273 {"2_Swap_USD", "Down:DiscountCurve/USD/4/5Y", 980404, 68.7502},
274 {"2_Swap_USD", "Down:DiscountCurve/USD/5/7Y", 980404, 118.458},
275 {"2_Swap_USD", "Down:DiscountCurve/USD/6/10Y", 980404, 245.108},
276 {"2_Swap_USD", "Down:DiscountCurve/USD/7/15Y", 980404, 202.42},
277 {"2_Swap_USD", "Down:DiscountCurve/USD/8/20Y", 980404, -0.0148314},
278 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/0/6M", 980404, -201.015},
279 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/1/1Y", 980404, 18.134},
280 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/2/2Y", 980404, 47.3066},
281 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/3/3Y", 980404, 113.4},
282 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/4/5Y", 980404, 205.068},
283 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/5/7Y", 980404, 352.859},
284 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/6/10Y", 980404, 730.076},
285 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/7/15Y", 980404, 8626.78},
286 {"2_Swap_USD", "Up:IndexCurve/USD-LIBOR-3M/8/20Y", 980404, 5.86437},
287 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/0/6M", 980404, 201.03},
288 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/1/1Y", 980404, -18.0746},
289 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/2/2Y", 980404, -47.1526},
290 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/3/3Y", 980404, -113.136},
291 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/4/5Y", 980404, -204.611},
292 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/5/7Y", 980404, -352.166},
293 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/6/10Y", 980404, -729.248},
294 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/7/15Y", 980404, -8626.13},
295 {"2_Swap_USD", "Down:IndexCurve/USD-LIBOR-3M/8/20Y", 980404, -5.86436},
296 {"2_Swap_USD", "Up:FXSpot/EURUSD/0/spot", 980404, -9706.97},
297 {"2_Swap_USD", "Down:FXSpot/EURUSD/0/spot", 980404, 9903.07},
298 {"3_Swap_GBP", "Up:DiscountCurve/GBP/0/6M", 69795.3, 2.12392},
299 {"3_Swap_GBP", "Up:DiscountCurve/GBP/1/1Y", 69795.3, -0.646097},
300 {"3_Swap_GBP", "Up:DiscountCurve/GBP/2/2Y", 69795.3, -1.75066},
301 {"3_Swap_GBP", "Up:DiscountCurve/GBP/3/3Y", 69795.3, -4.24827},
302 {"3_Swap_GBP", "Up:DiscountCurve/GBP/4/5Y", 69795.3, -7.2252},
303 {"3_Swap_GBP", "Up:DiscountCurve/GBP/5/7Y", 69795.3, -12.5287},
304 {"3_Swap_GBP", "Up:DiscountCurve/GBP/6/10Y", 69795.3, -24.7828},
305 {"3_Swap_GBP", "Up:DiscountCurve/GBP/7/15Y", 69795.3, -39.2456},
306 {"3_Swap_GBP", "Up:DiscountCurve/GBP/8/20Y", 69795.3, 31.2081},
307 {"3_Swap_GBP", "Down:DiscountCurve/GBP/0/6M", 69795.3, -2.12413},
308 {"3_Swap_GBP", "Down:DiscountCurve/GBP/1/1Y", 69795.3, 0.645698},
309 {"3_Swap_GBP", "Down:DiscountCurve/GBP/2/2Y", 69795.3, 1.74981},
310 {"3_Swap_GBP", "Down:DiscountCurve/GBP/3/3Y", 69795.3, 4.2473},
311 {"3_Swap_GBP", "Down:DiscountCurve/GBP/4/5Y", 69795.3, 7.22426},
312 {"3_Swap_GBP", "Down:DiscountCurve/GBP/5/7Y", 69795.3, 12.5298},
313 {"3_Swap_GBP", "Down:DiscountCurve/GBP/6/10Y", 69795.3, 24.7939},
314 {"3_Swap_GBP", "Down:DiscountCurve/GBP/7/15Y", 69795.3, 39.2773},
315 {"3_Swap_GBP", "Down:DiscountCurve/GBP/8/20Y", 69795.3, -31.2925},
316 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/0/6M", 69795.3, -308.49},
317 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/1/1Y", 69795.3, 68.819},
318 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/2/2Y", 69795.3, 81.3735},
319 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/3/3Y", 69795.3, 239.034},
320 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/4/5Y", 69795.3, 372.209},
321 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/5/7Y", 69795.3, 654.949},
322 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/6/10Y", 69795.3, 1343.01},
323 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/7/15Y", 69795.3, 2139.68},
324 {"3_Swap_GBP", "Up:IndexCurve/GBP-LIBOR-6M/8/20Y", 69795.3, 12633.8},
325 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/0/6M", 69795.3, 308.513},
326 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/1/1Y", 69795.3, -68.7287},
327 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/2/2Y", 69795.3, -81.1438},
328 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/3/3Y", 69795.3, -238.649},
329 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/4/5Y", 69795.3, -371.553},
330 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/5/7Y", 69795.3, -653.972},
331 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/6/10Y", 69795.3, -1341.88},
332 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/7/15Y", 69795.3, -2138.11},
333 {"3_Swap_GBP", "Down:IndexCurve/GBP-LIBOR-6M/8/20Y", 69795.3, -12632.5},
334 {"3_Swap_GBP", "Up:FXSpot/EURGBP/0/spot", 69795.3, -691.043},
335 {"3_Swap_GBP", "Down:FXSpot/EURGBP/0/spot", 69795.3, 705.003},
336 {"4_Swap_JPY", "Up:DiscountCurve/JPY/0/6M", 871.03, -0.00750246},
337 {"4_Swap_JPY", "Up:DiscountCurve/JPY/1/1Y", 871.03, -0.00147994},
338 {"4_Swap_JPY", "Up:DiscountCurve/JPY/2/2Y", 871.03, -0.020079},
339 {"4_Swap_JPY", "Up:DiscountCurve/JPY/3/3Y", 871.03, -0.0667249},
340 {"4_Swap_JPY", "Up:DiscountCurve/JPY/4/5Y", 871.03, 4.75708},
341 {"4_Swap_JPY", "Down:DiscountCurve/JPY/0/6M", 871.03, 0.00747801},
342 {"4_Swap_JPY", "Down:DiscountCurve/JPY/1/1Y", 871.03, 0.00140807},
343 {"4_Swap_JPY", "Down:DiscountCurve/JPY/2/2Y", 871.03, 0.0199001},
344 {"4_Swap_JPY", "Down:DiscountCurve/JPY/3/3Y", 871.03, 0.0664106},
345 {"4_Swap_JPY", "Down:DiscountCurve/JPY/4/5Y", 871.03, -4.75978},
346 {"4_Swap_JPY", "Up:IndexCurve/JPY-LIBOR-6M/0/6M", 871.03, -193.514},
347 {"4_Swap_JPY", "Up:IndexCurve/JPY-LIBOR-6M/1/1Y", 871.03, 2.95767},
348 {"4_Swap_JPY", "Up:IndexCurve/JPY-LIBOR-6M/2/2Y", 871.03, 7.81453},
349 {"4_Swap_JPY", "Up:IndexCurve/JPY-LIBOR-6M/3/3Y", 871.03, 19.3576},
350 {"4_Swap_JPY", "Up:IndexCurve/JPY-LIBOR-6M/4/5Y", 871.03, 3832.83},
351 {"4_Swap_JPY", "Down:IndexCurve/JPY-LIBOR-6M/0/6M", 871.03, 193.528},
352 {"4_Swap_JPY", "Down:IndexCurve/JPY-LIBOR-6M/1/1Y", 871.03, -2.90067},
353 {"4_Swap_JPY", "Down:IndexCurve/JPY-LIBOR-6M/2/2Y", 871.03, -7.6631},
354 {"4_Swap_JPY", "Down:IndexCurve/JPY-LIBOR-6M/3/3Y", 871.03, -19.0907},
355 {"4_Swap_JPY", "Down:IndexCurve/JPY-LIBOR-6M/4/5Y", 871.03, -3832.59},
356 {"4_Swap_JPY", "Up:FXSpot/EURJPY/0/spot", 871.03, -8.62406},
357 {"4_Swap_JPY", "Down:FXSpot/EURJPY/0/spot", 871.03, 8.79829},
358 {"5_Swaption_EUR", "Up:DiscountCurve/EUR/6/10Y", 37497.4, -10.0061},
359 {"5_Swaption_EUR", "Up:DiscountCurve/EUR/7/15Y", 37497.4, -28.0689},
360 {"5_Swaption_EUR", "Up:DiscountCurve/EUR/8/20Y", 37497.4, -17.5118},
361 {"5_Swaption_EUR", "Down:DiscountCurve/EUR/6/10Y", 37497.4, 10.0128},
362 {"5_Swaption_EUR", "Down:DiscountCurve/EUR/7/15Y", 37497.4, 28.0967},
363 {"5_Swaption_EUR", "Down:DiscountCurve/EUR/8/20Y", 37497.4, 17.535},
364 {"5_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 37497.4, -395.217},
365 {"5_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/7/15Y", 37497.4, 56.7325},
366 {"5_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/8/20Y", 37497.4, 722.297},
367 {"5_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 37497.4, 397.912},
368 {"5_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/7/15Y", 37497.4, -56.5086},
369 {"5_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/8/20Y", 37497.4, -713.454},
370 {"5_Swaption_EUR", "Up:SwaptionVolatility/EUR/5/10Y/10Y/ATM", 37497.4, 367.34},
371 {"5_Swaption_EUR", "Down:SwaptionVolatility/EUR/5/10Y/10Y/ATM", 37497.4, -367.339},
372 {"6_Swaption_EUR", "Up:DiscountCurve/EUR/2/2Y", 10728, -0.485565},
373 {"6_Swaption_EUR", "Up:DiscountCurve/EUR/3/3Y", 10728, -1.08915},
374 {"6_Swaption_EUR", "Up:DiscountCurve/EUR/4/5Y", 10728, -1.98536},
375 {"6_Swaption_EUR", "Up:DiscountCurve/EUR/5/7Y", 10728, -0.589162},
376 {"6_Swaption_EUR", "Up:DiscountCurve/EUR/6/10Y", 10728, 0.00671364},
377 {"6_Swaption_EUR", "Down:DiscountCurve/EUR/2/2Y", 10728, 0.485627},
378 {"6_Swaption_EUR", "Down:DiscountCurve/EUR/3/3Y", 10728, 1.08927},
379 {"6_Swaption_EUR", "Down:DiscountCurve/EUR/4/5Y", 10728, 1.9858},
380 {"6_Swaption_EUR", "Down:DiscountCurve/EUR/5/7Y", 10728, 0.589199},
381 {"6_Swaption_EUR", "Down:DiscountCurve/EUR/6/10Y", 10728, -0.00671365},
382 {"6_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", 10728, -97.3815},
383 {"6_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", 10728, 4.02331},
384 {"6_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", 10728, 8.90295},
385 {"6_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", 10728, 322.905},
386 {"6_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 10728, 1.2365},
387 {"6_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", 10728, 97.9503},
388 {"6_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", 10728, -3.98884},
389 {"6_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", 10728, -8.83939},
390 {"6_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", 10728, -316.852},
391 {"6_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 10728, -1.23641},
392 {"6_Swaption_EUR", "Up:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 10728, 102.403},
393 {"6_Swaption_EUR", "Up:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 10728, 0.187171},
394 {"6_Swaption_EUR", "Down:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 10728, -102.402},
395 {"6_Swaption_EUR", "Down:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 10728, -0.187171},
396 {"17_Swaption_EUR", "Up:DiscountCurve/EUR/2/2Y", 9574.97, -0.255216},
397 {"17_Swaption_EUR", "Up:DiscountCurve/EUR/3/3Y", 9574.97, -1.08915},
398 {"17_Swaption_EUR", "Up:DiscountCurve/EUR/4/5Y", 9574.97, -1.98536},
399 {"17_Swaption_EUR", "Up:DiscountCurve/EUR/5/7Y", 9574.97, -0.589162},
400 {"17_Swaption_EUR", "Up:DiscountCurve/EUR/6/10Y", 9574.97, 0.00671364},
401 {"17_Swaption_EUR", "Down:DiscountCurve/EUR/2/2Y", 9574.97, 0.255232},
402 {"17_Swaption_EUR", "Down:DiscountCurve/EUR/3/3Y", 9574.97, 1.08927},
403 {"17_Swaption_EUR", "Down:DiscountCurve/EUR/4/5Y", 9574.97, 1.9858},
404 {"17_Swaption_EUR", "Down:DiscountCurve/EUR/5/7Y", 9574.97, 0.589199},
405 {"17_Swaption_EUR", "Down:DiscountCurve/EUR/6/10Y", 9574.97, -0.00671365},
406 {"17_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", 9574.97, -97.3815},
407 {"17_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", 9574.97, 4.02331},
408 {"17_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", 9574.97, 8.90295},
409 {"17_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", 9574.97, 322.905},
410 {"17_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 9574.97, 1.2365},
411 {"17_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", 9574.97, 97.9503},
412 {"17_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", 9574.97, -3.98884},
413 {"17_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", 9574.97, -8.83939},
414 {"17_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", 9574.97, -316.852},
415 {"17_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 9574.97, -1.23641},
416 {"17_Swaption_EUR", "Up:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 9574.97, 102.403},
417 {"17_Swaption_EUR", "Up:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 9574.97, 0.187171},
418 {"17_Swaption_EUR", "Down:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 9574.97, -102.402},
419 {"17_Swaption_EUR", "Down:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 9574.97, -0.187171},
420 { "13_Swaption_EUR", "Up:DiscountCurve/EUR/2/2Y", 28897.73677078046239330, -0.27803008252885775 },
421 { "13_Swaption_EUR", "Up:DiscountCurve/EUR/3/3Y", 28897.73677078046239330, -1.33378866274506436 },
422 { "13_Swaption_EUR", "Up:DiscountCurve/EUR/4/5Y", 28897.73677078046239330, -3.18918880432465812 },
423 { "13_Swaption_EUR", "Up:DiscountCurve/EUR/5/7Y", 28897.73677078046239330, -5.84492214726196835 },
424 { "13_Swaption_EUR", "Up:DiscountCurve/EUR/6/10Y", 28897.73677078046239330, -8.05244884515923331 },
425 { "13_Swaption_EUR", "Up:DiscountCurve/EUR/7/15Y", 28897.73677078046239330, -0.69943596490338678 },
426 { "13_Swaption_EUR", "Down:DiscountCurve/EUR/2/2Y", 28897.73677078046239330, 0.27805747913225787 },
427 { "13_Swaption_EUR", "Down:DiscountCurve/EUR/3/3Y", 28897.73677078046239330, 1.33400263515068218 },
428 { "13_Swaption_EUR", "Down:DiscountCurve/EUR/4/5Y", 28897.73677078046239330, 3.19001306503196247 },
429 { "13_Swaption_EUR", "Down:DiscountCurve/EUR/5/7Y", 28897.73677078046239330, 5.84723266483342741 },
430 { "13_Swaption_EUR", "Down:DiscountCurve/EUR/6/10Y", 28897.73677078046239330, 8.05807870846547303 },
431 { "13_Swaption_EUR", "Down:DiscountCurve/EUR/7/15Y", 28897.73677078046239330, 0.69933176309859846 },
432 { "13_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", 28897.73677078046239330, -38.21252730777996476 },
433 { "13_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", 28897.73677078046239330, -45.32662074925974593 },
434 { "13_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", 28897.73677078046239330, -64.33186224827295518 },
435 { "13_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", 28897.73677078046239330, -17.67819831141969189 },
436 { "13_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 28897.73677078046239330, 303.22767876380385133 },
437 { "13_Swaption_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/7/15Y", 28897.73677078046239330, 284.38032909158937400 },
438 { "13_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", 28897.73677078046239330, 38.21580821301176911 },
439 { "13_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", 28897.73677078046239330, 45.32991632828270667 },
440 { "13_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", 28897.73677078046239330, 66.17154485030550859 },
441 { "13_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", 28897.73677078046239330, 18.94715080036257859 },
442 { "13_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 28897.73677078046239330, -303.16555956740558031 },
443 { "13_Swaption_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/7/15Y", 28897.73677078046239330, -284.35056285505561391 },
444 { "13_Swaption_EUR", "Up:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 28897.73677078046239330, 11.08070607382614980 },
445 { "13_Swaption_EUR", "Up:SwaptionVolatility/EUR/1/2Y/10Y/ATM", 28897.73677078046239330, 76.78895257816475350 },
446 { "13_Swaption_EUR", "Up:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 28897.73677078046239330, 109.40430923897656612 },
447 { "13_Swaption_EUR", "Up:SwaptionVolatility/EUR/3/5Y/10Y/ATM", 28897.73677078046239330, 60.54663518636516528 },
448 { "13_Swaption_EUR", "Up:SwaptionVolatility/EUR/4/10Y/5Y/ATM", 28897.73677078046239330, 18.72588467272362323 },
449 { "13_Swaption_EUR", "Up:SwaptionVolatility/EUR/5/10Y/10Y/ATM", 28897.73677078046239330, 4.69121790060671628 },
450 { "13_Swaption_EUR", "Down:SwaptionVolatility/EUR/0/2Y/5Y/ATM", 28897.73677078046239330, -11.09549747305936762 },
451 { "13_Swaption_EUR", "Down:SwaptionVolatility/EUR/1/2Y/10Y/ATM", 28897.73677078046239330, -77.54106330653303303 },
452 { "13_Swaption_EUR", "Down:SwaptionVolatility/EUR/2/5Y/5Y/ATM", 28897.73677078046239330, -109.65679842332247063 },
453 { "13_Swaption_EUR", "Down:SwaptionVolatility/EUR/3/5Y/10Y/ATM", 28897.73677078046239330, -60.77103383964640670 },
454 { "13_Swaption_EUR", "Down:SwaptionVolatility/EUR/4/10Y/5Y/ATM", 28897.73677078046239330, -18.79003667952929391 },
455 { "13_Swaption_EUR", "Down:SwaptionVolatility/EUR/5/10Y/10Y/ATM", 28897.73677078046239330, -4.69902158074910403 },
456 {"7_FxOption_EUR_USD", "Up:DiscountCurve/EUR/3/3Y", 1.36968e+06, -2107.81},
457 {"7_FxOption_EUR_USD", "Up:DiscountCurve/EUR/4/5Y", 1.36968e+06, -3.85768},
458 {"7_FxOption_EUR_USD", "Up:DiscountCurve/USD/3/3Y", 1.36968e+06, 1698.91},
459 {"7_FxOption_EUR_USD", "Up:DiscountCurve/USD/4/5Y", 1.36968e+06, 3.10717},
460 {"7_FxOption_EUR_USD", "Down:DiscountCurve/EUR/3/3Y", 1.36968e+06, 2109.74},
461 {"7_FxOption_EUR_USD", "Down:DiscountCurve/EUR/4/5Y", 1.36968e+06, 3.85768},
462 {"7_FxOption_EUR_USD", "Down:DiscountCurve/USD/3/3Y", 1.36968e+06, -1698.12},
463 {"7_FxOption_EUR_USD", "Down:DiscountCurve/USD/4/5Y", 1.36968e+06, -3.10717},
464 {"7_FxOption_EUR_USD", "Up:FXSpot/EURUSD/0/spot", 1.36968e+06, 56850.7},
465 {"7_FxOption_EUR_USD", "Down:FXSpot/EURUSD/0/spot", 1.36968e+06, -56537.6},
466 {"7_FxOption_EUR_USD", "Up:FXVolatility/EURUSD/0/5Y/ATM", 1.36968e+06, 672236},
467 {"7_FxOption_EUR_USD", "Down:FXVolatility/EURUSD/0/5Y/ATM", 1.36968e+06, -329688},
468 {"8_FxOption_EUR_GBP", "Up:DiscountCurve/EUR/5/7Y", 798336, -2435.22},
469 {"8_FxOption_EUR_GBP", "Up:DiscountCurve/GBP/5/7Y", 798336, 1880.89},
470 {"8_FxOption_EUR_GBP", "Down:DiscountCurve/EUR/5/7Y", 798336, 2441.08},
471 {"8_FxOption_EUR_GBP", "Down:DiscountCurve/GBP/5/7Y", 798336, -1878.05},
472 {"8_FxOption_EUR_GBP", "Up:FXSpot/EURGBP/0/spot", 798336, 27009.9},
473 {"8_FxOption_EUR_GBP", "Down:FXSpot/EURGBP/0/spot", 798336, -26700.2},
474 {"8_FxOption_EUR_GBP", "Up:FXVolatility/EURGBP/0/5Y/ATM", 798336, 1.36635e+06},
475 {"8_FxOption_EUR_GBP", "Down:FXVolatility/EURGBP/0/5Y/ATM", 798336, -798336},
476 {"9_Cap_EUR", "Up:DiscountCurve/EUR/2/2Y", 289.105, -7.28588e-07},
477 {"9_Cap_EUR", "Up:DiscountCurve/EUR/3/3Y", 289.105, -0.000381869},
478 {"9_Cap_EUR", "Up:DiscountCurve/EUR/4/5Y", 289.105, -0.00790528},
479 {"9_Cap_EUR", "Up:DiscountCurve/EUR/5/7Y", 289.105, -0.0764893},
480 {"9_Cap_EUR", "Up:DiscountCurve/EUR/6/10Y", 289.105, -0.162697},
481 {"9_Cap_EUR", "Down:DiscountCurve/EUR/2/2Y", 289.105, 7.28664e-07},
482 {"9_Cap_EUR", "Down:DiscountCurve/EUR/3/3Y", 289.105, 0.000381934},
483 {"9_Cap_EUR", "Down:DiscountCurve/EUR/4/5Y", 289.105, 0.00790776},
484 {"9_Cap_EUR", "Down:DiscountCurve/EUR/5/7Y", 289.105, 0.0765231},
485 {"9_Cap_EUR", "Down:DiscountCurve/EUR/6/10Y", 289.105, 0.162824},
486 {"9_Cap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/1/1Y", 289.105, -1.81582e-05},
487 {"9_Cap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/2/2Y", 289.105, -0.00670729},
488 {"9_Cap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/3/3Y", 289.105, -0.330895},
489 {"9_Cap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/4/5Y", 289.105, -2.03937},
490 {"9_Cap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/5/7Y", 289.105, -6.42991},
491 {"9_Cap_EUR", "Up:IndexCurve/EUR-EURIBOR-6M/6/10Y", 289.105, 15.5182},
492 {"9_Cap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/1/1Y", 289.105, 1.97218e-05},
493 {"9_Cap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/2/2Y", 289.105, 0.00746096},
494 {"9_Cap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/3/3Y", 289.105, 0.353405},
495 {"9_Cap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/4/5Y", 289.105, 2.24481},
496 {"9_Cap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/5/7Y", 289.105, 7.1522},
497 {"9_Cap_EUR", "Down:IndexCurve/EUR-EURIBOR-6M/6/10Y", 289.105, -14.6675},
498 {"9_Cap_EUR", "Up:OptionletVolatility/EUR/4/1Y/0.05", 289.105, 8.49293e-05},
499 {"9_Cap_EUR", "Up:OptionletVolatility/EUR/9/2Y/0.05", 289.105, 0.0150901},
500 {"9_Cap_EUR", "Up:OptionletVolatility/EUR/14/3Y/0.05", 289.105, 0.620393},
501 {"9_Cap_EUR", "Up:OptionletVolatility/EUR/19/5Y/0.05", 289.105, 17.2057},
502 {"9_Cap_EUR", "Up:OptionletVolatility/EUR/24/10Y/0.05", 289.105, 24.4267},
503 {"9_Cap_EUR", "Down:OptionletVolatility/EUR/4/1Y/0.05", 289.105, -6.97789e-05},
504 {"9_Cap_EUR", "Down:OptionletVolatility/EUR/9/2Y/0.05", 289.105, -0.0125099},
505 {"9_Cap_EUR", "Down:OptionletVolatility/EUR/14/3Y/0.05", 289.105, -0.554344},
506 {"9_Cap_EUR", "Down:OptionletVolatility/EUR/19/5Y/0.05", 289.105, -16.1212},
507 {"9_Cap_EUR", "Down:OptionletVolatility/EUR/24/10Y/0.05", 289.105, -23.0264},
508 {"10_Floor_USD", "Up:DiscountCurve/USD/0/6M", 3406.46, -7.03494e-09},
509 {"10_Floor_USD", "Up:DiscountCurve/USD/1/1Y", 3406.46, -8.41429e-05},
510 {"10_Floor_USD", "Up:DiscountCurve/USD/2/2Y", 3406.46, -0.00329744},
511 {"10_Floor_USD", "Up:DiscountCurve/USD/3/3Y", 3406.46, -0.053884},
512 {"10_Floor_USD", "Up:DiscountCurve/USD/4/5Y", 3406.46, -0.269714},
513 {"10_Floor_USD", "Up:DiscountCurve/USD/5/7Y", 3406.46, -0.989583},
514 {"10_Floor_USD", "Up:DiscountCurve/USD/6/10Y", 3406.46, -1.26544},
515 {"10_Floor_USD", "Down:DiscountCurve/USD/0/6M", 3406.46, 7.0354e-09},
516 {"10_Floor_USD", "Down:DiscountCurve/USD/1/1Y", 3406.46, 8.41464e-05},
517 {"10_Floor_USD", "Down:DiscountCurve/USD/2/2Y", 3406.46, 0.00329786},
518 {"10_Floor_USD", "Down:DiscountCurve/USD/3/3Y", 3406.46, 0.0538949},
519 {"10_Floor_USD", "Down:DiscountCurve/USD/4/5Y", 3406.46, 0.269802},
520 {"10_Floor_USD", "Down:DiscountCurve/USD/5/7Y", 3406.46, 0.990038},
521 {"10_Floor_USD", "Down:DiscountCurve/USD/6/10Y", 3406.46, 1.26635},
522 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/0/6M", 3406.46, 0.00150733},
523 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/1/1Y", 3406.46, 0.240284},
524 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/2/2Y", 3406.46, 2.17175},
525 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/3/3Y", 3406.46, 7.77249},
526 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/4/5Y", 3406.46, 12.9642},
527 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/5/7Y", 3406.46, 16.8269},
528 {"10_Floor_USD", "Up:IndexCurve/USD-LIBOR-3M/6/10Y", 3406.46, -81.4363},
529 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/0/6M", 3406.46, -0.00139804},
530 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/1/1Y", 3406.46, -0.230558},
531 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/2/2Y", 3406.46, -2.00123},
532 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/3/3Y", 3406.46, -7.14862},
533 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/4/5Y", 3406.46, -11.2003},
534 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/5/7Y", 3406.46, -13.7183},
535 {"10_Floor_USD", "Down:IndexCurve/USD-LIBOR-3M/6/10Y", 3406.46, 84.0113},
536 {"10_Floor_USD", "Up:FXSpot/EURUSD/0/spot", 3406.46, -33.7273},
537 {"10_Floor_USD", "Down:FXSpot/EURUSD/0/spot", 3406.46, 34.4087},
538 {"10_Floor_USD", "Up:OptionletVolatility/USD/0/1Y/0.01", 3406.46, 0.402913},
539 {"10_Floor_USD", "Up:OptionletVolatility/USD/5/2Y/0.01", 3406.46, 3.32861},
540 {"10_Floor_USD", "Up:OptionletVolatility/USD/10/3Y/0.01", 3406.46, 16.8798},
541 {"10_Floor_USD", "Up:OptionletVolatility/USD/15/5Y/0.01", 3406.46, 96.415},
542 {"10_Floor_USD", "Up:OptionletVolatility/USD/20/10Y/0.01", 3406.46, 92.2212},
543 {"10_Floor_USD", "Down:OptionletVolatility/USD/0/1Y/0.01", 3406.46, -0.37428},
544 {"10_Floor_USD", "Down:OptionletVolatility/USD/5/2Y/0.01", 3406.46, -3.14445},
545 {"10_Floor_USD", "Down:OptionletVolatility/USD/10/3Y/0.01", 3406.46, -16.3074},
546 {"10_Floor_USD", "Down:OptionletVolatility/USD/15/5Y/0.01", 3406.46, -94.5309},
547 {"10_Floor_USD", "Down:OptionletVolatility/USD/20/10Y/0.01", 3406.46, -90.9303},
548 // Excel calculation with z=5% flat rate, term structure day counter ActAct,
549 // time to maturity T = YEARFRAC(14/4/16, 14/4/26, 1) = 9.99800896, yields
550 // sensi to up shift d=1bp: exp(-(z+d)*T)-exp(z*T)
551 // = -0.00060616719559925
552 {"11_ZeroBond_EUR", "Up:YieldCurve/BondCurve0/6/10Y", 0.60659, -0.000606168}, // OK, diff 1e-9
553 // sensi to down shift d=-1bp: 0.00060677354516836
554 {"11_ZeroBond_EUR", "Down:YieldCurve/BondCurve0/6/10Y", 0.60659, 0.000606774}, // OK, diff < 1e-9
555 // A relative shift in yield curve is equivalent to a relative shift in default curve
556 {"11_ZeroBond_EUR", "Up:SurvivalProbability/BondIssuer0/6/10Y", 0.60659, -0.000606168},
557 {"11_ZeroBond_EUR", "Down:SurvivalProbability/BondIssuer0/6/10Y", 0.60659, 0.000606774},
558 // sensi to up shift d=+1bp: exp(-(z+d)*T)*USDEUR - exp(-z*T)*USDEUR
559 // = -0.000505139329666004
560 {"12_ZeroBond_USD", "Up:YieldCurve/BondCurve0/6/10Y", 0.505492, -0.00050514}, // OK, diff < 1e-8
561 // sensi to down shift d=-1bp: 0.000505644620973689
562 {"12_ZeroBond_USD", "Down:YieldCurve/BondCurve0/6/10Y", 0.505492, 0.000505645}, // OK, diff < 1e-9
563 // A relative shift in yield curve is equivalent to a relative shift in default curve
564 {"12_ZeroBond_USD", "Up:SurvivalProbability/BondIssuer0/6/10Y", 0.505492, -0.00050514},
565 {"12_ZeroBond_USD", "Down:SurvivalProbability/BondIssuer0/6/10Y", 0.505492, 0.000505645},
566 // sensi to EURUSD upshift d=+1%: exp(-z*T)*USDEUR/(1+d) - exp(-z*T)*USDEUR
567 // = -0.00500487660122262
568 {"12_ZeroBond_USD", "Up:FXSpot/EURUSD/0/spot", 0.505492, -0.00500487}, // OK, diff < 1e-8
569 // sensi to EURUSD down shift d=-1%: 0.00510598521942907
570 {"12_ZeroBond_USD", "Down:FXSpot/EURUSD/0/spot", 0.505492, 0.00510598}, // OK, diff < 1e-8
571 {"14_EquityOption_SP5", "Up:DiscountCurve/USD/2/2Y", 216085, 123.022},
572 {"14_EquityOption_SP5", "Up:DiscountCurve/USD/3/3Y", 216085, 1.0169},
573 {"14_EquityOption_SP5", "Down:DiscountCurve/USD/2/2Y", 216085, -122.988},
574 {"14_EquityOption_SP5", "Down:DiscountCurve/USD/3/3Y", 216085, -1.0169},
575 {"14_EquityOption_SP5", "Up:EquitySpot/SP5/0/spot", 216085, 8423.66},
576 {"14_EquityOption_SP5", "Down:EquitySpot/SP5/0/spot", 216085, -8277.55},
577 {"14_EquityOption_SP5", "Up:FXSpot/EURUSD/0/spot", 216085, -2139.45},
578 {"14_EquityOption_SP5", "Down:FXSpot/EURUSD/0/spot", 216085, 2182.67},
579 {"14_EquityOption_SP5", "Up:EquityVolatility/SP5/0/5Y/ATM", 216085, 1849.98},
580 {"14_EquityOption_SP5", "Down:EquityVolatility/SP5/0/5Y/ATM", 216085, -1850.33},
581 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/0/6M", -32068.5, -0.0306304},
582 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/1/1Y", -32068.5, -0.279201},
583 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/2/2Y", -32068.5, -0.772336},
584 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/3/3Y", -32068.5, -1.80941},
585 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/4/5Y", -32068.5, -3.18149},
586 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/5/7Y", -32068.5, -5.26791},
587 {"15_CPIInflationSwap_UKRPI", "Up:DiscountCurve/GBP/6/10Y", -32068.5, 58.9998},
588 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/0/6M", -32068.5, 0.030632},
589 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/1/1Y", -32068.5, 0.279223},
590 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/2/2Y", -32068.5, 0.772443},
591 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/3/3Y", -32068.5, 1.8098},
592 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/4/5Y", -32068.5, 3.18254},
593 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/5/7Y", -32068.5, 5.27039},
594 {"15_CPIInflationSwap_UKRPI", "Down:DiscountCurve/GBP/6/10Y", -32068.5, -59.0602},
595 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/0/6M", -32068.5, -6.17897},
596 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/1/1Y", -32068.5, 0.672814},
597 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/2/2Y", -32068.5, 0.804723},
598 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/3/3Y", -32068.5, 2.4176},
599 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/4/5Y", -32068.5, 3.61554},
600 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/5/7Y", -32068.5, 6.77412},
601 {"15_CPIInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/6/10Y", -32068.5, 89.6542},
602 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/0/6M", -32068.5, 6.17927},
603 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/1/1Y", -32068.5, -0.671026},
604 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/2/2Y", -32068.5, -0.80017},
605 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/3/3Y", -32068.5, -2.40996},
606 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/4/5Y", -32068.5, -3.60255},
607 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/5/7Y", -32068.5, -6.75478},
608 {"15_CPIInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/6/10Y", -32068.5, -89.6393},
609 {"15_CPIInflationSwap_UKRPI", "Up:FXSpot/EURGBP/0/spot", -32068.5, 317.51},
610 {"15_CPIInflationSwap_UKRPI", "Down:FXSpot/EURGBP/0/spot", -32068.5, -323.924},
611 {"15_CPIInflationSwap_UKRPI", "Up:ZeroInflationCurve/UKRPI/0/1Y", -32068.5, -0.0789981},
612 {"15_CPIInflationSwap_UKRPI", "Up:ZeroInflationCurve/UKRPI/1/2Y", -32068.5, -0.154098},
613 {"15_CPIInflationSwap_UKRPI", "Up:ZeroInflationCurve/UKRPI/2/3Y", -32068.5, -0.381073},
614 {"15_CPIInflationSwap_UKRPI", "Up:ZeroInflationCurve/UKRPI/3/5Y", -32068.5, -0.749769},
615 {"15_CPIInflationSwap_UKRPI", "Up:ZeroInflationCurve/UKRPI/4/7Y", -32068.5, -1.34474},
616 {"15_CPIInflationSwap_UKRPI", "Up:ZeroInflationCurve/UKRPI/5/10Y", -32068.5, -144.53},
617 {"15_CPIInflationSwap_UKRPI", "Down:ZeroInflationCurve/UKRPI/0/1Y", -32068.5, 0.0789981},
618 {"15_CPIInflationSwap_UKRPI", "Down:ZeroInflationCurve/UKRPI/1/2Y", -32068.5, 0.154083},
619 {"15_CPIInflationSwap_UKRPI", "Down:ZeroInflationCurve/UKRPI/2/3Y", -32068.5, 0.381006},
620 {"15_CPIInflationSwap_UKRPI", "Down:ZeroInflationCurve/UKRPI/3/5Y", -32068.5, 0.749547},
621 {"15_CPIInflationSwap_UKRPI", "Down:ZeroInflationCurve/UKRPI/4/7Y", -32068.5, 1.34416},
622 {"15_CPIInflationSwap_UKRPI", "Down:ZeroInflationCurve/UKRPI/5/10Y", -32068.5, 144.404},
623 {"16_YoYInflationSwap_UKRPI", "Up:DiscountCurve/GBP/1/1Y", 7005.96, 0.232259},
624 {"16_YoYInflationSwap_UKRPI", "Up:DiscountCurve/GBP/2/2Y", 7005.96, -0.239315},
625 {"16_YoYInflationSwap_UKRPI", "Up:DiscountCurve/GBP/3/3Y", 7005.96, -0.583046},
626 {"16_YoYInflationSwap_UKRPI", "Up:DiscountCurve/GBP/4/5Y", 7005.96, -1.00199},
627 {"16_YoYInflationSwap_UKRPI", "Up:DiscountCurve/GBP/5/7Y", 7005.96, -1.72218},
628 {"16_YoYInflationSwap_UKRPI", "Up:DiscountCurve/GBP/6/10Y", 7005.96, -1.79744},
629 {"16_YoYInflationSwap_UKRPI", "Down:DiscountCurve/GBP/1/1Y", 7005.96, -0.232282},
630 {"16_YoYInflationSwap_UKRPI", "Down:DiscountCurve/GBP/2/2Y", 7005.96, 0.239363},
631 {"16_YoYInflationSwap_UKRPI", "Down:DiscountCurve/GBP/3/3Y", 7005.96, 0.583198},
632 {"16_YoYInflationSwap_UKRPI", "Down:DiscountCurve/GBP/4/5Y", 7005.96, 1.00236},
633 {"16_YoYInflationSwap_UKRPI", "Down:DiscountCurve/GBP/5/7Y", 7005.96, 1.72305},
634 {"16_YoYInflationSwap_UKRPI", "Down:DiscountCurve/GBP/6/10Y", 7005.96, 1.79882},
635 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/0/6M", 7005.96, -0.0656954},
636 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/1/1Y", 7005.96, -11.785},
637 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/2/2Y", 7005.96, 0.816056},
638 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/3/3Y", 7005.96, 2.44319},
639 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/4/5Y", 7005.96, 3.66156},
640 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/5/7Y", 7005.96, 6.85113},
641 {"16_YoYInflationSwap_UKRPI", "Up:IndexCurve/GBP-LIBOR-6M/6/10Y", 7005.96, 90.5575},
642 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/0/6M", 7005.96, 0.0656954},
643 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/1/1Y", 7005.96, 11.7862},
644 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/2/2Y", 7005.96, -0.80686},
645 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/3/3Y", 7005.96, -2.42775},
646 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/4/5Y", 7005.96, -3.63532},
647 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/5/7Y", 7005.96, -6.81206},
648 {"16_YoYInflationSwap_UKRPI", "Down:IndexCurve/GBP-LIBOR-6M/6/10Y", 7005.96, -90.5274},
649 {"16_YoYInflationSwap_UKRPI", "Up:FXSpot/EURGBP/0/spot", 7005.96, -69.3659},
650 {"16_YoYInflationSwap_UKRPI", "Down:FXSpot/EURGBP/0/spot", 7005.96, 70.7673},
651 {"16_YoYInflationSwap_UKRPI", "Up:YoYInflationCurve/UKRPI/0/1Y", 7005.96, -12.1136},
652 {"16_YoYInflationSwap_UKRPI", "Up:YoYInflationCurve/UKRPI/1/2Y", 7005.96, -11.4741},
653 {"16_YoYInflationSwap_UKRPI", "Up:YoYInflationCurve/UKRPI/2/3Y", 7005.96, -16.3788},
654 {"16_YoYInflationSwap_UKRPI", "Up:YoYInflationCurve/UKRPI/3/5Y", 7005.96, -20.4522},
655 {"16_YoYInflationSwap_UKRPI", "Up:YoYInflationCurve/UKRPI/4/7Y", 7005.96, -23.3381},
656 {"16_YoYInflationSwap_UKRPI", "Up:YoYInflationCurve/UKRPI/5/10Y", 7005.96, -17.2056},
657 {"16_YoYInflationSwap_UKRPI", "Down:YoYInflationCurve/UKRPI/0/1Y", 7005.96, 12.1136},
658 {"16_YoYInflationSwap_UKRPI", "Down:YoYInflationCurve/UKRPI/1/2Y", 7005.96, 11.4741},
659 {"16_YoYInflationSwap_UKRPI", "Down:YoYInflationCurve/UKRPI/2/3Y", 7005.96, 16.3788},
660 {"16_YoYInflationSwap_UKRPI", "Down:YoYInflationCurve/UKRPI/3/5Y", 7005.96, 20.4522},
661 {"16_YoYInflationSwap_UKRPI", "Down:YoYInflationCurve/UKRPI/4/7Y", 7005.96, 23.3381},
662 {"16_YoYInflationSwap_UKRPI", "Down:YoYInflationCurve/UKRPI/5/10Y", 7005.96, 17.2056},
663 {"17_CommodityForward_GOLD", "Up:DiscountCurve/USD/1/1Y", -735.964496751649, 0.073448445224},
664 {"17_CommodityForward_GOLD", "Down:DiscountCurve/USD/1/1Y", -735.964496751649, -0.073455776029},
665 {"17_CommodityForward_GOLD", "Up:FXSpot/EURUSD/0/spot", -735.964496751649, 7.286777195561},
666 {"17_CommodityForward_GOLD", "Down:FXSpot/EURUSD/0/spot", -735.964496751649, -7.433984815673},
667 {"17_CommodityForward_GOLD", "Up:CommodityCurve/COMDTY_GOLD_USD/1/1Y", -735.964496751649, 938.880422284606},
668 {"17_CommodityForward_GOLD", "Down:CommodityCurve/COMDTY_GOLD_USD/1/1Y", -735.964496751649, -938.880422284606},
669 {"18_CommodityForward_OIL", "Up:DiscountCurve/USD/3/3Y", -118575.997564574063, 23.666326609469},
670 {"18_CommodityForward_OIL", "Up:DiscountCurve/USD/4/5Y", -118575.997564574063, 23.759329674402},
671 {"18_CommodityForward_OIL", "Down:DiscountCurve/USD/3/3Y", -118575.997564574063, -23.671051063342},
672 {"18_CommodityForward_OIL", "Down:DiscountCurve/USD/4/5Y", -118575.997564574063, -23.764091336881},
673 {"18_CommodityForward_OIL", "Up:FXSpot/EURUSD/0/spot", -118575.997564574063, 1174.019777867070},
674 {"18_CommodityForward_OIL", "Down:FXSpot/EURUSD/0/spot", -118575.997564574063, -1197.737349137125},
675 {"18_CommodityForward_OIL", "Up:CommodityCurve/COMDTY_WTI_USD/2/2Y", -118575.997564574063, -10938.550513848924},
676 {"18_CommodityForward_OIL", "Up:CommodityCurve/COMDTY_WTI_USD/3/5Y", -118575.997564574063, -24245.826202620548},
677 {"18_CommodityForward_OIL", "Down:CommodityCurve/COMDTY_WTI_USD/2/2Y", -118575.997564574063,
678 10938.550513849448},
679 {"18_CommodityForward_OIL", "Down:CommodityCurve/COMDTY_WTI_USD/3/5Y", -118575.997564574063,
680 24245.826202621072},
681 {"19_CommodityOption_GOLD", "Up:DiscountCurve/USD/1/1Y", 5266.437412224631, -0.516232985022},
682 {"19_CommodityOption_GOLD", "Up:DiscountCurve/USD/2/2Y", 5266.437412224631, -0.018723533876},
683 {"19_CommodityOption_GOLD", "Down:DiscountCurve/USD/1/1Y", 5266.437412224631, 0.516283587557},
684 {"19_CommodityOption_GOLD", "Down:DiscountCurve/USD/2/2Y", 5266.437412224631, 0.018723579571},
685 {"19_CommodityOption_GOLD", "Up:FXSpot/EURUSD/0/spot", 5266.437412224631, -52.142944675492},
686 {"19_CommodityOption_GOLD", "Down:FXSpot/EURUSD/0/spot", 5266.437412224631, 53.196337497218},
687 {"19_CommodityOption_GOLD", "Up:CommodityCurve/COMDTY_GOLD_USD/1/1Y", 5266.437412224631, 490.253537097216},
688 {"19_CommodityOption_GOLD", "Down:CommodityCurve/COMDTY_GOLD_USD/1/1Y", 5266.437412224631, -465.274919275530},
689 {"19_CommodityOption_GOLD", "Up:CommodityVolatility/COMDTY_GOLD_USD/6/1Y/ATM", 5266.437412224631,
690 56.110511491685},
691 {"19_CommodityOption_GOLD", "Down:CommodityVolatility/COMDTY_GOLD_USD/6/1Y/ATM", 5266.437412224631,
692 -56.112114940141},
693 {"20_CommodityOption_OIL", "Up:DiscountCurve/USD/3/3Y", -491152.228798501019, 98.775116046891},
694 {"20_CommodityOption_OIL", "Up:DiscountCurve/USD/4/5Y", -491152.228798501019, 97.292577287881},
695 {"20_CommodityOption_OIL", "Down:DiscountCurve/USD/3/3Y", -491152.228798501019, -98.794984069362},
696 {"20_CommodityOption_OIL", "Down:DiscountCurve/USD/4/5Y", -491152.228798501019, -97.311852635990},
697 {"20_CommodityOption_OIL", "Up:FXSpot/EURUSD/0/spot", -491152.228798501019, 4862.893354440632},
698 {"20_CommodityOption_OIL", "Down:FXSpot/EURUSD/0/spot", -491152.228798501019, -4961.133624227310},
699 {"20_CommodityOption_OIL", "Up:CommodityCurve/COMDTY_WTI_USD/2/2Y", -491152.228798501019, 4223.515679404372},
700 {"20_CommodityOption_OIL", "Up:CommodityCurve/COMDTY_WTI_USD/3/5Y", -491152.228798501019, 9317.978340855800},
701 {"20_CommodityOption_OIL", "Down:CommodityCurve/COMDTY_WTI_USD/2/2Y", -491152.228798501019, -4256.075631047075},
702 {"20_CommodityOption_OIL", "Down:CommodityCurve/COMDTY_WTI_USD/3/5Y", -491152.228798501019, -9477.947397496144},
703 { "20_CommodityOption_OIL", "Up:CommodityVolatility/COMDTY_WTI_USD/3/1Y/0.95", -491152.228798501019, -169.914415647450 },
704 { "20_CommodityOption_OIL", "Up:CommodityVolatility/COMDTY_WTI_USD/6/1Y/ATM", -491152.228798501019, -167.260480643541 },
705 { "20_CommodityOption_OIL", "Up:CommodityVolatility/COMDTY_WTI_USD/5/5Y/0.95", -491152.228798501019, -2553.579689398874 },
706 { "20_CommodityOption_OIL", "Up:CommodityVolatility/COMDTY_WTI_USD/8/5Y/ATM", -491152.228798501019, -2513.783958086802 },
707 { "20_CommodityOption_OIL", "Down:CommodityVolatility/COMDTY_WTI_USD/3/1Y/0.95", -491152.228798501019, 168.278235032340 },
708 { "20_CommodityOption_OIL", "Down:CommodityVolatility/COMDTY_WTI_USD/6/1Y/ATM", -491152.228798501019, 165.649017560529 },
709 { "20_CommodityOption_OIL", "Down:CommodityVolatility/COMDTY_WTI_USD/5/5Y/0.95", -491152.228798501019, 2540.538653619646 },
710 { "20_CommodityOption_OIL", "Down:CommodityVolatility/COMDTY_WTI_USD/8/5Y/ATM", -491152.228798501019, 2500.755505821493 }};
711 // clang-format on
712
713 std::map<pair<string, string>, Real> npvMap, sensiMap;
714 std::set<pair<string, string>> coveredSensis;
715 for (Size i = 0; i < cachedResults.size(); ++i) {
716 pair<string, string> p(cachedResults[i].id, cachedResults[i].label);
717 npvMap[p] = cachedResults[i].npv;
718 sensiMap[p] = cachedResults[i].sensi;
719 }
720
721 Real tiny = 1.0e-10;
722 Real tolerance = 0.01;
723 Size count = 0;
724 vector<ShiftScenarioGenerator::ScenarioDescription> desc = scenarioGenerator->scenarioDescriptions();
725 size_t currentTradeIdx = 0;
726 for (const auto& [tradeId, trade] : portfolio->trades()) {
727 Real npv0 = cube->getT0(currentTradeIdx, 0);
728 for (Size j = 1; j < scenarioGenerator->samples(); ++j) { // skip j = 0, this is the base scenario
729 Real npv = cube->get(currentTradeIdx, 0, j, 0);
730 Real sensi = npv - npv0;
731 string label = to_string(desc[j]);
732 if (fabs(sensi) > tiny) {
733 count++;
734 BOOST_TEST_MESSAGE("{ \"" << tradeId << "\", \"" << label << "\", " << std::fixed
735 << std::setprecision(12) << npv0 << ", " << sensi << " },");
736 pair<string, string> p(tradeId, label);
737 QL_REQUIRE(npvMap.find(p) != npvMap.end(),
738 "pair (" << p.first << ", " << p.second << ") not found in npv map");
739 QL_REQUIRE(sensiMap.find(p) != sensiMap.end(),
740 "pair (" << p.first << ", " << p.second << ") not found in sensi map");
741 BOOST_CHECK_MESSAGE(fabs(npv0 - npvMap[p]) < tolerance || fabs((npv0 - npvMap[p]) / npv0) < tolerance,
742 "npv regression failed for pair (" << p.first << ", " << p.second << "): " << npv0
743 << " vs " << npvMap[p]);
744 BOOST_CHECK_MESSAGE(fabs(sensi - sensiMap[p]) < tolerance ||
745 fabs((sensi - sensiMap[p]) / sensi) < tolerance,
746 "sensitivity regression failed for pair ("
747 << p.first << ", " << p.second << "): " << sensi << " vs " << sensiMap[p]);
748 coveredSensis.insert(p);
749 }
750 }
751 currentTradeIdx++;
752 }
753 currentTradeIdx = 0;
754 BOOST_CHECK_MESSAGE(count == cachedResults.size(), "number of non-zero sensitivities ("
755 << count << ") do not match regression data ("
756 << cachedResults.size() << ")");
757 for (auto const& p : sensiMap) {
758 if (coveredSensis.find(p.first) == coveredSensis.end()) {
759 BOOST_TEST_MESSAGE("sensi in expected, but not in calculated results: " << p.first.first << " "
760 << p.first.second);
761 }
762 }
763
764 // Repeat analysis using the SensitivityAnalysis class and spot check a few deltas and gammas
765 QuantLib::ext::shared_ptr<SensitivityAnalysis> sa = QuantLib::ext::make_shared<SensitivityAnalysis>(
766 portfolio, initMarket, Market::defaultConfiguration, data, simMarketData, sensiData, false);
767 sa->generateSensitivities();
768 map<pair<string, string>, Real> deltaMap;
769 map<pair<string, string>, Real> gammaMap;
770 std::set<string> sensiTrades;
771 for (const auto& [pid, p] : portfolio->trades()) {
772 sensiTrades.insert(pid);
773 for (const auto& f : sa->sensiCube()->factors()) {
774 auto des = sa->sensiCube()->factorDescription(f);
775 deltaMap[make_pair(pid, des)] = sa->sensiCube()->delta(pid, f);
776 gammaMap[make_pair(pid, des)] = sa->sensiCube()->gamma(pid, f);
777 }
778 }
779
780 std::vector<Results> cachedResults2 = {
781 // trade, factor, delta, gamma
782 {"11_ZeroBond_EUR", "YieldCurve/BondCurve0/6/10Y", -0.000606168, 6.06352e-07}, // gamma OK see case 1 below
783 {"12_ZeroBond_USD", "YieldCurve/BondCurve0/6/10Y", -0.00050514, 5.05294e-07}, // gamma OK, see case 2 below
784 {"12_ZeroBond_USD", "FXSpot/EURUSD/0/spot", -0.00500487, 0.000101108} // gamma OK, see case 3
785 };
786
787 // Validation of cached gammas:
788 // gamma * (dx)^2 = \partial^2_x NPV(x) * (dx)^2
789 // \approx (NPV(x_up) - 2 NPV(x) + NPV(x_down)) = sensi(up) + sensi(down)
790 // Case 1: "11_ZeroBond_EUR", "YieldCurve/BondCurve1/6/10Y"
791 // NPV(x_up) - NPV(x) = -0.000606168, NPV(x_down) - NPV(x) = 0.000606774
792 // gamma * (dx)^2 = -0.000606168 + 0.000606774 = 0.000000606 = 6.06e-7
793 //
794 // Case 2: "12_ZeroBond_USD", "YieldCurve/BondCurve1/6/10Y"
795 // NPV(x_up) - NPV(x) = -0.00050514, NPV(x_down) - NPV(x) = 0.000505645
796 // gamma * (dx)^2 = -0.00050514 + 0.000505645 = 0.000000505 = 5.05e-7
797 //
798 // Case 3: "12_ZeroBond_USD", "FXSpot/EURUSD/0/spot"
799 // NPV(x_up) - NPV(x) = -0.00500487, NPV(x_down) - NPV(x) = 0.00510598
800 // gamma * (dx)^2 = -0.00500487 + 0.00510598 = 0.00010111
801 //
802 for (Size i = 0; i < cachedResults2.size(); ++i) {
803 pair<string, string> p(cachedResults2[i].id, cachedResults2[i].label);
804 Real delta = cachedResults2[i].npv; // is delta
805 Real gamma = cachedResults2[i].sensi; // is gamma
806 BOOST_CHECK_MESSAGE(fabs((delta - deltaMap[p]) / delta) < tolerance,
807 "delta regression failed for trade " << p.first << " factor " << p.second << ", cached="
808 << delta << ", computed=" << deltaMap[p]);
809 BOOST_CHECK_MESSAGE(fabs((gamma - gammaMap[p]) / gamma) < tolerance,
810 "gamma regression failed for trade " << p.first << " factor " << p.second << ", cached="
811 << gamma << ", computed=" << gammaMap[p]);
812 }
813
814 BOOST_TEST_MESSAGE("Cube generated in " << t.format(default_places, "%w") << " seconds");
815 ObservationMode::instance().setMode(backupMode);
816 IndexManager::instance().clearHistories();
817}
818} // namespace
819
820BOOST_FIXTURE_TEST_SUITE(OREAnalyticsTestSuite, ore::test::OreaTopLevelFixture)
821
822BOOST_AUTO_TEST_SUITE(SensitivityAnalysisTest)
823
824BOOST_AUTO_TEST_CASE(testPortfolioSensitivityNoneObs) {
825 BOOST_TEST_MESSAGE("Testing Portfolio sensitivity (None observation mode)");
826 testPortfolioSensitivity(ObservationMode::Mode::None);
827}
828
829BOOST_AUTO_TEST_CASE(testPortfolioSensitivityDisableObs) {
830 BOOST_TEST_MESSAGE("Testing Portfolio sensitivity (Disable observation mode)");
831 testPortfolioSensitivity(ObservationMode::Mode::Disable);
832}
833
834BOOST_AUTO_TEST_CASE(testPortfolioSensitivityDeferObs) {
835 BOOST_TEST_MESSAGE("Testing Portfolio sensitivity (Defer observation mode)");
836 testPortfolioSensitivity(ObservationMode::Mode::Defer);
837}
838
839BOOST_AUTO_TEST_CASE(testPortfolioSensitivityUnregisterObs) {
840 BOOST_TEST_MESSAGE("Testing Portfolio sensitivity (Unregister observation mode)");
841 testPortfolioSensitivity(ObservationMode::Mode::Unregister);
842}
843
844void test1dShifts(bool granular) {
845 BOOST_TEST_MESSAGE("Testing 1d shifts " << (granular ? "granular" : "sparse"));
846
847 SavedSettings backup;
848
849 ObservationMode::Mode backupMode = ObservationMode::instance().mode();
850 ObservationMode::instance().setMode(ObservationMode::Mode::None);
851
852 Date today = Date(14, April, 2016);
853 Settings::instance().evaluationDate() = today;
854
855 BOOST_TEST_MESSAGE("Today is " << today);
856
857 // build model
858 string baseCcy = "EUR";
859 vector<string> ccys;
860 ccys.push_back(baseCcy);
861 ccys.push_back("GBP");
862
863 // Init market
864 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
865
866 // build scenario sim market parameters
867 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
869
870 // sensitivity config
871 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData;
872 if (granular)
874 else
876
877 // build sim market
878 auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(initMarket, simMarketData);
879
880 // build scenario factory
881 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
882 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
883
884 // build scenario generator
885 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
886 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
887 scenarioFactory, false);
888
889 // cache initial zero rates
890 vector<Period> tenors = simMarketData->yieldCurveTenors("");
891 vector<Real> initialZeros(tenors.size());
892 vector<Real> times(tenors.size());
893 string ccy = simMarketData->ccys()[0];
894 Handle<YieldTermStructure> ts = initMarket->discountCurve(ccy);
895 DayCounter dc = ts->dayCounter();
896 for (Size j = 0; j < tenors.size(); ++j) {
897 Date d = today + simMarketData->yieldCurveTenors("")[j];
898 initialZeros[j] = ts->zeroRate(d, dc, Continuous);
899 times[j] = dc.yearFraction(today, d);
900 }
901
902 // apply zero shifts for tenors on the shift curve
903 // collect shifted data at tenors of the underlying curve
904 // aggregate "observed" shifts
905 // compare to expected total shifts
906 vector<Period> shiftTenors = sensiData->discountCurveShiftData()["EUR"]->shiftTenors;
907 vector<Time> shiftTimes(shiftTenors.size());
908 for (Size i = 0; i < shiftTenors.size(); ++i)
909 shiftTimes[i] = dc.yearFraction(today, today + shiftTenors[i]);
910
911 vector<Real> shiftedZeros(tenors.size());
912 vector<Real> diffAbsolute(tenors.size(), 0.0);
913 vector<Real> diffRelative(tenors.size(), 0.0);
914 Real shiftSize = 0.01;
915 ShiftType shiftTypeAbsolute = ShiftType::Absolute;
916 ShiftType shiftTypeRelative = ShiftType::Relative;
917 for (Size i = 0; i < shiftTenors.size(); ++i) {
918 scenarioGenerator->applyShift(i, shiftSize, true, shiftTypeAbsolute, shiftTimes, initialZeros, times,
919 shiftedZeros, true);
920 for (Size j = 0; j < tenors.size(); ++j)
921 diffAbsolute[j] += shiftedZeros[j] - initialZeros[j];
922 scenarioGenerator->applyShift(i, shiftSize, true, shiftTypeRelative, shiftTimes, initialZeros, times,
923 shiftedZeros, true);
924 for (Size j = 0; j < tenors.size(); ++j)
925 diffRelative[j] += shiftedZeros[j] / initialZeros[j] - 1.0;
926 }
927
928 Real tolerance = 1.0e-10;
929 for (Size j = 0; j < tenors.size(); ++j) {
930 // BOOST_TEST_MESSAGE("1d shift: checking sensitivity to curve tenor point " << j << ": " << diff[j]);
931 BOOST_CHECK_MESSAGE(fabs(diffAbsolute[j] - shiftSize) < tolerance,
932 "inconsistency in absolute 1d shifts at curve tenor point " << j);
933 BOOST_CHECK_MESSAGE(fabs(diffRelative[j] - shiftSize) < tolerance,
934 "inconsistency in relative 1d shifts at curve tenor point " << j);
935 }
936 ObservationMode::instance().setMode(backupMode);
937 IndexManager::instance().clearHistories();
938}
939
940BOOST_AUTO_TEST_CASE(test1dShiftsSparse) { test1dShifts(false); }
941
942BOOST_AUTO_TEST_CASE(test1dShiftsGranular) { test1dShifts(true); }
943
944BOOST_AUTO_TEST_CASE(test2dShifts) {
945 BOOST_TEST_MESSAGE("Testing 2d shifts");
946
947 SavedSettings backup;
948
949 ObservationMode::Mode backupMode = ObservationMode::instance().mode();
950 ObservationMode::instance().setMode(ObservationMode::Mode::None);
951
952 Date today = Date(14, April, 2016);
953 Settings::instance().evaluationDate() = today;
954
955 BOOST_TEST_MESSAGE("Today is " << today);
956
957 // build model
958 string baseCcy = "EUR";
959 vector<string> ccys;
960 ccys.push_back(baseCcy);
961 ccys.push_back("GBP");
962
963 // Init market
964 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
965
966 // build scenario sim market parameters
967 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
969
970 // sensitivity config
971 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = TestConfigurationObjects::setupSensitivityScenarioData2();
972
973 // build sim market
974 auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(initMarket, simMarketData);
975
976 // build scenario factory
977 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
978 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
979
980 // build scenario generator
981 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
982 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
983 scenarioFactory, false);
984
985 // cache initial zero rates
986 vector<Period> expiries = simMarketData->swapVolExpiries("");
987 vector<Period> terms = simMarketData->swapVolTerms("");
988 vector<vector<Real>> initialData(expiries.size(), vector<Real>(terms.size(), 0.0));
989 vector<Real> expiryTimes(expiries.size());
990 vector<Real> termTimes(terms.size());
991 string ccy = simMarketData->ccys()[0];
992 Handle<SwaptionVolatilityStructure> ts = initMarket->swaptionVol(ccy);
993 DayCounter dc = ts->dayCounter();
994 for (Size i = 0; i < expiries.size(); ++i)
995 expiryTimes[i] = dc.yearFraction(today, today + expiries[i]);
996 for (Size j = 0; j < terms.size(); ++j)
997 termTimes[j] = dc.yearFraction(today, today + terms[j]);
998 for (Size i = 0; i < expiries.size(); ++i) {
999 for (Size j = 0; j < terms.size(); ++j)
1000 initialData[i][j] = ts->volatility(expiries[i], terms[j], Null<Real>()); // ATM
1001 }
1002
1003 // apply shifts for tenors on the 2d shift grid
1004 // collect shifted data at tenors of the underlying 2d grid (different from the grid above)
1005 // aggregate "observed" shifts
1006 // compare to expected total shifts
1007 vector<Period> expiryShiftTenors = sensiData->swaptionVolShiftData()["EUR"].shiftExpiries;
1008 vector<Period> termShiftTenors = sensiData->swaptionVolShiftData()["EUR"].shiftTerms;
1009 vector<Real> shiftExpiryTimes(expiryShiftTenors.size());
1010 vector<Real> shiftTermTimes(termShiftTenors.size());
1011 for (Size i = 0; i < expiryShiftTenors.size(); ++i)
1012 shiftExpiryTimes[i] = dc.yearFraction(today, today + expiryShiftTenors[i]);
1013 for (Size j = 0; j < termShiftTenors.size(); ++j)
1014 shiftTermTimes[j] = dc.yearFraction(today, today + termShiftTenors[j]);
1015
1016 vector<vector<Real>> shiftedData(expiries.size(), vector<Real>(terms.size(), 0.0));
1017 vector<vector<Real>> diffAbsolute(expiries.size(), vector<Real>(terms.size(), 0.0));
1018 vector<vector<Real>> diffRelative(expiries.size(), vector<Real>(terms.size(), 0.0));
1019 Real shiftSize = 0.01; // arbitrary
1020 ShiftType shiftTypeAbsolute = ShiftType::Absolute;
1021 ShiftType shiftTypeRelative = ShiftType::Relative;
1022 for (Size i = 0; i < expiryShiftTenors.size(); ++i) {
1023 for (Size j = 0; j < termShiftTenors.size(); ++j) {
1024 scenarioGenerator->applyShift(i, j, shiftSize, true, shiftTypeAbsolute, shiftExpiryTimes, shiftTermTimes,
1025 expiryTimes, termTimes, initialData, shiftedData, true);
1026 for (Size k = 0; k < expiries.size(); ++k) {
1027 for (Size l = 0; l < terms.size(); ++l)
1028 diffAbsolute[k][l] += shiftedData[k][l] - initialData[k][l];
1029 }
1030 scenarioGenerator->applyShift(i, j, shiftSize, true, shiftTypeRelative, shiftExpiryTimes, shiftTermTimes,
1031 expiryTimes, termTimes, initialData, shiftedData, true);
1032 for (Size k = 0; k < expiries.size(); ++k) {
1033 for (Size l = 0; l < terms.size(); ++l)
1034 diffRelative[k][l] += shiftedData[k][l] / initialData[k][l] - 1.0;
1035 }
1036 }
1037 }
1038
1039 Real tolerance = 1.0e-10;
1040 for (Size k = 0; k < expiries.size(); ++k) {
1041 for (Size l = 0; l < terms.size(); ++l) {
1042 // BOOST_TEST_MESSAGE("2d shift: checking sensitivity to underlying grid point (" << k << ", " << l << "): "
1043 // << diff[k][l]);
1044 BOOST_CHECK_MESSAGE(fabs(diffAbsolute[k][l] - shiftSize) < tolerance,
1045 "inconsistency in absolute 2d shifts at grid point (" << k << ", " << l
1046 << "): " << diffAbsolute[k][l]);
1047 BOOST_CHECK_MESSAGE(fabs(diffRelative[k][l] - shiftSize) < tolerance,
1048 "inconsistency in relative 2d shifts at grid point (" << k << ", " << l
1049 << "): " << diffRelative[k][l]);
1050 }
1051 }
1052 ObservationMode::instance().setMode(backupMode);
1053 IndexManager::instance().clearHistories();
1054}
1055
1056BOOST_AUTO_TEST_CASE(testEquityOptionDeltaGamma) {
1057
1058 BOOST_TEST_MESSAGE("Testing Equity option sensitivities against QL analytic greeks");
1059
1060 ObservationMode::instance().setMode(ObservationMode::Mode::None);
1061
1062 Date today = Date(14, April, 2016);
1063 Settings::instance().evaluationDate() = today;
1064
1065 BOOST_TEST_MESSAGE("Today is " << today);
1066 // Init market
1067 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
1068
1069 // build scenario sim market parameters
1070 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
1072
1073 // sensitivity config
1074 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = TestConfigurationObjects::setupSensitivityScenarioData5();
1075
1076 map<string, SensitivityScenarioData::VolShiftData>& eqvs = sensiData->equityVolShiftData();
1077 for (auto& it : eqvs) {
1078 it.second.shiftSize = 0.0001; // want a smaller shift size than 1.0 to test the analytic sensitivities
1079 }
1080 map<string, SensitivityScenarioData::SpotShiftData>& eqs = sensiData->equityShiftData();
1081 for (auto& it : eqs) {
1082 it.second.shiftSize = 0.0001; // want a smaller shift size to test the analytic sensitivities
1083 }
1084
1085 // build sim market
1086 auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(initMarket, simMarketData);
1087
1088 // build scenario factory
1089 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
1090 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
1091
1092 // build scenario generator
1093 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
1094 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
1095 scenarioFactory, false);
1096 simMarket->scenarioGenerator() = scenarioGenerator;
1097
1098 // build portfolio
1099 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
1100 data->model("EquityForward") = "DiscountedCashflows";
1101 data->engine("EquityForward") = "DiscountingEquityForwardEngine";
1102 data->model("EquityOption") = "BlackScholesMerton";
1103 data->engine("EquityOption") = "AnalyticEuropeanEngine";
1104 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(data, simMarket);
1105
1106 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
1107 Size trnCount = 0;
1108 portfolio->add(buildEquityOption("Call_SP5", "Long", "Call", 2, "SP5", "USD", 2147.56, 1000));
1109 trnCount++;
1110 portfolio->add(buildEquityOption("Put_SP5", "Long", "Put", 2, "SP5", "USD", 2147.56, 1000));
1111 trnCount++;
1112 // portfolio->add(buildEquityForward("Fwd_SP5", "Long", 2, "SP5", "USD", 2147.56, 1000));
1113 // trnCount++;
1114 portfolio->add(buildEquityOption("Call_Luft", "Short", "Call", 2, "Lufthansa", "EUR", 12.75, 1000));
1115 trnCount++;
1116 portfolio->add(buildEquityOption("Put_Luft", "Short", "Put", 2, "Lufthansa", "EUR", 12.75, 1000));
1117 trnCount++;
1118 // portfolio->add(buildEquityForward("Fwd_Luft", "Short", 2, "Lufthansa", "EUR", 12.75, 1000));
1119 // trnCount++;
1120 portfolio->build(factory);
1121 BOOST_CHECK_EQUAL(portfolio->size(), trnCount);
1122
1123 struct AnalyticInfo {
1124 string id;
1125 string name;
1126 string npvCcy;
1127 Real spot;
1128 Real fx;
1129 Real baseNpv;
1130 Real qlNpv;
1131 Real delta;
1132 Real gamma;
1133 Real vega;
1134 Real rho;
1135 Real divRho;
1136 };
1137 map<string, AnalyticInfo> qlInfoMap;
1138 for (const auto& [tradeId, trade] : portfolio->trades()) {
1139 AnalyticInfo info;
1140 QuantLib::ext::shared_ptr<ore::data::EquityOption> eqoTrn = QuantLib::ext::dynamic_pointer_cast<ore::data::EquityOption>(trade);
1141 BOOST_CHECK(eqoTrn);
1142 info.id = tradeId;
1143 info.name = eqoTrn->equityName();
1144 info.npvCcy = trade->npvCurrency();
1145
1146 info.spot = initMarket->equitySpot(info.name)->value();
1147 string pair = info.npvCcy + simMarketData->baseCcy();
1148 info.fx = initMarket->fxRate(pair)->value();
1149 info.baseNpv = trade->instrument()->NPV() * info.fx;
1150 QuantLib::ext::shared_ptr<QuantLib::VanillaOption> qlOpt =
1151 QuantLib::ext::dynamic_pointer_cast<QuantLib::VanillaOption>(trade->instrument()->qlInstrument());
1152 BOOST_CHECK(qlOpt);
1153 Position::Type positionType = parsePositionType(eqoTrn->option().longShort());
1154 Real bsInd = (positionType == QuantLib::Position::Long ? 1.0 : -1.0);
1155 info.qlNpv = qlOpt->NPV() * eqoTrn->quantity() * bsInd;
1156 info.delta = qlOpt->delta() * eqoTrn->quantity() * bsInd;
1157 info.gamma = qlOpt->gamma() * eqoTrn->quantity() * bsInd;
1158 info.vega = qlOpt->vega() * eqoTrn->quantity() * bsInd;
1159 info.rho = qlOpt->rho() * eqoTrn->quantity() * bsInd;
1160 info.divRho = qlOpt->dividendRho() * eqoTrn->quantity() * bsInd;
1161 qlInfoMap[info.id] = info;
1162 }
1163
1164 bool recalibrateModels = true; // nothing to calibrate here
1165 QuantLib::ext::shared_ptr<SensitivityAnalysis> sa = QuantLib::ext::make_shared<SensitivityAnalysis>(
1166 portfolio, initMarket, Market::defaultConfiguration, data, simMarketData, sensiData, recalibrateModels);
1167 sa->generateSensitivities();
1168
1169 map<pair<string, string>, Real> deltaMap;
1170 map<pair<string, string>, Real> gammaMap;
1171 std::set<string> sensiTrades;
1172 for (auto [pid, p] : portfolio->trades()) {
1173 sensiTrades.insert(pid);
1174 for (const auto& f : sa->sensiCube()->factors()) {
1175 auto des = sa->sensiCube()->factorDescription(f);
1176 deltaMap[make_pair(pid, des)] = sa->sensiCube()->delta(pid, f);
1177 gammaMap[make_pair(pid, des)] = sa->sensiCube()->gamma(pid, f);
1178 }
1179 }
1180
1181 struct SensiResults {
1182 string id;
1183 Real baseNpv;
1184 Real discountDelta;
1185 Real ycDelta;
1186 Real equitySpotDelta;
1187 Real equityVolDelta;
1188 Real equitySpotGamma;
1189 };
1190
1191 Real epsilon = 1.e-15; // a small number
1192 string equitySpotStr = "EquitySpot";
1193 string equityVolStr = "EquityVolatility";
1194
1195 for (auto it : qlInfoMap) {
1196 string id = it.first;
1197 BOOST_CHECK(sensiTrades.find(id) != sensiTrades.end());
1198 AnalyticInfo qlInfo = it.second;
1199 SensiResults res = {string(""), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
1200 for (auto it2 : deltaMap) {
1201 pair<string, string> sensiKey = it2.first;
1202 string sensiTrnId = it2.first.first;
1203 if (sensiTrnId != id)
1204 continue;
1205 res.id = sensiTrnId;
1206 res.baseNpv = sa->sensiCube()->npv(sensiTrnId);
1207 string sensiId = it2.first.second;
1208 Real sensiVal = it2.second;
1209 if (std::fabs(sensiVal) < epsilon) // not interested in zero sensis
1210 continue;
1211 vector<string> tokens;
1212 boost::split(tokens, sensiId, boost::is_any_of("/-"));
1213 BOOST_CHECK(tokens.size() > 0);
1214 bool isEquitySpot = (tokens[0] == equitySpotStr);
1215 bool isEquityVol = (tokens[0] == equityVolStr);
1216 if (isEquitySpot) {
1217 BOOST_CHECK(tokens.size() > 2);
1218 bool hasGamma = (gammaMap.find(sensiKey) != gammaMap.end());
1219 BOOST_CHECK(hasGamma);
1220 Real gammaVal = 0.0;
1221 if (hasGamma) {
1222 gammaVal = gammaMap[sensiKey];
1223 }
1224 res.equitySpotDelta += sensiVal;
1225 res.equitySpotGamma += gammaVal;
1226 continue;
1227 } else if (isEquityVol) {
1228 BOOST_CHECK(tokens.size() > 2);
1229 res.equityVolDelta += sensiVal;
1230 continue;
1231 } else {
1232 continue;
1233 }
1234 }
1235
1236 Real bp = 1.e-4;
1237 Real tol = 0.5; // % relative tolerance
1238
1239 BOOST_TEST_MESSAGE("SA: id=" << res.id << ", npv=" << res.baseNpv << ", equitySpotDelta=" << res.equitySpotDelta
1240 << ", equityVolDelta=" << res.equityVolDelta
1241 << ", equitySpotGamma=" << res.equitySpotGamma);
1242 BOOST_TEST_MESSAGE("QL: id=" << qlInfo.id << ", fx=" << qlInfo.fx << ", npv=" << qlInfo.baseNpv
1243 << ", ccyNpv=" << qlInfo.qlNpv << ", delta=" << qlInfo.delta
1244 << ", gamma=" << qlInfo.gamma << ", vega=" << qlInfo.vega
1245 << ", spotDelta=" << (qlInfo.delta * qlInfo.fx * bp * qlInfo.spot));
1246
1247 Real eqVol =
1248 initMarket->equityVol(qlInfo.name)->blackVol(1.0, 1.0, true); // TO-DO more appropriate vol extraction
1249 BOOST_CHECK_CLOSE(res.equityVolDelta, qlInfo.vega * qlInfo.fx * (bp * eqVol), tol);
1250
1251 BOOST_CHECK_CLOSE(res.equitySpotDelta, qlInfo.delta * qlInfo.fx * (bp * qlInfo.spot), tol);
1252 BOOST_CHECK_CLOSE(res.equitySpotGamma, qlInfo.gamma * qlInfo.fx * (pow(bp * qlInfo.spot, 2)), tol);
1253 }
1254}
1255
1256BOOST_AUTO_TEST_CASE(testFxOptionDeltaGamma) {
1257
1258 BOOST_TEST_MESSAGE("Testing FX option sensitivities against QL analytic greeks");
1259
1260 SavedSettings backup;
1261
1262 ObservationMode::Mode backupMode = ObservationMode::instance().mode();
1263 ObservationMode::instance().setMode(ObservationMode::Mode::None);
1264
1265 Date today = Date(14, April, 2016); // Settings::instance().evaluationDate();
1266 Settings::instance().evaluationDate() = today;
1267
1268 BOOST_TEST_MESSAGE("Today is " << today);
1269
1270 // Init market
1271 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
1272
1273 // build scenario sim market parameters
1274 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
1276
1277 // sensitivity config
1278 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = TestConfigurationObjects::setupSensitivityScenarioData5();
1279
1280 map<string, SensitivityScenarioData::VolShiftData>& fxvs = sensiData->fxVolShiftData();
1281 for (auto& it : fxvs) {
1282 it.second.shiftSize = 0.0001; // want a smaller shift size than 1.0 to test the analytic sensitivities
1283 }
1284 map<string, SensitivityScenarioData::SpotShiftData>& fxs = sensiData->fxShiftData();
1285 for (auto& it : fxs) {
1286 it.second.shiftSize = 0.0001; // want a smaller shift size to test the analytic sensitivities
1287 }
1288
1289 // build sim market
1290 auto simMarket = QuantLib::ext::make_shared<ScenarioSimMarket>(initMarket, simMarketData);
1291
1292 // build scenario factory
1293 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
1294 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
1295
1296 // build scenario generator
1297 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
1298 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
1299 scenarioFactory, false);
1300 simMarket->scenarioGenerator() = scenarioGenerator;
1301
1302 // build portfolio
1303 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
1304 data->model("FxOption") = "GarmanKohlhagen";
1305 data->engine("FxOption") = "AnalyticEuropeanEngine";
1306 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(data, simMarket);
1307
1308 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
1309 Size trnCount = 0;
1310 portfolio->add(buildFxOption("Call_1", "Long", "Call", 1, "USD", 100000000.0, "EUR", 100000000.0));
1311 trnCount++;
1312 portfolio->add(buildFxOption("Put_1", "Long", "Put", 1, "USD", 100000000.0, "EUR", 100000000.0));
1313 trnCount++;
1314 portfolio->add(buildFxOption("Call_2", "Short", "Call", 2, "GBP", 100000000.0, "CHF", 130000000.0));
1315 trnCount++;
1316 portfolio->add(buildFxOption("Put_2", "Short", "Put", 2, "GBP", 100000000.0, "CHF", 130000000.0));
1317 trnCount++;
1318 portfolio->add(buildFxOption("Call_3", "Long", "Call", 1, "EUR", 100000000.0, "USD", 100000000.0));
1319 trnCount++;
1320 portfolio->add(buildFxOption("Put_3", "Short", "Put", 1, "EUR", 100000000.0, "USD", 100000000.0));
1321 trnCount++;
1322 portfolio->add(buildFxOption("Call_4", "Long", "Call", 1, "JPY", 10000000000.0, "EUR", 100000000.0));
1323 trnCount++;
1324 portfolio->add(buildFxOption("Call_5", "Long", "Call", 1, "EUR", 100000000.0, "JPY", 10000000000.0));
1325 trnCount++;
1326 portfolio->build(factory);
1327 BOOST_CHECK_EQUAL(portfolio->size(), trnCount);
1328
1329 struct AnalyticInfo {
1330 string id;
1331 string npvCcy;
1332 string forCcy;
1333 string domCcy;
1334 Real fx;
1335 Real trnFx;
1336 Real baseNpv;
1337 Real qlNpv;
1338 Real delta;
1339 Real gamma;
1340 Real vega;
1341 Real rho;
1342 Real divRho;
1343 Real fxForBase;
1344 };
1345 map<string, AnalyticInfo> qlInfoMap;
1346 for (const auto& [tradeId, trade] : portfolio->trades()) {
1347 AnalyticInfo info;
1348 QuantLib::ext::shared_ptr<ore::data::FxOption> fxoTrn = QuantLib::ext::dynamic_pointer_cast<ore::data::FxOption>(trade);
1349 BOOST_CHECK(fxoTrn);
1350 info.id = tradeId;
1351 info.npvCcy = trade->npvCurrency();
1352 info.forCcy = fxoTrn->boughtCurrency();
1353 info.domCcy = fxoTrn->soldCurrency();
1354 BOOST_CHECK_EQUAL(info.npvCcy, info.domCcy);
1355 string pair = info.npvCcy + simMarketData->baseCcy();
1356 info.fx = initMarket->fxRate(pair)->value();
1357 string trnPair = info.forCcy + info.domCcy;
1358 info.trnFx = initMarket->fxRate(trnPair)->value();
1359 string forPair = info.forCcy + simMarketData->baseCcy();
1360 info.fxForBase = initMarket->fxRate(forPair)->value();
1361 info.baseNpv = trade->instrument()->NPV() * info.fx;
1362 QuantLib::ext::shared_ptr<QuantLib::VanillaOption> qlOpt =
1363 QuantLib::ext::dynamic_pointer_cast<QuantLib::VanillaOption>(trade->instrument()->qlInstrument());
1364 BOOST_CHECK(qlOpt);
1365 Position::Type positionType = parsePositionType(fxoTrn->option().longShort());
1366 Real bsInd = (positionType == QuantLib::Position::Long ? 1.0 : -1.0);
1367 info.qlNpv = qlOpt->NPV() * fxoTrn->boughtAmount() * bsInd;
1368 info.delta = qlOpt->delta() * fxoTrn->boughtAmount() * bsInd;
1369 info.gamma = qlOpt->gamma() * fxoTrn->boughtAmount() * bsInd;
1370 info.vega = qlOpt->vega() * fxoTrn->boughtAmount() * bsInd;
1371 info.rho = qlOpt->rho() * fxoTrn->boughtAmount() * bsInd;
1372 info.divRho = qlOpt->dividendRho() * fxoTrn->boughtAmount() * bsInd;
1373 BOOST_CHECK_CLOSE(info.fx, info.baseNpv / info.qlNpv, 0.01);
1374 qlInfoMap[info.id] = info;
1375 }
1376
1377 bool recalibrateModels = true; // nothing to calibrate here
1378 bool useOriginalFxForBaseCcyConv = true; // convert sensi to EUR using original FX rate (not the shifted rate)
1379 QuantLib::ext::shared_ptr<SensitivityAnalysis> sa = QuantLib::ext::make_shared<SensitivityAnalysis>(
1380 portfolio, initMarket, Market::defaultConfiguration, data, simMarketData, sensiData, recalibrateModels, nullptr,
1381 nullptr, useOriginalFxForBaseCcyConv);
1382 sa->generateSensitivities();
1383
1384 map<pair<string, string>, Real> deltaMap;
1385 map<pair<string, string>, Real> gammaMap;
1386 std::set<string> sensiTrades;
1387 for (const auto& [pid, _] : portfolio->trades()) {
1388 sensiTrades.insert(pid);
1389 for (const auto& f : sa->sensiCube()->factors()) {
1390 auto des = sa->sensiCube()->factorDescription(f);
1391 deltaMap[make_pair(pid, des)] = sa->sensiCube()->delta(pid, f);
1392 gammaMap[make_pair(pid, des)] = sa->sensiCube()->gamma(pid, f);
1393 }
1394 }
1395
1396 struct SensiResults {
1397 string id;
1398 Real baseNpv;
1399 Real forDiscountDelta;
1400 Real forIndexDelta;
1401 Real forYcDelta;
1402 Real domDiscountDelta;
1403 Real domIndexDelta;
1404 Real domYcDelta;
1405 Real fxSpotDeltaFor;
1406 Real fxSpotDeltaDom;
1407 Real fxVolDelta;
1408 Real fxSpotGammaFor;
1409 Real fxSpotGammaDom;
1410 Real fxRateSensiFor;
1411 Real fxRateSensiDom;
1412 bool hasFxSpotDomSensi;
1413 bool hasFxSpotForSensi;
1414 string fxSensiForCcy;
1415 string fxSensiDomCcy;
1416 };
1417
1418 Real epsilon = 1.e-15; // a small number
1419 string discountCurveStr = "DiscountCurve";
1420 string indexCurveStr = "IndexCurve";
1421 string yieldCurveStr = "YieldCurve";
1422 string fxSpotStr = "FXSpot";
1423 string fxVolStr = "FXVolatility";
1424 string swaptionStr = "SwaptionVolatility";
1425 string capStr = "OptionletVolatility";
1426 for (auto it : qlInfoMap) {
1427 string id = it.first;
1428 BOOST_CHECK(sensiTrades.find(id) != sensiTrades.end());
1429 AnalyticInfo qlInfo = it.second;
1430 SensiResults res = {string(""), 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
1431 0.0, 0.0, 0.0, 0.0, 0.0, false, false, string(""), string("")};
1432 for (auto it2 : deltaMap) {
1433 pair<string, string> sensiKey = it2.first;
1434 string sensiTrnId = it2.first.first;
1435 if (sensiTrnId != id)
1436 continue;
1437 res.id = sensiTrnId;
1438 res.baseNpv = sa->sensiCube()->npv(sensiTrnId);
1439 string sensiId = it2.first.second;
1440 Real sensiVal = it2.second;
1441 if (std::fabs(sensiVal) < epsilon) // not interested in zero sensis
1442 continue;
1443 vector<string> tokens;
1444 boost::split(tokens, sensiId, boost::is_any_of("/-"));
1445 BOOST_CHECK(tokens.size() > 0);
1446 bool isDiscountCurve = (tokens[0] == discountCurveStr);
1447 bool isIndexCurve = (tokens[0] == indexCurveStr);
1448 bool isYieldCurve = (tokens[0] == yieldCurveStr);
1449 bool isFxSpot = (tokens[0] == fxSpotStr);
1450 bool isFxVol = (tokens[0] == fxVolStr);
1451 bool isSwaption = (tokens[0] == swaptionStr);
1452 bool isCapFloorlet = (tokens[0] == capStr);
1453 BOOST_CHECK(!(isSwaption || isCapFloorlet)); // no relation to fx options
1454 if (isDiscountCurve || isIndexCurve || isYieldCurve) {
1455 BOOST_CHECK(tokens.size() > 2);
1456 string ccy = tokens[1];
1457 bool isFgnCcySensi = (ccy == qlInfo.forCcy);
1458 bool isDomCcySensi = (ccy == qlInfo.domCcy);
1459 BOOST_CHECK(isFgnCcySensi || isDomCcySensi);
1460 if (isDiscountCurve) {
1461 if (isFgnCcySensi)
1462 res.forDiscountDelta += sensiVal;
1463 else if (isDomCcySensi)
1464 res.domDiscountDelta += sensiVal;
1465 } else if (isIndexCurve) {
1466 if (isFgnCcySensi)
1467 res.forIndexDelta += sensiVal;
1468 else if (isDomCcySensi)
1469 res.domIndexDelta += sensiVal;
1470 } else if (isYieldCurve) {
1471 if (isFgnCcySensi)
1472 res.forYcDelta += sensiVal;
1473 if (isDomCcySensi)
1474 res.domYcDelta += sensiVal;
1475 }
1476 continue;
1477 } else if (isFxSpot) {
1478 BOOST_CHECK(tokens.size() > 2);
1479 string pair = tokens[1];
1480 BOOST_CHECK_EQUAL(pair.length(), 6);
1481 string sensiForCcy = pair.substr(0, 3);
1482 string sensiDomCcy = pair.substr(3, 3);
1483 Real fxSensi = initMarket->fxRate(pair)->value();
1484 bool isSensiForBase = (sensiForCcy == simMarketData->baseCcy());
1485 bool isSensiDomBase = (sensiDomCcy == simMarketData->baseCcy());
1486 // TO-DO this could be relaxed to handle case where market stores the currency pairs the other way
1487 // around
1488 BOOST_CHECK(isSensiForBase && !isSensiDomBase);
1489 bool hasGamma = (gammaMap.find(sensiKey) != gammaMap.end());
1490 BOOST_CHECK(hasGamma);
1491 Real gammaVal = 0.0;
1492 if (hasGamma) {
1493 gammaVal = gammaMap[sensiKey];
1494 }
1495 if (isSensiForBase) {
1496 if (sensiDomCcy == qlInfo.forCcy) {
1497 res.fxSpotDeltaFor += sensiVal;
1498 res.fxRateSensiFor = fxSensi;
1499 res.hasFxSpotForSensi = true;
1500 res.fxSpotGammaFor += gammaVal;
1501 } else if (sensiDomCcy == qlInfo.domCcy) {
1502 res.fxSpotDeltaDom += sensiVal;
1503 res.fxRateSensiDom = fxSensi;
1504 res.hasFxSpotDomSensi = true;
1505 res.fxSpotGammaDom += gammaVal;
1506 }
1507 res.fxSensiForCcy = sensiForCcy;
1508 res.fxSensiDomCcy = sensiDomCcy;
1509 } else {
1510 BOOST_ERROR("This ccy pair configuration not supported yet by this test");
1511 }
1512 continue;
1513 } else if (isFxVol) {
1514 BOOST_CHECK(tokens.size() > 2);
1515 string pair = tokens[1];
1516 BOOST_CHECK_EQUAL(pair.length(), 6);
1517 string sensiForCcy = pair.substr(0, 3);
1518 string sensiDomCcy = pair.substr(3, 3);
1519 BOOST_CHECK((sensiForCcy == qlInfo.forCcy) || (sensiForCcy == qlInfo.domCcy));
1520 BOOST_CHECK((sensiDomCcy == qlInfo.forCcy) || (sensiDomCcy == qlInfo.domCcy));
1521 res.fxVolDelta += sensiVal;
1522 continue;
1523 } else {
1524 BOOST_ERROR("Unrecognised sensitivity factor - " << sensiId);
1525 }
1526 }
1527 // HERE COME THE ACTUAL SENSI COMPARISONS
1528 // index and yc sensis not expected
1529 BOOST_CHECK_EQUAL(res.forIndexDelta, 0.0);
1530 BOOST_CHECK_EQUAL(res.domIndexDelta, 0.0);
1531 BOOST_CHECK_EQUAL(res.forYcDelta, 0.0);
1532 BOOST_CHECK_EQUAL(res.domYcDelta, 0.0);
1533 BOOST_TEST_MESSAGE(
1534 "SA: id=" << res.id << ", npv=" << res.baseNpv << ", forDiscountDelta=" << res.forDiscountDelta
1535 << ", domDiscountDelta=" << res.domDiscountDelta << ", fxSpotDeltaFor=" << res.fxSpotDeltaFor
1536 << ", fxSpotDeltaDom=" << res.fxSpotDeltaDom << ", fxVolDelta=" << res.fxVolDelta
1537 << ", fxSpotGammaFor=" << res.fxSpotGammaFor << ", fxSpotGammaDom=" << res.fxSpotGammaDom
1538 << ", hasFxDom=" << res.hasFxSpotDomSensi << ", hasFxFor=" << res.hasFxSpotForSensi);
1539 BOOST_TEST_MESSAGE("QL: id=" << qlInfo.id << ", forCcy=" << qlInfo.forCcy << ", domCcy=" << qlInfo.domCcy
1540 << ", fx=" << qlInfo.fx << ", npv=" << qlInfo.baseNpv
1541 << ", ccyNpv=" << qlInfo.qlNpv << ", delta=" << qlInfo.delta
1542 << ", gamma=" << qlInfo.gamma << ", vega=" << qlInfo.vega << ", rho=" << qlInfo.rho
1543 << ", divRho=" << qlInfo.divRho);
1544 Real bp = 1.e-4;
1545 Real tol = 1.0; // % relative tolerance
1546 // rate sensis are 1bp absolute shifts
1547 // fx vol sensis are 1bp relative shifts
1548 // fx spot sensis are 1pb relative shifts
1549 BOOST_CHECK_CLOSE(res.domDiscountDelta, qlInfo.rho * qlInfo.fx * bp, tol);
1550 BOOST_CHECK_CLOSE(res.forDiscountDelta, qlInfo.divRho * qlInfo.fx * bp, tol);
1551 Real fxVol = initMarket->fxVol(qlInfo.forCcy + qlInfo.domCcy)
1552 ->blackVol(1.0, 1.0, true); // TO-DO more appropriate vol extraction
1553 BOOST_CHECK_CLOSE(res.fxVolDelta, qlInfo.vega * qlInfo.fx * (bp * fxVol), tol);
1554 if (res.hasFxSpotDomSensi) {
1555 Real qlGamma = qlInfo.gamma;
1556 if ((res.fxSensiForCcy == qlInfo.domCcy) && (res.fxSensiDomCcy == qlInfo.forCcy)) {
1557 // the QL sensi is relative to the inverted FX quote, so we need to convert to the sensi that we want
1558 // (via chain rule)
1559 Real ql_fx = qlInfo.trnFx;
1560 qlGamma = 2 * pow(ql_fx, 3) * qlInfo.delta + pow(ql_fx, 4) * qlInfo.gamma;
1561 } else if ((res.fxSensiForCcy == qlInfo.forCcy) && (res.fxSensiDomCcy == qlInfo.domCcy)) {
1562 qlGamma = qlInfo.gamma;
1563 } else {
1564 // perform the necessary conversion for cross quotes
1565 Real otherFx = 1.0 / qlInfo.fxForBase;
1566 qlGamma = qlInfo.gamma / pow(otherFx, 2);
1567 }
1568 BOOST_CHECK_CLOSE(res.fxSpotDeltaDom, qlInfo.delta * qlInfo.fx * (bp * qlInfo.trnFx), tol);
1569 BOOST_CHECK_CLOSE(res.fxSpotGammaDom, qlGamma * qlInfo.fx * (pow(bp * res.fxRateSensiDom, 2)), tol);
1570 }
1571 if (res.hasFxSpotForSensi) {
1572 Real qlGamma = qlInfo.gamma;
1573 if ((res.fxSensiForCcy == qlInfo.domCcy) && (res.fxSensiDomCcy == qlInfo.forCcy)) {
1574 // the QL sensi is relative to the inverted FX quote, so we need to convert to the sensi that we want
1575 // (via chain rule)
1576 Real ql_fx = qlInfo.trnFx;
1577 qlGamma = 2 * pow(ql_fx, 3) * qlInfo.delta + pow(ql_fx, 4) * qlInfo.gamma;
1578 } else if ((res.fxSensiForCcy == qlInfo.forCcy) && (res.fxSensiDomCcy == qlInfo.domCcy)) {
1579 qlGamma = qlInfo.gamma;
1580 } else {
1581 // perform the necessary conversion for cross quotes
1582 Real y = 1.0 / qlInfo.fx; // BASE/TrnDom
1583 Real z = 1.0 / qlInfo.fxForBase; // BASE/TrnFor
1584 qlGamma = ((2.0 * y) / pow(z, 3)) * qlInfo.delta + (y / pow(z, 4)) * qlInfo.gamma;
1585 }
1586 BOOST_CHECK_CLOSE(res.fxSpotDeltaFor, qlInfo.delta * qlInfo.fx * (-bp * qlInfo.trnFx), tol);
1587 BOOST_CHECK_CLOSE(res.fxSpotGammaFor, qlGamma * qlInfo.fx * (pow(-bp * res.fxRateSensiFor, 2)), tol);
1588 }
1589 }
1590 ObservationMode::instance().setMode(backupMode);
1591 IndexManager::instance().clearHistories();
1592}
1593
1594BOOST_AUTO_TEST_CASE(testCrossGamma) {
1595
1596 BOOST_TEST_MESSAGE("Testing cross-gamma sensitivities against cached results");
1597
1598 SavedSettings backup;
1599
1600 ObservationMode::Mode backupMode = ObservationMode::instance().mode();
1601 ObservationMode::instance().setMode(ObservationMode::Mode::None);
1602
1603 Date today = Date(14, April, 2016);
1604 Settings::instance().evaluationDate() = today;
1605
1606 BOOST_TEST_MESSAGE("Today is " << today);
1607
1608 // Init market
1609 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarket>(today);
1610
1611 // build scenario sim market parameters
1612 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarketParameters> simMarketData =
1614
1615 // sensitivity config
1616 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData = TestConfigurationObjects::setupSensitivityScenarioData5();
1617 vector<pair<string, string>>& cgFilter = sensiData->crossGammaFilter();
1618 BOOST_CHECK_EQUAL(cgFilter.size(), 0);
1619 cgFilter.push_back(pair<string, string>("DiscountCurve/EUR", "DiscountCurve/EUR"));
1620 cgFilter.push_back(pair<string, string>("DiscountCurve/EUR", "IndexCurve/EUR"));
1621 cgFilter.push_back(pair<string, string>("IndexCurve/EUR", "IndexCurve/EUR"));
1622 cgFilter.push_back(pair<string, string>("IndexCurve/USD", "IndexCurve/USD"));
1623 cgFilter.push_back(pair<string, string>("DiscountCurve/USD", "DiscountCurve/USD"));
1624 cgFilter.push_back(pair<string, string>("OptionletVolatility/EUR", "OptionletVolatility/EUR"));
1625 cgFilter.push_back(pair<string, string>("OptionletVolatility/EUR", "DiscountCurve/EUR"));
1626 cgFilter.push_back(pair<string, string>("OptionletVolatility/EUR", "DiscountCurve/USD"));
1627 cgFilter.push_back(pair<string, string>("OptionletVolatility/USD", "DiscountCurve/USD"));
1628 cgFilter.push_back(pair<string, string>("OptionletVolatility/USD", "OptionletVolatility/USD"));
1629 cgFilter.push_back(pair<string, string>("SwaptionVolatility/EUR", "SwaptionVolatility/EUR"));
1630 cgFilter.push_back(pair<string, string>("SwaptionVolatility/EUR", "IndexCurve/EUR"));
1631 cgFilter.push_back(pair<string, string>("SwaptionVolatility/EUR", "DiscountCurve/EUR"));
1632 cgFilter.push_back(pair<string, string>("FXVolatility/EURUSD", "DiscountCurve/EUR"));
1633 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "DiscountCurve/EUR"));
1634 cgFilter.push_back(pair<string, string>("FXSpot/EURUSD", "IndexCurve/EUR"));
1635 cgFilter.push_back(pair<string, string>("FXSpot/EURGBP", "DiscountCurve/GBP"));
1636
1637 // build scenario sim market
1638 QuantLib::ext::shared_ptr<analytics::ScenarioSimMarket> simMarket =
1639 QuantLib::ext::make_shared<analytics::ScenarioSimMarket>(initMarket, simMarketData);
1640
1641 // build scenario factory
1642 QuantLib::ext::shared_ptr<Scenario> baseScenario = simMarket->baseScenario();
1643 QuantLib::ext::shared_ptr<ScenarioFactory> scenarioFactory = QuantLib::ext::make_shared<CloneScenarioFactory>(baseScenario);
1644
1645 // build scenario generator
1646 QuantLib::ext::shared_ptr<SensitivityScenarioGenerator> scenarioGenerator =
1647 QuantLib::ext::make_shared<SensitivityScenarioGenerator>(sensiData, baseScenario, simMarketData, simMarket,
1648 scenarioFactory, false);
1649 simMarket->scenarioGenerator() = scenarioGenerator;
1650
1651 // build portfolio
1652 QuantLib::ext::shared_ptr<EngineData> data = QuantLib::ext::make_shared<EngineData>();
1653 data->model("Swap") = "DiscountedCashflows";
1654 data->engine("Swap") = "DiscountingSwapEngine";
1655 data->model("CrossCurrencySwap") = "DiscountedCashflows";
1656 data->engine("CrossCurrencySwap") = "DiscountingCrossCurrencySwapEngine";
1657 data->model("EuropeanSwaption") = "BlackBachelier";
1658 data->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
1659 data->model("BermudanSwaption") = "LGM";
1660 data->engine("BermudanSwaption") = "Grid";
1661 map<string, string> bermudanModelParams;
1662 bermudanModelParams["Calibration"] = "Bootstrap";
1663 bermudanModelParams["CalibrationStrategy"] = "Coterminal";
1664 bermudanModelParams["Reversion"] = "0.03";
1665 bermudanModelParams["ReversionType"] = "HullWhite";
1666 bermudanModelParams["Volatility"] = "0.01";
1667 bermudanModelParams["CalibrationType"] = "Hagan";
1668 bermudanModelParams["Tolerance"] = "0.0001";
1669 data->modelParameters("BermudanSwaption") = bermudanModelParams;
1670 map<string, string> bermudanEngineParams;
1671 bermudanEngineParams["sy"] = "3.0";
1672 bermudanEngineParams["ny"] = "10";
1673 bermudanEngineParams["sx"] = "3.0";
1674 bermudanEngineParams["nx"] = "10";
1675 data->engineParameters("BermudanSwaption") = bermudanEngineParams;
1676 data->model("FxForward") = "DiscountedCashflows";
1677 data->engine("FxForward") = "DiscountingFxForwardEngine";
1678 data->model("FxOption") = "GarmanKohlhagen";
1679 data->engine("FxOption") = "AnalyticEuropeanEngine";
1680 data->model("CapFloor") = "IborCapModel";
1681 data->engine("CapFloor") = "IborCapEngine";
1682 data->model("CapFlooredIborLeg") = "BlackOrBachelier";
1683 data->engine("CapFlooredIborLeg") = "BlackIborCouponPricer";
1684 QuantLib::ext::shared_ptr<EngineFactory> factory = QuantLib::ext::make_shared<EngineFactory>(data, simMarket);
1685
1686 // QuantLib::ext::shared_ptr<Portfolio> portfolio = buildSwapPortfolio(portfolioSize, factory);
1687 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
1688 Size trnCount = 0;
1689 portfolio->add(buildSwap("1_Swap_EUR", "EUR", true, 10000000.0, 0, 10, 0.03, 0.00, "1Y", "30/360", "6M", "A360",
1690 "EUR-EURIBOR-6M"));
1691 trnCount++;
1692 portfolio->add(buildSwap("2_Swap_USD", "USD", true, 10000000.0, 0, 15, 0.02, 0.00, "6M", "30/360", "3M", "A360",
1693 "USD-LIBOR-3M"));
1694 trnCount++;
1695 portfolio->add(buildSwap("3_Swap_GBP", "GBP", true, 10000000.0, 0, 20, 0.04, 0.00, "6M", "30/360", "3M", "A360",
1696 "GBP-LIBOR-6M"));
1697 trnCount++;
1698 portfolio->add(buildSwap("4_Swap_JPY", "JPY", true, 1000000000.0, 0, 5, 0.01, 0.00, "6M", "30/360", "3M", "A360",
1699 "JPY-LIBOR-6M"));
1700 trnCount++;
1701 portfolio->add(buildEuropeanSwaption("5_Swaption_EUR", "Long", "EUR", true, 1000000.0, 10, 10, 0.02, 0.00, "1Y",
1702 "30/360", "6M", "A360", "EUR-EURIBOR-6M", "Physical"));
1703 trnCount++;
1704 portfolio->add(buildEuropeanSwaption("6_Swaption_EUR", "Long", "EUR", true, 1000000.0, 2, 5, 0.02, 0.00, "1Y",
1705 "30/360", "6M", "A360", "EUR-EURIBOR-6M", "Physical"));
1706 trnCount++;
1707 portfolio->add(buildFxOption("7_FxOption_EUR_USD", "Long", "Call", 3, "EUR", 10000000.0, "USD", 11000000.0));
1708 trnCount++;
1709 portfolio->add(buildFxOption("8_FxOption_EUR_GBP", "Long", "Call", 7, "EUR", 10000000.0, "GBP", 11000000.0));
1710 trnCount++;
1711 portfolio->add(buildCap("9_Cap_EUR", "EUR", "Long", 0.05, 1000000.0, 0, 10, "6M", "A360", "EUR-EURIBOR-6M"));
1712 trnCount++;
1713 portfolio->add(buildFloor("10_Floor_USD", "USD", "Long", 0.01, 1000000.0, 0, 10, "3M", "A360", "USD-LIBOR-3M"));
1714 trnCount++;
1715 portfolio->build(factory);
1716 BOOST_CHECK_EQUAL(trnCount, portfolio->size());
1717
1718 bool useOriginalFxForBaseCcyConv = false;
1719 QuantLib::ext::shared_ptr<SensitivityAnalysis> sa =
1720 QuantLib::ext::make_shared<SensitivityAnalysis>(portfolio, initMarket, Market::defaultConfiguration, data,
1721 simMarketData, sensiData, useOriginalFxForBaseCcyConv);
1722 sa->generateSensitivities();
1723
1724 std::vector<ore::analytics::SensitivityScenarioGenerator::ScenarioDescription> scenDesc =
1725 sa->scenarioGenerator()->scenarioDescriptions();
1726
1727 struct GammaResult {
1728 string id;
1729 string factor1;
1730 string factor2;
1731 Real crossgamma;
1732 };
1733
1734 vector<GammaResult> cachedResults = {
1735 {"10_Floor_USD", "DiscountCurve/USD/1/1Y", "OptionletVolatility/USD/0/1Y/0.01", -1.14292006e-05},
1736 {"10_Floor_USD", "DiscountCurve/USD/1/1Y", "OptionletVolatility/USD/5/2Y/0.01", -4.75325714e-06},
1737 {"10_Floor_USD", "DiscountCurve/USD/2/2Y", "OptionletVolatility/USD/0/1Y/0.01", -5.72627955e-05},
1738 {"10_Floor_USD", "DiscountCurve/USD/2/2Y", "OptionletVolatility/USD/10/3Y/0.01", -6.0423848e-05},
1739 {"10_Floor_USD", "DiscountCurve/USD/2/2Y", "OptionletVolatility/USD/5/2Y/0.01", -0.0003282313},
1740 {"10_Floor_USD", "DiscountCurve/USD/3/3Y", "DiscountCurve/USD/4/5Y", 2.38844859e-06},
1741 {"10_Floor_USD", "DiscountCurve/USD/3/3Y", "OptionletVolatility/USD/10/3Y/0.01", -0.0032767365},
1742 {"10_Floor_USD", "DiscountCurve/USD/3/3Y", "OptionletVolatility/USD/15/5Y/0.01", -0.00124021334},
1743 {"10_Floor_USD", "DiscountCurve/USD/3/3Y", "OptionletVolatility/USD/5/2Y/0.01", -0.000490482465},
1744 {"10_Floor_USD", "DiscountCurve/USD/4/5Y", "DiscountCurve/USD/5/7Y", 4.56303869e-05},
1745 {"10_Floor_USD", "DiscountCurve/USD/4/5Y", "OptionletVolatility/USD/10/3Y/0.01", -0.00309734116},
1746 {"10_Floor_USD", "DiscountCurve/USD/4/5Y", "OptionletVolatility/USD/15/5Y/0.01", -0.0154732663},
1747 {"10_Floor_USD", "DiscountCurve/USD/4/5Y", "OptionletVolatility/USD/20/10Y/0.01", -0.0011774169},
1748 {"10_Floor_USD", "DiscountCurve/USD/4/5Y", "OptionletVolatility/USD/5/2Y/0.01", -1.15352532e-06},
1749 {"10_Floor_USD", "DiscountCurve/USD/5/7Y", "DiscountCurve/USD/6/10Y", 0.00024726356},
1750 {"10_Floor_USD", "DiscountCurve/USD/5/7Y", "OptionletVolatility/USD/10/3Y/0.01", -1.30253466e-06},
1751 {"10_Floor_USD", "DiscountCurve/USD/5/7Y", "OptionletVolatility/USD/15/5Y/0.01", -0.0325565983},
1752 {"10_Floor_USD", "DiscountCurve/USD/5/7Y", "OptionletVolatility/USD/20/10Y/0.01", -0.026175823},
1753 {"10_Floor_USD", "DiscountCurve/USD/6/10Y", "OptionletVolatility/USD/15/5Y/0.01", -0.0151532607},
1754 {"10_Floor_USD", "DiscountCurve/USD/6/10Y", "OptionletVolatility/USD/20/10Y/0.01", -0.0524224726},
1755 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/0/6M", "IndexCurve/USD-LIBOR-3M/1/1Y", -0.000206363102},
1756 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/0/6M", "IndexCurve/USD-LIBOR-3M/2/2Y", -9.83482187e-06},
1757 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/1/1Y", "IndexCurve/USD-LIBOR-3M/2/2Y", -0.0181056744},
1758 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/1/1Y", "IndexCurve/USD-LIBOR-3M/3/3Y", -0.000292001105},
1759 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/2/2Y", "IndexCurve/USD-LIBOR-3M/3/3Y", -0.197980608},
1760 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/2/2Y", "IndexCurve/USD-LIBOR-3M/4/5Y", -0.000472459871},
1761 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/3/3Y", "IndexCurve/USD-LIBOR-3M/4/5Y", -0.506924993},
1762 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/4/5Y", "IndexCurve/USD-LIBOR-3M/5/7Y", -1.31308851},
1763 {"10_Floor_USD", "IndexCurve/USD-LIBOR-3M/5/7Y", "IndexCurve/USD-LIBOR-3M/6/10Y", -1.79643202},
1764 {"10_Floor_USD", "OptionletVolatility/USD/0/1Y/0.01", "OptionletVolatility/USD/5/2Y/0.01", 0.0214845769},
1765 {"10_Floor_USD", "OptionletVolatility/USD/10/3Y/0.01", "OptionletVolatility/USD/15/5Y/0.01", 0.224709734},
1766 {"10_Floor_USD", "OptionletVolatility/USD/15/5Y/0.01", "OptionletVolatility/USD/20/10Y/0.01", 0.693920762},
1767 {"10_Floor_USD", "OptionletVolatility/USD/5/2Y/0.01", "OptionletVolatility/USD/10/3Y/0.01", 0.0649121282},
1768 {"1_Swap_EUR", "DiscountCurve/EUR/1/1Y", "DiscountCurve/EUR/2/2Y", 0.000439456664},
1769 {"1_Swap_EUR", "DiscountCurve/EUR/1/1Y", "IndexCurve/EUR-EURIBOR-6M/0/6M", 0.0488603441},
1770 {"1_Swap_EUR", "DiscountCurve/EUR/1/1Y", "IndexCurve/EUR-EURIBOR-6M/1/1Y", -0.0725961695},
1771 {"1_Swap_EUR", "DiscountCurve/EUR/1/1Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.0499326873},
1772 {"1_Swap_EUR", "DiscountCurve/EUR/2/2Y", "DiscountCurve/EUR/3/3Y", 0.00136525929},
1773 {"1_Swap_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/0/6M", 0.00108389393},
1774 {"1_Swap_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/1/1Y", 0.141865394},
1775 {"1_Swap_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.191425738},
1776 {"1_Swap_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.1454702},
1777 {"1_Swap_EUR", "DiscountCurve/EUR/3/3Y", "DiscountCurve/EUR/4/5Y", 0.00183080882},
1778 {"1_Swap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/1/1Y", 0.000784549396},
1779 {"1_Swap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", 0.425320865},
1780 {"1_Swap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.337527203},
1781 {"1_Swap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.560276813},
1782 {"1_Swap_EUR", "DiscountCurve/EUR/4/5Y", "DiscountCurve/EUR/5/7Y", -0.00376823638},
1783 {"1_Swap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", 0.000516382745},
1784 {"1_Swap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", 0.91807051},
1785 {"1_Swap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.606871969},
1786 {"1_Swap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -1.1789221},
1787 {"1_Swap_EUR", "DiscountCurve/EUR/5/7Y", "DiscountCurve/EUR/6/10Y", -0.0210602414},
1788 {"1_Swap_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", 1.93838247},
1789 {"1_Swap_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.964284878},
1790 {"1_Swap_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -2.50079601},
1791 {"1_Swap_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 3.43097423},
1792 {"1_Swap_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -4.9024972},
1793 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/0/6M", "IndexCurve/EUR-EURIBOR-6M/1/1Y", -0.048865166},
1794 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/0/6M", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.00108389556},
1795 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/1/1Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.0924553103},
1796 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/1/1Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.000784546835},
1797 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.281394335},
1798 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.000516386237},
1799 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.359848329},
1800 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/4/5Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.779536431},
1801 {"1_Swap_EUR", "IndexCurve/EUR-EURIBOR-6M/5/7Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.989040876},
1802 {"2_Swap_USD", "DiscountCurve/USD/0/6M", "DiscountCurve/USD/1/1Y", 7.85577577e-05},
1803 {"2_Swap_USD", "DiscountCurve/USD/1/1Y", "DiscountCurve/USD/2/2Y", 0.00034391915},
1804 {"2_Swap_USD", "DiscountCurve/USD/2/2Y", "DiscountCurve/USD/3/3Y", 0.00101750751},
1805 {"2_Swap_USD", "DiscountCurve/USD/3/3Y", "DiscountCurve/USD/4/5Y", 0.00129107304},
1806 {"2_Swap_USD", "DiscountCurve/USD/4/5Y", "DiscountCurve/USD/5/7Y", 0.00885138742},
1807 {"2_Swap_USD", "DiscountCurve/USD/5/7Y", "DiscountCurve/USD/6/10Y", 0.0236235501},
1808 {"2_Swap_USD", "DiscountCurve/USD/6/10Y", "DiscountCurve/USD/7/15Y", 0.07325946},
1809 {"2_Swap_USD", "DiscountCurve/USD/7/15Y", "DiscountCurve/USD/8/20Y", -2.22151866e-05},
1810 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/0/6M", "IndexCurve/USD-LIBOR-3M/1/1Y", -0.0202145245},
1811 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/0/6M", "IndexCurve/USD-LIBOR-3M/2/2Y", -0.000431735534},
1812 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/1/1Y", "IndexCurve/USD-LIBOR-3M/2/2Y", -0.0379707172},
1813 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/1/1Y", "IndexCurve/USD-LIBOR-3M/3/3Y", -0.000316063757},
1814 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/2/2Y", "IndexCurve/USD-LIBOR-3M/3/3Y", -0.11422779},
1815 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/2/2Y", "IndexCurve/USD-LIBOR-3M/4/5Y", -0.000207132776},
1816 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/3/3Y", "IndexCurve/USD-LIBOR-3M/4/5Y", -0.137591099},
1817 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/4/5Y", "IndexCurve/USD-LIBOR-3M/5/7Y", -0.305644142},
1818 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/5/7Y", "IndexCurve/USD-LIBOR-3M/6/10Y", -0.37816313},
1819 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/6/10Y", "IndexCurve/USD-LIBOR-3M/7/15Y", -0.431405343},
1820 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/6/10Y", "IndexCurve/USD-LIBOR-3M/8/20Y", -0.000289136427},
1821 {"2_Swap_USD", "IndexCurve/USD-LIBOR-3M/7/15Y", "IndexCurve/USD-LIBOR-3M/8/20Y", 0.00042894634},
1822 {"3_Swap_GBP", "DiscountCurve/GBP/0/6M", "FXSpot/EURGBP/0/spot", -0.0210289143},
1823 {"3_Swap_GBP", "DiscountCurve/GBP/1/1Y", "FXSpot/EURGBP/0/spot", 0.00639700286},
1824 {"3_Swap_GBP", "DiscountCurve/GBP/2/2Y", "FXSpot/EURGBP/0/spot", 0.0173332273},
1825 {"3_Swap_GBP", "DiscountCurve/GBP/3/3Y", "FXSpot/EURGBP/0/spot", 0.0420620699},
1826 {"3_Swap_GBP", "DiscountCurve/GBP/4/5Y", "FXSpot/EURGBP/0/spot", 0.0715365904},
1827 {"3_Swap_GBP", "DiscountCurve/GBP/5/7Y", "FXSpot/EURGBP/0/spot", 0.124046364},
1828 {"3_Swap_GBP", "DiscountCurve/GBP/6/10Y", "FXSpot/EURGBP/0/spot", 0.245374591},
1829 {"3_Swap_GBP", "DiscountCurve/GBP/7/15Y", "FXSpot/EURGBP/0/spot", 0.388570486},
1830 {"3_Swap_GBP", "DiscountCurve/GBP/8/20Y", "FXSpot/EURGBP/0/spot", -0.308991311},
1831 {"5_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "DiscountCurve/EUR/7/15Y", 0.00500290218},
1832 {"5_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "DiscountCurve/EUR/8/20Y", -0.000119650445},
1833 {"5_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", 0.193956982},
1834 {"5_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/7/15Y", -0.274626882},
1835 {"5_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/8/20Y", -0.0230959074},
1836 {"5_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "SwaptionVolatility/EUR/5/10Y/10Y/ATM", -0.0783525323},
1837 {"5_Swaption_EUR", "DiscountCurve/EUR/7/15Y", "DiscountCurve/EUR/8/20Y", 0.00909222141},
1838 {"5_Swaption_EUR", "DiscountCurve/EUR/7/15Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", 0.318897412},
1839 {"5_Swaption_EUR", "DiscountCurve/EUR/7/15Y", "IndexCurve/EUR-EURIBOR-6M/7/15Y", -0.113123194},
1840 {"5_Swaption_EUR", "DiscountCurve/EUR/7/15Y", "IndexCurve/EUR-EURIBOR-6M/8/20Y", -0.492342945},
1841 {"5_Swaption_EUR", "DiscountCurve/EUR/7/15Y", "SwaptionVolatility/EUR/5/10Y/10Y/ATM", -0.277872723},
1842 {"5_Swaption_EUR", "DiscountCurve/EUR/8/20Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.0231524316},
1843 {"5_Swaption_EUR", "DiscountCurve/EUR/8/20Y", "IndexCurve/EUR-EURIBOR-6M/7/15Y", 0.586686233},
1844 {"5_Swaption_EUR", "DiscountCurve/EUR/8/20Y", "IndexCurve/EUR-EURIBOR-6M/8/20Y", -0.741062084},
1845 {"5_Swaption_EUR", "DiscountCurve/EUR/8/20Y", "SwaptionVolatility/EUR/5/10Y/10Y/ATM", -0.207022576},
1846 {"5_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/6/10Y", "IndexCurve/EUR-EURIBOR-6M/7/15Y", -0.438748346},
1847 {"5_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/6/10Y", "IndexCurve/EUR-EURIBOR-6M/8/20Y", -4.80598188},
1848 {"5_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/6/10Y", "SwaptionVolatility/EUR/5/10Y/10Y/ATM", 0.0374673201},
1849 {"5_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/7/15Y", "IndexCurve/EUR-EURIBOR-6M/8/20Y", 0.578274874},
1850 {"5_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/7/15Y", "SwaptionVolatility/EUR/5/10Y/10Y/ATM", -0.00750543873},
1851 {"5_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/8/20Y", "SwaptionVolatility/EUR/5/10Y/10Y/ATM", -0.134678679},
1852 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "DiscountCurve/EUR/3/3Y", 7.34225287e-05},
1853 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "DiscountCurve/EUR/4/5Y", -1.39672557e-06},
1854 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "DiscountCurve/EUR/5/7Y", -4.54013752e-05},
1855 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", 0.00762697723},
1856 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.00743193871},
1857 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.000253325068},
1858 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.0091003291},
1859 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -3.51917679e-05},
1860 {"6_Swaption_EUR", "DiscountCurve/EUR/2/2Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", 0.000131859928},
1861 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "DiscountCurve/EUR/4/5Y", 9.36521301e-05},
1862 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "DiscountCurve/EUR/5/7Y", 1.17673517e-06},
1863 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", 0.0217662195},
1864 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.0173020895},
1865 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.0288530865},
1866 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 0.000542137221},
1867 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.0105191516},
1868 {"6_Swaption_EUR", "DiscountCurve/EUR/3/3Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", -1.92268253e-05},
1869 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "DiscountCurve/EUR/5/7Y", 0.000380955356},
1870 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.000175687061},
1871 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", 0.0470703001},
1872 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.0309543681},
1873 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.0603712949},
1874 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", 3.56844794e-06},
1875 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.0194332275},
1876 {"6_Swaption_EUR", "DiscountCurve/EUR/4/5Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", -3.55200336e-05},
1877 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "DiscountCurve/EUR/6/10Y", -3.53218638e-06},
1878 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -0.00907584063},
1879 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", 0.000465011277},
1880 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", 0.100206381},
1881 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.110760564},
1882 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.000747127526},
1883 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.0212825534},
1884 {"6_Swaption_EUR", "DiscountCurve/EUR/5/7Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", -3.89078705e-05},
1885 {"6_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -7.04072845e-05},
1886 {"6_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", 2.90610478e-06},
1887 {"6_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", 0.00015803353},
1888 {"6_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 1.87784499e-05},
1889 {"6_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -2.49396362e-06},
1890 {"6_Swaption_EUR", "DiscountCurve/EUR/6/10Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -5.68973592e-05},
1891 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.0374868064},
1892 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.0510088999},
1893 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -1.83061212},
1894 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.00707882478},
1895 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", 0.0237742927},
1896 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", 4.3887334e-05},
1897 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.0162251326},
1898 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 0.0753026757},
1899 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", 0.000291552333},
1900 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.00109766971},
1901 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", -2.02629781e-06},
1902 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/4/5Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 0.126414823},
1903 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/4/5Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", 0.000493449001},
1904 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/4/5Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.00244118512},
1905 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/4/5Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", -4.50652442e-06},
1906 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/5/7Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", 0.0233867156},
1907 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/5/7Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.116493942},
1908 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/5/7Y", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", -0.000215046299},
1909 {"6_Swaption_EUR", "IndexCurve/EUR-EURIBOR-6M/6/10Y", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", -0.000336383262},
1910 {"6_Swaption_EUR", "SwaptionVolatility/EUR/0/2Y/5Y/ATM", "SwaptionVolatility/EUR/2/5Y/5Y/ATM", 2.31331433e-06},
1911 {"7_FxOption_EUR_USD", "DiscountCurve/EUR/3/3Y", "DiscountCurve/EUR/4/5Y", 0.0027612336},
1912 {"7_FxOption_EUR_USD", "DiscountCurve/EUR/3/3Y", "FXSpot/EURUSD/0/spot", -42.4452352},
1913 {"7_FxOption_EUR_USD", "DiscountCurve/EUR/3/3Y", "FXVolatility/EURUSD/0/5Y/ATM", 168.577072},
1914 {"7_FxOption_EUR_USD", "DiscountCurve/EUR/4/5Y", "FXSpot/EURUSD/0/spot", -0.0776202832},
1915 {"7_FxOption_EUR_USD", "DiscountCurve/EUR/4/5Y", "FXVolatility/EURUSD/0/5Y/ATM", 0.308961544},
1916 {"7_FxOption_EUR_USD", "DiscountCurve/USD/3/3Y", "DiscountCurve/USD/4/5Y", 0.00206353236},
1917 {"8_FxOption_EUR_GBP", "DiscountCurve/GBP/5/7Y", "FXSpot/EURGBP/0/spot", 40.247185},
1918 {"9_Cap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", 1.89362237e-06},
1919 {"9_Cap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", 1.60204674e-05},
1920 {"9_Cap_EUR", "DiscountCurve/EUR/3/3Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -3.54807444e-05},
1921 {"9_Cap_EUR", "DiscountCurve/EUR/3/3Y", "OptionletVolatility/EUR/14/3Y/0.05", -7.41440071e-05},
1922 {"9_Cap_EUR", "DiscountCurve/EUR/3/3Y", "OptionletVolatility/EUR/19/5Y/0.05", -2.8717396e-05},
1923 {"9_Cap_EUR", "DiscountCurve/EUR/3/3Y", "OptionletVolatility/EUR/9/2Y/0.05", -3.95373826e-06},
1924 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "DiscountCurve/EUR/5/7Y", 1.87918619e-06},
1925 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", 0.000141954676},
1926 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", 0.000136532169},
1927 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.000558091084},
1928 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "OptionletVolatility/EUR/14/3Y/0.05", -0.000195855626},
1929 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "OptionletVolatility/EUR/19/5Y/0.05", -0.0013501175},
1930 {"9_Cap_EUR", "DiscountCurve/EUR/4/5Y", "OptionletVolatility/EUR/24/10Y/0.05", -9.03819837e-05},
1931 {"9_Cap_EUR", "DiscountCurve/EUR/5/7Y", "DiscountCurve/EUR/6/10Y", 2.44087892e-05},
1932 {"9_Cap_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", 0.00131097735},
1933 {"9_Cap_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 0.000537751659},
1934 {"9_Cap_EUR", "DiscountCurve/EUR/5/7Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.00376190752},
1935 {"9_Cap_EUR", "DiscountCurve/EUR/5/7Y", "OptionletVolatility/EUR/19/5Y/0.05", -0.00650057233},
1936 {"9_Cap_EUR", "DiscountCurve/EUR/5/7Y", "OptionletVolatility/EUR/24/10Y/0.05", -0.00529335126},
1937 {"9_Cap_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", 0.00677440175},
1938 {"9_Cap_EUR", "DiscountCurve/EUR/6/10Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.0101355366},
1939 {"9_Cap_EUR", "DiscountCurve/EUR/6/10Y", "OptionletVolatility/EUR/19/5Y/0.05", -0.00512368197},
1940 {"9_Cap_EUR", "DiscountCurve/EUR/6/10Y", "OptionletVolatility/EUR/24/10Y/0.05", -0.0166702108},
1941 {"9_Cap_EUR", "IndexCurve/EUR-EURIBOR-6M/1/1Y", "IndexCurve/EUR-EURIBOR-6M/2/2Y", -3.22099407e-06},
1942 {"9_Cap_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/3/3Y", -0.00114858136},
1943 {"9_Cap_EUR", "IndexCurve/EUR-EURIBOR-6M/2/2Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -3.32910605e-06},
1944 {"9_Cap_EUR", "IndexCurve/EUR-EURIBOR-6M/3/3Y", "IndexCurve/EUR-EURIBOR-6M/4/5Y", -0.0325351415},
1945 {"9_Cap_EUR", "IndexCurve/EUR-EURIBOR-6M/4/5Y", "IndexCurve/EUR-EURIBOR-6M/5/7Y", -0.22049032},
1946 {"9_Cap_EUR", "IndexCurve/EUR-EURIBOR-6M/5/7Y", "IndexCurve/EUR-EURIBOR-6M/6/10Y", -0.599739496},
1947 {"9_Cap_EUR", "OptionletVolatility/EUR/14/3Y/0.05", "OptionletVolatility/EUR/19/5Y/0.05", 0.0480747768},
1948 {"9_Cap_EUR", "OptionletVolatility/EUR/19/5Y/0.05", "OptionletVolatility/EUR/24/10Y/0.05", 0.670249341},
1949 {"9_Cap_EUR", "OptionletVolatility/EUR/4/1Y/0.05", "OptionletVolatility/EUR/9/2Y/0.05", 2.49049523e-05},
1950 {"9_Cap_EUR", "OptionletVolatility/EUR/9/2Y/0.05", "OptionletVolatility/EUR/14/3Y/0.05", 0.00180372518}};
1951
1952 map<tuple<string, string, string>, Real> cachedMap;
1953 for (Size i = 0; i < cachedResults.size(); ++i) {
1954 tuple<string, string, string> p(cachedResults[i].id, cachedResults[i].factor1, cachedResults[i].factor2);
1955 cachedMap[p] = cachedResults[i].crossgamma;
1956 }
1957
1958 vector<tuple<string, string, string>> ids;
1959 Real rel_tol = 0.005;
1960 Real threshold = 1.e-6;
1961 Size count = 0;
1962 for (const auto& [tradeId, _] : portfolio->trades()) {
1963 for (auto const& s : scenDesc) {
1964 if (s.type() == ShiftScenarioGenerator::ScenarioDescription::Type::Cross) {
1965 string factor1 = s.factor1();
1966 string factor2 = s.factor2();
1967 ostringstream os;
1968 os << tradeId << "_" << factor1 << "_" << factor2;
1969 string keyStr = os.str();
1970 tuple<string, string, string> key = make_tuple(tradeId, factor1, factor2);
1971 Real crossgamma = sa->sensiCube()->crossGamma(tradeId, make_pair(s.key1(), s.key2()));
1972 if (fabs(crossgamma) >= threshold) {
1973 ids.push_back(make_tuple(tradeId, factor1, factor2));
1974 // BOOST_TEST_MESSAGE("{ \"" << id << std::setprecision(9) << "\", \"" << factor1 << "\", \"" <<
1975 // factor2 <<
1976 // "\", " << crossgamma << " },");
1977 auto cached_it = cachedMap.find(key);
1978 BOOST_CHECK_MESSAGE(cached_it != cachedMap.end(), keyStr << " not found in cached results");
1979 if (cached_it != cachedMap.end()) {
1980 Real cached_cg = cached_it->second;
1981 BOOST_CHECK_CLOSE(crossgamma, cached_cg, rel_tol);
1982 count++;
1983 }
1984 }
1985 }
1986 }
1987 }
1988 BOOST_TEST_MESSAGE("number of cross-gammas checked = " << count);
1989 BOOST_CHECK_MESSAGE(count == cachedResults.size(), "number of non-zero sensitivities ("
1990 << count << ") do not match regression data ("
1991 << cachedResults.size() << ")");
1992 ObservationMode::instance().setMode(backupMode);
1993 IndexManager::instance().clearHistories();
1994}
1995
1996BOOST_AUTO_TEST_SUITE_END()
1997
1998BOOST_AUTO_TEST_SUITE_END()
static const string defaultConfiguration
OREAnalytics Top level fixture.
Static class to allow for easy construction of configuration objects for use within tests.
Definition: testmarket.hpp:222
static QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > setupSimMarketData2()
ScenarioSimMarketParameters instance, 2 currencies.
static QuantLib::ext::shared_ptr< ore::analytics::SensitivityScenarioData > setupSensitivityScenarioData2()
SensitivityScenarioData instance, 2 currencies.
static QuantLib::ext::shared_ptr< ore::analytics::SensitivityScenarioData > setupSensitivityScenarioData5()
SensitivityScenarioData instance, 5 currencies.
static QuantLib::ext::shared_ptr< ore::analytics::SensitivityScenarioData > setupSensitivityScenarioData2b()
SensitivityScenarioData instance, 2 currencies, shifts more granular than base curve.
static QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > setupSimMarketData5()
ScenarioSimMarketParameters instance, 5 currencies.
Simple flat market setup to be used in the test suite.
Definition: testmarket.hpp:64
factory class for cloning a cached scenario
Class that wraps a sensitivity stream and filters out negligible records.
Position::Type parsePositionType(const string &s)
A cube implementation that stores the cube in memory.
data
RandomVariable pow(RandomVariable x, const RandomVariable &y)
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 > buildCPIInflationSwap(string id, string ccy, bool isPayer, Real notional, int start, Size term, Real spread, string floatFreq, string floatDC, string index, string cpiFreq, string cpiDC, string cpiIndex, Real baseRate, string observationLag, bool interpolated, Real cpiRate)
QuantLib::ext::shared_ptr< Trade > buildZeroBond(string id, string ccy, Real notional, Size term, string suffix)
QuantLib::ext::shared_ptr< Trade > buildBermudanSwaption(string id, string longShort, string ccy, bool isPayer, Real notional, Size exercises, 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)
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 > buildYYInflationSwap(string id, string ccy, bool isPayer, Real notional, int start, Size term, Real spread, string floatFreq, string floatDC, string index, string yyFreq, string yyDC, string yyIndex, string observationLag, Size fixDays)
QuantLib::ext::shared_ptr< Trade > buildCommodityForward(const std::string &id, const std::string &position, Size term, const std::string &commodityName, const std::string &currency, Real strike, Real quantity)
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)
QuantLib::ext::shared_ptr< Trade > buildCommodityOption(const string &id, const string &longShort, const string &putCall, Size term, const string &commodityName, const string &currency, Real strike, Real quantity, Real premium, const string &premiumCcy, const string &premiumDate)
Singleton class to hold global Observation Mode.
Fixture that can be used at top level of OREAnalytics test suites.
std::size_t count
Perform parametric var calculation for a given portfolio.
risk class and type filter
A Market class that can be updated by Scenarios.
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.
Struct for holding a sensitivity record.
Sensitivity scenario generation.
Base class for sensitivity record streamer.
perform a stress testing analysis for a given portfolio.
void test1dShifts(bool granular)
BOOST_AUTO_TEST_CASE(testPortfolioSensitivityNoneObs)
string name
The counterparty cube calculator interface.
The cube valuation core.