Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Static Public Member Functions | List of all members
ParSensitivityAnalysisManualTest Class Reference

Par sensitivity analysis comparison against manual bump. More...

#include <test/parsensitivityanalysismanual.hpp>

+ Collaboration diagram for ParSensitivityAnalysisManualTest:

Static Public Member Functions

static void testParSwapBenchmark ()
 Benchmark par conversion against brute-force bump on the par instruments ("None" observation mode) More...
 
static boost::unit_test_framework::test_suite * suite ()
 

Detailed Description

Par sensitivity analysis comparison against manual bump.

Definition at line 33 of file parsensitivityanalysismanual.hpp.

Member Function Documentation

◆ testParSwapBenchmark()

void testParSwapBenchmark ( )
static

Benchmark par conversion against brute-force bump on the par instruments ("None" observation mode)

Definition at line 171 of file parsensitivityanalysismanual.cpp.

171 {
172
173 BOOST_TEST_MESSAGE("Testing swap par sensitivities against manual bump of par curve instruments");
174 SavedSettings backup;
175
176 ObservationMode::Mode backupMode = ObservationMode::instance().mode();
177 ObservationMode::Mode om = ObservationMode::Mode::None;
178 ObservationMode::instance().setMode(om);
179
180 Date today = Date(14, April, 2016); // Settings::instance().evaluationDate();
181 Settings::instance().evaluationDate() = today;
182 BOOST_TEST_MESSAGE("Today is " << today);
183
184 // build model
185 string baseCcy = "EUR";
186 vector<string> ccys;
187 ccys.push_back(baseCcy);
188 ccys.push_back("GBP");
189 ccys.push_back("CHF");
190 ccys.push_back("USD");
191 ccys.push_back("JPY");
192
193 // Init market
194 QuantLib::ext::shared_ptr<Market> initMarket = QuantLib::ext::make_shared<TestMarketParCurves>(today);
195
196 // build scenario sim market parameters
197 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarketParameters> simMarketData =
199
200 // sensitivity config
201 QuantLib::ext::shared_ptr<SensitivityScenarioData> sensiData =
203 // build porfolio
204 QuantLib::ext::shared_ptr<EngineData> engineData = QuantLib::ext::make_shared<EngineData>();
205 engineData->model("Swap") = "DiscountedCashflows";
206 engineData->engine("Swap") = "DiscountingSwapEngine";
207 engineData->model("CrossCurrencySwap") = "DiscountedCashflows";
208 engineData->engine("CrossCurrencySwap") = "DiscountingCrossCurrencySwapEngine";
209 engineData->model("EuropeanSwaption") = "BlackBachelier";
210 engineData->engine("EuropeanSwaption") = "BlackBachelierSwaptionEngine";
211 engineData->model("FxForward") = "DiscountedCashflows";
212 engineData->engine("FxForward") = "DiscountingFxForwardEngine";
213 engineData->model("FxOption") = "GarmanKohlhagen";
214 engineData->engine("FxOption") = "AnalyticEuropeanEngine";
215 engineData->model("CapFloor") = "IborCapModel";
216 engineData->engine("CapFloor") = "IborCapEngine";
217 engineData->model("CapFlooredIborLeg") = "BlackOrBachelier";
218 engineData->engine("CapFlooredIborLeg") = "BlackIborCouponPricer";
219 engineData->model("CreditDefaultSwap") = "DiscountedCashflows";
220 engineData->engine("CreditDefaultSwap") = "MidPointCdsEngine";
221
222 engineData->model("IndexCreditDefaultSwapOption") = "Black";
223 engineData->engine("IndexCreditDefaultSwapOption") = "BlackIndexCdsOptionEngine";
224 map<string, string> engineParamMap1;
225 engineParamMap1["Curve"] = "Underlying";
226 engineData->engineParameters("IndexCreditDefaultSwapOption") = engineParamMap1;
227
228 engineData->model("IndexCreditDefaultSwap") = "DiscountedCashflows";
229 engineData->engine("IndexCreditDefaultSwap") = "MidPointIndexCdsEngine";
230 map<string, string> engineParamMap2;
231 engineParamMap2["Curve"] = "Underlying";
232 engineData->engineParameters("IndexCreditDefaultSwap") = engineParamMap2;
233
234 engineData->model("CMS") = "LinearTSR";
235 engineData->engine("CMS") = "LinearTSRPricer";
236 map<string, string> engineparams;
237 engineparams["MeanReversion"] = "0.0";
238 engineparams["Policy"] = "RateBound";
239 engineparams["LowerRateBoundNormal"] = "-2.0000";
240 engineparams["UpperRateBoundNormal"] = "2.0000";
241 engineData->engineParameters("CMS") = engineparams;
242 engineData->model("SyntheticCDO") = "GaussCopula";
243 engineData->engine("SyntheticCDO") = "Bucketing";
244 map<string, string> modelParamMap3;
245 map<string, string> engineParamMap3;
246 modelParamMap3["correlation"] = "0.0";
247 modelParamMap3["min"] = "-5.0";
248 modelParamMap3["max"] = "5.0";
249 modelParamMap3["steps"] = "64";
250 engineParamMap3["buckets"] = "200";
251 engineParamMap3["homogeneousPoolWhenJustified"] = "N";
252 engineData->modelParameters("SyntheticCDO") = modelParamMap3;
253 engineData->engineParameters("SyntheticCDO") = engineParamMap3;
254
255 engineData->model("EquityOption") = "BlackScholesMerton";
256 engineData->engine("EquityOption") = "AnalyticEuropeanEngine";
257
258 std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> builders;
259 // builders.push_back(QuantLib::ext::make_shared<oreplus::data::MidPointIndexCdsEngineBuilder>());
260 // builders.push_back(QuantLib::ext::make_shared<oreplus::data::BlackIndexCdsOptionEngineBuilder>());
261 builders.push_back(QuantLib::ext::make_shared<ore::data::GaussCopulaBucketingCdoEngineBuilder>());
262
263 QuantLib::ext::shared_ptr<EngineFactory> factory = registerBuilders(engineData, initMarket);
264 QuantLib::ext::shared_ptr<Portfolio> portfolio(new Portfolio());
265 QuantLib::ext::shared_ptr<Conventions> conventions = InstrumentConventions::instance().conventions();
266 QuantLib::ext::shared_ptr<IRSwapConvention> eurConv =
267 QuantLib::ext::dynamic_pointer_cast<IRSwapConvention>(conventions->get("EUR-6M-SWAP-CONVENTIONS"));
268 string eurIdx = "EUR-EURIBOR-6M";
269 Period eurFloatTenor = initMarket->iborIndex(eurIdx)->tenor();
270 QuantLib::ext::shared_ptr<IRSwapConvention> usdConv =
271 QuantLib::ext::dynamic_pointer_cast<IRSwapConvention>(conventions->get("USD-6M-SWAP-CONVENTIONS"));
272 string usdIdx = "USD-LIBOR-6M";
273 Period usdFloatTenor = initMarket->iborIndex(usdIdx)->tenor();
274 QuantLib::ext::shared_ptr<IRSwapConvention> jpyConv =
275 QuantLib::ext::dynamic_pointer_cast<IRSwapConvention>(conventions->get("JPY-6M-SWAP-CONVENTIONS"));
276 string jpyIdx = "JPY-LIBOR-6M";
277 Period jpyFloatTenor = initMarket->iborIndex(jpyIdx)->tenor();
278 QuantLib::ext::shared_ptr<CrossCcyBasisSwapConvention> chfBasisConv =
279 QuantLib::ext::dynamic_pointer_cast<CrossCcyBasisSwapConvention>(conventions->get("CHF-XCCY-BASIS-CONVENTIONS"));
280 QuantLib::ext::shared_ptr<CdsConvention> cdsConv =
281 QuantLib::ext::dynamic_pointer_cast<CdsConvention>(conventions->get("CDS-STANDARD-CONVENTIONS"));
282
283 string chfIdx = chfBasisConv->spreadIndexName();
284 string otherIdx = chfBasisConv->flatIndexName();
285 Period chfFloatTenor = initMarket->iborIndex(chfIdx)->tenor();
286 Period otherFloatTenor = initMarket->iborIndex(otherIdx)->tenor();
287
288 portfolio->add(buildSwap(
289 "1_Swap_EUR", "EUR", true, 10000000.0, 0, 10, 0.02, 0.00,
290 ore::data::to_string(Period(eurConv->fixedFrequency())), ore::data::to_string(eurConv->fixedDayCounter()),
291 ore::data::to_string(eurFloatTenor), "A360", eurIdx, eurConv->fixedCalendar(),
292 initMarket->iborIndex(eurIdx)->fixingDays(), true));
293 portfolio->add(buildSwap(
294 "2_Swap_USD", "USD", true, 10000000.0, 0, 15, 0.03, 0.00,
295 ore::data::to_string(Period(usdConv->fixedFrequency())), ore::data::to_string(usdConv->fixedDayCounter()),
296 ore::data::to_string(usdFloatTenor), "A360", usdIdx, usdConv->fixedCalendar(),
297 initMarket->iborIndex(usdIdx)->fixingDays(), true));
298 portfolio->add(buildCap(
299 "9_Cap_EUR", "EUR", "Long", 0.02, 1000000.0, 0, 10, ore::data::to_string(eurFloatTenor), "A360", eurIdx,
300 eurConv->fixedCalendar(), initMarket->iborIndex(eurIdx)->fixingDays(), true));
301 portfolio->add(buildFloor(
302 "10_Floor_USD", "USD", "Long", 0.03, 1000000.0, 0, 10, ore::data::to_string(usdFloatTenor), "A360", usdIdx,
303 usdConv->fixedCalendar(), initMarket->iborIndex(usdIdx)->fixingDays(), true));
304 portfolio->add(buildSwap(
305 "3_Swap_EUR", "EUR", false, 10000000.0, 1, 12, 0.025, 0.00,
306 ore::data::to_string(Period(eurConv->fixedFrequency())), ore::data::to_string(eurConv->fixedDayCounter()),
307 ore::data::to_string(eurFloatTenor), "A360", eurIdx, eurConv->fixedCalendar(),
308 initMarket->iborIndex(eurIdx)->fixingDays(), true));
309 portfolio->add(buildCrossCcyBasisSwap(
310 "4_XCCY_SWAP", "CHF", 10000000, "EUR", 10000000, 0, 15, 0.0000, 0.0000, ore::data::to_string(chfFloatTenor),
311 "A360", chfIdx, chfBasisConv->settlementCalendar(), ore::data::to_string(otherFloatTenor), "A360", otherIdx,
312 chfBasisConv->settlementCalendar(), chfBasisConv->settlementDays(), true));
313 portfolio->add(buildCrossCcyBasisSwap(
314 "5_XCCY_SWAP_WithPrincipal", "CHF", 10000000, "EUR", 10000000, 0, 15, 0.0000, 0.0000,
315 ore::data::to_string(chfFloatTenor), "A360", chfIdx, chfBasisConv->settlementCalendar(),
316 ore::data::to_string(otherFloatTenor), "A360", otherIdx, chfBasisConv->settlementCalendar(),
317 chfBasisConv->settlementDays(), true, true, true, true, false));
318 portfolio->add(buildSwap(
319 "6_Swap_JPY", "JPY", true, 1000000000.0, 0, 10, 0.005, 0.00,
320 ore::data::to_string(Period(jpyConv->fixedFrequency())), ore::data::to_string(jpyConv->fixedDayCounter()),
321 ore::data::to_string(jpyFloatTenor), "A360", jpyIdx, jpyConv->fixedCalendar(),
322 initMarket->iborIndex(jpyIdx)->fixingDays(), true));
323 portfolio->add(buildCrossCcyBasisSwap(
324 "7_XCCY_SWAP_OffMarket", "EUR", 10000000, "CHF", 10500000, 0, 15, 0.0000, 0.0010,
325 ore::data::to_string(chfFloatTenor), "A360", chfIdx, chfBasisConv->settlementCalendar(),
326 ore::data::to_string(otherFloatTenor), "A360", otherIdx, chfBasisConv->settlementCalendar(),
327 chfBasisConv->settlementDays(), true));
328 portfolio->add(buildCrossCcyBasisSwap(
329 "8_XCCY_SWAP_RESET", "CHF", 10000000, "EUR", 10000000, 0, 15, 0.0000, 0.0000,
330 ore::data::to_string(chfFloatTenor), "A360", chfIdx, chfBasisConv->settlementCalendar(),
331 ore::data::to_string(otherFloatTenor), "A360", otherIdx, chfBasisConv->settlementCalendar(),
332 chfBasisConv->settlementDays(), true, true, true, false, false, true));
333 portfolio->add(buildCreditDefaultSwap("9_CDS_USD", "USD", "dc", "dc", true, 10000000, 0, 15, 0.4,
334 0.009, ore::data::to_string(Period(cdsConv->frequency())),
335 ore::data::to_string(cdsConv->dayCounter())));
336 portfolio->add(buildCreditDefaultSwap(
337 "9_CDS_EUR", "EUR", "dc2", "dc2", true, 10000000, 0, 15, 0.4, 0.009,
338 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
339 portfolio->add(buildCreditDefaultSwap(
340 "10_CDS_USD", "USD", "dc", "dc", true, 10000000, 0, 10, 0.4, 0.001,
341 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
342 portfolio->add(buildCreditDefaultSwap(
343 "10_CDS_EUR", "EUR", "dc2", "dc2", true, 10000000, 0, 10, 0.4, 0.001,
344 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
345 portfolio->add(buildCreditDefaultSwap(
346 "11_CDS_EUR", "EUR", "dc2", "dc2", true, 10000000, 0, 5, 0.4, 0.001,
347 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
348 portfolio->add(buildCreditDefaultSwap("11_CDS_USD", "USD", "dc", "dc", true, 10000000, 0, 5, 0.4,
349 0.001, ore::data::to_string(Period(cdsConv->frequency())),
350 ore::data::to_string(cdsConv->dayCounter())));
351 portfolio->add(buildCreditDefaultSwap("12_CDS_USD", "USD", "dc", "dc", true, 10000000, 0, 2, 0.4,
352 0.004, ore::data::to_string(Period(cdsConv->frequency())),
353 ore::data::to_string(cdsConv->dayCounter())));
354 portfolio->add(buildCreditDefaultSwap(
355 "12_CDS_EUR", "EUR", "dc2", "dc2", true, 10000000, 0, 2, 0.4, 0.001,
356 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
357 portfolio->add(buildCreditDefaultSwap(
358 "13_CDS_USD", "USD", "dc", "dc", true, 10000000, 0, 15, 0.4, 0.001,
359 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
360 portfolio->add(buildCreditDefaultSwap(
361 "13_CDS_EUR", "EUR", "dc2", "dc2", true, 10000000, 0, 15, 0.4, 0.001,
362 ore::data::to_string(Period(cdsConv->frequency())), ore::data::to_string(cdsConv->dayCounter())));
363
364 vector<string> names = {"dc", "dc2", "dc3"};
365 vector<string> indexCcys = {"USD", "EUR", "GBP"};
366 vector<Real> notionals = {3000000, 3000000, 3000000};
367 // portfolio->add(buildIndexCdsOption("14_IndexCDSOption_USD", "dc", names, "Long", "USD",
368 // indexCcys, true, notionals, notional, 1, 4,
369 // 0.4, 0.001,
370 // ore::data::to_string(Period(cdsConv->frequency())),
371 // ore::data::to_string(cdsConv->dayCounter()), "Physical"));
372
373 vector<string> names2(1, "dc2");
374 vector<string> indexCcys2(1, "EUR");
375 vector<Real> notionals2(1, 10000000.0);
376 // portfolio->add(buildIndexCdsOption("15_IndexCDSOption_EUR", "dc2", names2, "Long", "EUR",
377 // indexCcys2, true, notionals2, 10000000.0, 1, 4,
378 // 0.4, 0.001,
379 // ore::data::to_string(Period(cdsConv->frequency())),
380 // ore::data::to_string(cdsConv->dayCounter()), "Physical"));
381 portfolio->add(buildSyntheticCDO("16_SyntheticCDO_EUR", "dc2", names2, "Long", "EUR", indexCcys2,
382 true, notionals2, 1000000.0, 0, 5, 0.03, 0.01, "1Y", "30/360"));
383
384 portfolio->add(buildCmsCapFloor("17_CMS_EUR", "EUR", "EUR-CMS-30Y", true, 2000000, 0, 5, 0.0, 1,
385 0.0, ore::data::to_string(Period(eurConv->fixedFrequency())),
386 ore::data::to_string(eurConv->fixedDayCounter())));
387 portfolio->add(
388 buildEquityOption("18_EquityOption_SP5", "Long", "Call", 2, "SP5", "USD", 2147.56, 775));
389
390 portfolio->add(buildCPIInflationSwap("19_CPIInflationSwap_UKRPI", "GBP", true, 100000.0, 0, 10,
391 0.0, "6M", "ACT/ACT", "GBP-LIBOR-6M", "1Y", "ACT/ACT",
392 "UKRPI", 201.0, "2M", false, 0.005));
393 portfolio->add(buildYYInflationSwap("20_YoYInflationSwap_UKRPI", "GBP", true, 100000.0, 0, 10,
394 0.0, "1Y", "ACT/ACT", "GBP-LIBOR-6M", "1Y", "ACT/ACT",
395 "UKRPI", "2M", 2));
396
397 Size tradeCount = portfolio->size();
398 portfolio->build(factory);
399 BOOST_CHECK_MESSAGE(portfolio->size() == tradeCount,
400 "Some trades not built correctly," << portfolio->size() << " vs. " << tradeCount);
401 // build the sensitivity analysis object
402 QuantLib::ext::shared_ptr<SensitivityAnalysis> zeroAnalysis =
403 QuantLib::ext::make_shared<SensitivityAnalysis>(portfolio, initMarket, Market::defaultConfiguration, engineData,
404 simMarketData, sensiData,
405 false, nullptr, nullptr, false, nullptr);
406 ParSensitivityAnalysis parAnalysis(today, simMarketData, *sensiData, Market::defaultConfiguration);
407 parAnalysis.alignPillars();
408 zeroAnalysis->overrideTenors(true);
409 zeroAnalysis->generateSensitivities();
410 parAnalysis.computeParInstrumentSensitivities(zeroAnalysis->simMarket());
411 QuantLib::ext::shared_ptr<ParSensitivityConverter> parConverter =
412 QuantLib::ext::make_shared<ParSensitivityConverter>(parAnalysis.parSensitivities(), parAnalysis.shiftSizes());
413 QuantLib::ext::shared_ptr<SensitivityCube> sensiCube = zeroAnalysis->sensiCube();
414 ZeroToParCube parCube(sensiCube, parConverter);
415
416 std::map<std::pair<std::string, std::string>, Real> parDelta;
417 std::map<std::pair<std::string, std::string>, Real> zeroDelta;
418 map<string, Real> baseManualPv;
419 map<string, Real> basePv;
420 for (const auto& tradeId : portfolio->ids()) {
421 basePv[tradeId] = sensiCube->npv(tradeId);
422 for (const auto& f : sensiCube->factors()) {
423 string des = sensiCube->factorDescription(f);
424 zeroDelta[make_pair(tradeId, des)] = sensiCube->delta(tradeId, f);
425 }
426 // Fill the par deltas map
427 auto temp = parCube.parDeltas(tradeId);
428 for (const auto& kv : temp) {
429 string des = sensiCube->factorDescription(kv.first);
430 parDelta[make_pair(tradeId, des)] = kv.second;
431 }
432 }
433 QuantLib::ext::shared_ptr<EngineFactory> manualFactory = registerBuilders(engineData, initMarket);
434
435 portfolio->reset();
436 portfolio->build(manualFactory);
437
438 for (auto [tradeId, trade] : portfolio->trades()) {
439 Real fx = 1.0;
440 if (trade->npvCurrency() != "EUR") {
441 string ccyPair = trade->npvCurrency() + baseCcy;
442 fx = initMarket->fxRate(ccyPair)->value();
443 }
444 baseManualPv[tradeId] = fx * trade->instrument()->NPV();
445 Real tradeNotional = fx * trade->notional();
446 Real simMarketTol =
447 1.e-5 * tradeNotional; // tolerance for difference to sim market is 0.1bp upfront (should this be tightened?)
448
449 BOOST_TEST_MESSAGE("Base PV check for trade " << tradeId << "; got " << baseManualPv[tradeId]
450 << ", expected " << basePv[tradeId]);
451 BOOST_CHECK_MESSAGE(std::fabs(baseManualPv[tradeId] - basePv[tradeId]) < simMarketTol,
452 "Base PV check error for trade " << tradeId << "; got " << baseManualPv[tradeId]
453 << ", but expected " << basePv[tradeId]);
454 }
455
456 QuantLib::ext::shared_ptr<TestMarketParCurves> initParMarket = QuantLib::ext::dynamic_pointer_cast<TestMarketParCurves>(initMarket);
457 BOOST_ASSERT(initParMarket);
458 BOOST_TEST_MESSAGE("testing discount curve par sensis");
459 // the discount curve par sensis
460 for (auto d_it : initParMarket->discountRateHelpersInstMap()) {
461 string ccy = d_it.first;
462 Real shiftSize = zeroAnalysis->sensitivityData()->discountCurveShiftData()[ccy]->shiftSize;
463 ShiftType shiftType = zeroAnalysis->sensitivityData()->discountCurveShiftData()[ccy]->shiftType;
464 vector<Period> parTenorVec = initParMarket->discountRateHelperTenorsMap().find(ccy)->second;
465 vector<Handle<Quote>> parValVecBase = initParMarket->discountRateHelperValuesMap().find(ccy)->second;
466 vector<string> sensiLabels(parValVecBase.size());
467 for (Size i = 0; i < parValVecBase.size(); i++) {
468 sensiLabels[i] = "DiscountCurve/" + ccy + "/" + to_string(i) + "/" + to_string(parTenorVec[i]);
469 }
470 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
471 shiftSize, shiftType, parDelta, zeroDelta, basePv);
472 }
473 BOOST_TEST_MESSAGE("testing index curve par sensis");
474 // the index curve par sensis
475 for (auto d_it : initParMarket->indexCurveRateHelperInstMap()) {
476 string idxName = d_it.first;
477 BOOST_TEST_MESSAGE(idxName);
478 auto itr = zeroAnalysis->sensitivityData()->indexCurveShiftData().find(idxName);
479 if (itr == zeroAnalysis->sensitivityData()->indexCurveShiftData().end())
480 zeroAnalysis->sensitivityData()->indexCurveShiftData()[idxName] =
481 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftData>();
482 Real shiftSize = zeroAnalysis->sensitivityData()->indexCurveShiftData()[idxName]->shiftSize;
483 ShiftType shiftType = zeroAnalysis->sensitivityData()->indexCurveShiftData()[idxName]->shiftType;
484 vector<Period> parTenorVec = initParMarket->indexCurveRateHelperTenorsMap().find(idxName)->second;
485 vector<Handle<Quote>> parValVecBase = initParMarket->indexCurveRateHelperValuesMap().find(idxName)->second;
486 vector<string> sensiLabels(parValVecBase.size());
487 for (Size i = 0; i < parValVecBase.size(); i++) {
488 sensiLabels[i] = "IndexCurve/" + idxName + "/" + to_string(i) + "/" + to_string(parTenorVec[i]);
489 }
490 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
491 shiftSize, shiftType, parDelta, zeroDelta, basePv);
492 }
493 BOOST_TEST_MESSAGE("testing default curve par sensis");
494 // the default curve par sensis
495 for (auto d_it : initParMarket->defaultRateHelpersInstMap()) {
496 string name = d_it.first;
497 auto itr = zeroAnalysis->sensitivityData()->creditCurveShiftData().find(name);
498 if (itr == zeroAnalysis->sensitivityData()->creditCurveShiftData().end())
499 zeroAnalysis->sensitivityData()->creditCurveShiftData()[name] =
500 QuantLib::ext::make_shared<SensitivityScenarioData::CurveShiftData>();
501 Real shiftSize = zeroAnalysis->sensitivityData()->creditCurveShiftData()[name]->shiftSize;
502 ShiftType shiftType = zeroAnalysis->sensitivityData()->creditCurveShiftData()[name]->shiftType;
503 vector<Period> parTenorVec = initParMarket->defaultRateHelperTenorsMap().find(name)->second;
504 vector<Handle<Quote>> parValVecBase = initParMarket->defaultRateHelperValuesMap().find(name)->second;
505 vector<string> sensiLabels(parValVecBase.size());
506 for (Size i = 0; i < parValVecBase.size(); i++) {
507 sensiLabels[i] = "SurvivalProbability/" + name + "/" + to_string(i) + "/" + to_string(parTenorVec[i]);
508 }
509 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
510 shiftSize, shiftType, parDelta, zeroDelta, basePv);
511 }
512 BOOST_TEST_MESSAGE("testing cds par sensis");
513 // CDS Vol sensis (compare with zero sensi)
514 for (auto d_it : initParMarket->cdsVolRateHelperValuesMap()) {
515 string name = d_it.first;
516 Real shiftSize = zeroAnalysis->sensitivityData()->cdsVolShiftData()[name].shiftSize;
517 ShiftType shiftType = zeroAnalysis->sensitivityData()->cdsVolShiftData()[name].shiftType;
518 vector<Period> parTenorVec = initParMarket->cdsVolRateHelperTenorsMap().find(name)->second;
519 vector<Handle<Quote>> parValVecBase = initParMarket->cdsVolRateHelperValuesMap().find(name)->second;
520 vector<string> sensiLabels(parValVecBase.size());
521 for (Size i = 0; i < parValVecBase.size(); i++) {
522 sensiLabels[i] = "CDSVolatility/" + name + "/" + to_string(i) + "/" + to_string(parTenorVec[i]) + "/ATM";
523 }
524 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
525 shiftSize, shiftType, zeroDelta, zeroDelta, basePv);
526 }
527 BOOST_TEST_MESSAGE("testing eqVol curve par sensis");
528 // Equity Vol sensis (compare with zero sensi)
529 for (auto d_it : initParMarket->equityVolRateHelperValuesMap()) {
530 string name = d_it.first;
531 Real shiftSize = zeroAnalysis->sensitivityData()->equityVolShiftData()[name].shiftSize;
532 ShiftType shiftType = zeroAnalysis->sensitivityData()->equityVolShiftData()[name].shiftType;
533 vector<Period> parTenorVec = initParMarket->equityVolRateHelperTenorsMap().find(name)->second;
534 vector<Handle<Quote>> parValVecBase = initParMarket->equityVolRateHelperValuesMap().find(name)->second;
535 vector<string> sensiLabels(parValVecBase.size());
536 for (Size i = 0; i < parValVecBase.size(); i++) {
537 sensiLabels[i] = "EquityVolatility/" + name + "/" + to_string(i) + "/" + to_string(parTenorVec[i]) + "/ATM";
538 }
539 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
540 shiftSize, shiftType, zeroDelta, zeroDelta, basePv);
541 }
542 BOOST_TEST_MESSAGE("testing swaption vol par sensis");
543 // Swaption Vol sensis (compare with zero sensi)
544 for (auto d_it : initParMarket->swaptionVolRateHelperValuesMap()) {
545 string name = d_it.first;
546 Real shiftSize = zeroAnalysis->sensitivityData()->swaptionVolShiftData()[name].shiftSize;
547 ShiftType shiftType = zeroAnalysis->sensitivityData()->swaptionVolShiftData()[name].shiftType;
548 vector<Period> parTenorVec = initParMarket->swaptionVolRateHelperTenorsMap().find(name)->second;
549 vector<Period> swapTenorVec = initParMarket->swaptionVolRateHelperSwapTenorsMap().find(name)->second;
550 vector<Real> strikeSpreadVec = zeroAnalysis->sensitivityData()->swaptionVolShiftData()[name].shiftStrikes;
551 vector<Handle<Quote>> parValVecBase = initParMarket->swaptionVolRateHelperValuesMap().find(name)->second;
552 vector<string> sensiLabels(parValVecBase.size());
553 Size j = swapTenorVec.size();
554 Size k = zeroAnalysis->sensitivityData()->swaptionVolShiftData()[name].shiftStrikes.size();
555
556 for (Size i = 0; i < parValVecBase.size(); i++) {
557 Size strike = i % k;
558 Size parTenor = i / (j * k);
559 Size swapTenor = (i - parTenor * j * k - strike) / k;
560 std::ostringstream o;
561 if (close_enough(strikeSpreadVec[strike], 0))
562 o << "SwaptionVolatility/" << name << "/" << i << "/" << parTenorVec[parTenor] << "/"
563 << swapTenorVec[swapTenor] << "/ATM";
564 else
565 o << "SwaptionVolatility/" << name << "/" << i << "/" << parTenorVec[parTenor] << "/"
566 << swapTenorVec[swapTenor] << "/" << std::setprecision(4) << strikeSpreadVec[strike];
567 sensiLabels[i] = o.str();
568 }
569
570 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
571 shiftSize, shiftType, zeroDelta, zeroDelta, basePv);
572 }
573 BOOST_TEST_MESSAGE("testing base correlation par sensis");
574 // Base correlations sensis (compare with zero sensi)
575 for (auto d_it : initParMarket->baseCorrRateHelperValuesMap()) {
576 string name = d_it.first;
577 Real shiftSize = zeroAnalysis->sensitivityData()->baseCorrelationShiftData()[name].shiftSize;
578 ShiftType shiftType = zeroAnalysis->sensitivityData()->baseCorrelationShiftData()[name].shiftType;
579 vector<Period> parTenorVec = initParMarket->baseCorrRateHelperTenorsMap().find(name)->second;
580 vector<string> lossLevelVec = initParMarket->baseCorrLossLevelsMap().find(name)->second;
581 vector<Handle<Quote>> parValVecBase = initParMarket->baseCorrRateHelperValuesMap().find(name)->second;
582 vector<string> sensiLabels(parValVecBase.size());
583 Size j = lossLevelVec.size();
584 for (Size i = 0; i < parValVecBase.size(); i++) {
585 sensiLabels[i] = "BaseCorrelation/" + name + "/" + to_string(i) + "/" + lossLevelVec[i % j] + "/" +
586 to_string(parTenorVec[i / j]);
587 }
588 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
589 shiftSize, shiftType, zeroDelta, zeroDelta, basePv);
590 }
591 BOOST_TEST_MESSAGE("testing zero inflation par sensis");
592 // Zero Inflation sensis
593 for (auto d_it : initParMarket->zeroInflationRateHelperInstMap()) {
594 string idxName = d_it.first;
595 Real shiftSize = zeroAnalysis->sensitivityData()->zeroInflationCurveShiftData()[idxName]->shiftSize;
596 ShiftType shiftType = zeroAnalysis->sensitivityData()->zeroInflationCurveShiftData()[idxName]->shiftType;
597 vector<Period> parTenorVec = initParMarket->zeroInflationRateHelperTenorsMap().find(idxName)->second;
598 vector<Handle<Quote>> parValVecBase = initParMarket->zeroInflationRateHelperValuesMap().find(idxName)->second;
599 vector<string> sensiLabels(parValVecBase.size());
600 for (Size i = 0; i < parValVecBase.size(); i++) {
601 sensiLabels[i] = "ZeroInflationCurve/" + idxName + "/" + to_string(i) + "/" + to_string(parTenorVec[i]);
602 }
603 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
604 shiftSize, shiftType, parDelta, zeroDelta, basePv);
605 }
606 BOOST_TEST_MESSAGE("testing yoy inflation par sensis");
607 // YoY Inflation sensis
608 for (auto d_it : initParMarket->yoyInflationRateHelperInstMap()) {
609 string idxName = d_it.first;
610 Real shiftSize = zeroAnalysis->sensitivityData()->yoyInflationCurveShiftData()[idxName]->shiftSize;
611 ShiftType shiftType = zeroAnalysis->sensitivityData()->yoyInflationCurveShiftData()[idxName]->shiftType;
612 vector<Period> parTenorVec = initParMarket->yoyInflationRateHelperTenorsMap().find(idxName)->second;
613 vector<Handle<Quote>> parValVecBase = initParMarket->yoyInflationRateHelperValuesMap().find(idxName)->second;
614 vector<string> sensiLabels(parValVecBase.size());
615 for (Size i = 0; i < parValVecBase.size(); i++) {
616 sensiLabels[i] = "YoYInflationCurve/" + idxName + "/" + to_string(i) + "/" + to_string(parTenorVec[i]);
617 }
618 parSensiBumpAnalysis(portfolio, engineData, initMarket, baseManualPv, baseCcy, parValVecBase, sensiLabels,
619 shiftSize, shiftType, parDelta, zeroDelta, basePv);
620 }
621
622 // end
623 ObservationMode::instance().setMode(backupMode);
624 IndexManager::instance().clearHistories();
625}
static const string defaultConfiguration
static QuantLib::ext::shared_ptr< ore::analytics::SensitivityScenarioData > setupSensitivityScenarioData(bool hasSwapVolCube=false, bool hasYYCapVols=false, bool parConversion=false)
SensitivityScenarioData instance.
static QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > setupSimMarketData(bool hasSwapVolCube=false, bool hasYYCapVols=false)
ScenarioSimMarketParameters instance.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::string to_string(const LocationInfo &l)
QuantLib::ext::shared_ptr< Trade > buildCreditDefaultSwap(string id, string ccy, string issuerId, string creditCurveId, bool isPayer, Real notional, int start, Size term, Real rate, Real spread, string fixedFreq, string fixedDC)
QuantLib::ext::shared_ptr< Trade > buildSyntheticCDO(string id, string name, vector< string > names, string longShort, string ccy, vector< string > ccys, bool isPayer, vector< Real > notionals, Real notional, int start, Size term, Real rate, Real spread, string fixedFreq, string fixedDC)
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 > buildCmsCapFloor(string id, string ccy, string indexId, bool isPayer, Real notional, int start, Size term, Real capRate, Real floorRate, Real spread, string freq, string dc)
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 > 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 > buildCrossCcyBasisSwap(string id, string recCcy, Real recNotional, string payCcy, Real payNotional, int start, Size term, Real recLegSpread, Real payLegSpread, string recFreq, string recDC, string recIndex, Calendar recCalendar, string payFreq, string payDC, string payIndex, Calendar payCalendar, Natural spotDays, bool spotStartLag, bool notionalInitialExchange, bool notionalFinalExchange, bool notionalAmortizingExchange, bool isRecLegFXResettable, bool isPayLegFXResettable)
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)
string name
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ suite()

static boost::unit_test_framework::test_suite * suite ( )
static