504 {
505
506
507
508 CachedResultsData cachedResults;
509 std::map<tuple<string, string, string, string, string, string>, vector<Date>> cachedDefaultDates = cachedResults.defaultDates;
510 std::map<tuple<string, string, string, string, string, string>, vector<Real>> cachedDefaultValues = cachedResults.defaultValues;
511 std::map<tuple<string, string, string, string, string, string>, vector<Date>> cachedCloseOutDates = cachedResults.closeOutDates;
512 std::map<tuple<string, string, string, string, string, string>, vector<Real>> cachedCloseOutValues = cachedResults.closeOutValues;
513
514
515 BOOST_TEST_MESSAGE("Running NettedExposureCalculatorTestWithCloseOutGrid...");
517 BOOST_TEST_MESSAGE("Reference Date is "<<QuantLib::io::iso_date(referenceDate));
519
520 string dateGridStr;
521 QuantLib::ext::shared_ptr<DateGrid> dateGrid;
522 std::string nettingSetMpor = "1W";
523 BOOST_TEST_MESSAGE("Neting-set mpor is "<< nettingSetMpor);
524 vector<bool> withCloseOutGrid = {false, true};
525 bool mporStickyDate = false;
526 string mporModeStr = mporStickyDate ? "StickyDate": "ActualDate";
527 bool withCompounding = false;
528 string compoundingStr = withCompounding ? "withCompounding" : "woCompounding";
529 string calcTypeStr;
530
531 for(Size k = 0; k<withCloseOutGrid.size(); k++){
532
533 string closeOutGridStr = withCloseOutGrid[k] ? "withCloseOutGrid": "woCloseOutGrid";
534 std::vector<CollateralExposureHelper::CalculationType> calcTypes;
535 if (withCloseOutGrid[k]){
536 dateGridStr = "13,1M";
537 dateGrid = QuantLib::ext::make_shared<DateGrid>(dateGridStr);
538 calcTypes= {CollateralExposureHelper::CalculationType::NoLag};
539 }
540 else{
541 dateGridStr = "13,1W";
542 dateGrid = QuantLib::ext::make_shared<DateGrid>(dateGridStr);
543 calcTypes= {CollateralExposureHelper::CalculationType::Symmetric,
544 CollateralExposureHelper::CalculationType::AsymmetricCVA,
545 CollateralExposureHelper::CalculationType::AsymmetricDVA
546 };
547 }
548 Period Mpor(1, Weeks);
549 if (withCloseOutGrid[k]){
550 BOOST_TEST_MESSAGE("With close-out grid!");
551 BOOST_TEST_MESSAGE("MPOR in close-out grid= "<< Mpor);
552 dateGrid->addCloseOutDates(Mpor);
553 if (mporStickyDate){
554 BOOST_TEST_MESSAGE("With mpor mode sticky date!");
555 }else
556 BOOST_TEST_MESSAGE("With mpor mode actual date!");
557 }else
558 BOOST_TEST_MESSAGE("Without close-out grid!");
559
560 TestData td(referenceDate, dateGrid, withCloseOutGrid[k], mporStickyDate);
561
562 BOOST_TEST_MESSAGE("DateGrid: ");
563 BOOST_TEST_MESSAGE("t_0, "<<io::iso_date(referenceDate));
564 for(Size i=0; i<dateGrid->times().
size(); i++)
565 BOOST_TEST_MESSAGE("t_"<<i+1<<", "<<QuantLib::io::iso_date(dateGrid->dates()[i]));
566
567 QuantLib::ext::shared_ptr<Market> initMarket = td.initMarket_;
568 QuantLib::ext::shared_ptr<NPVCube> cube = td.cube_;
569 QuantLib::ext::shared_ptr<Portfolio> portfolio = td.portfolio_;
570
571 std::string nettingSetId = portfolio->trades().begin()->second->envelope().nettingSetId();
573
574 if (withCloseOutGrid[k]){
575 Period nettingSetMporPeriod = PeriodParser::parse(nettingSetMpor);
576 QL_REQUIRE(nettingSetMporPeriod == Mpor, "Netting-set mpor is not consistent with the closeout grid!");
577 }
578
579 std::vector<std::string> elgColls = {"EUR"};
580 QuantLib::ext::shared_ptr<NettingSetDefinition> nettingSetDefinition = QuantLib::ext::make_shared<NettingSetDefinition>(nettingSetDetails,
581 "Bilateral", "EUR", "EUR-EONIA",
582 0.0, 0.0, 0.0, 0.0, 0.0,
583 "FIXED", "1D", "1D",
584 nettingSetMpor, 0.0, 0.0, elgColls);
585 QuantLib::ext::shared_ptr<NettingSetManager> nettingSetManager = QuantLib::ext::make_shared<NettingSetManager>();
586 nettingSetManager->add(nettingSetDefinition);
587
588
589 QuantLib::ext::shared_ptr<CollateralBalances> collateralBalances = QuantLib::ext::make_shared<CollateralBalances>();
590
591 map<string, vector<vector<Real>>> nettingSetDefaultValue;
592 map<string, vector<vector<Real>>> nettingSetCloseOutValue;
593 map<string, vector<vector<Real>>> nettingSetMporPositiveFlow;
594 map<string, vector<vector<Real>>> nettingSetMporNegativeFlow;
595 map<string, vector<vector<Real>>> nettingSetValue;
596 vector<Real> collateralBalance;
597 vector<vector<Real>> defaultValue;
598
599 std::string fileName;
600 Handle<AggregationScenarioData> asd;
601 QuantLib::ext::shared_ptr<CubeInterpretation> cubeInterpreter;
602 if (withCloseOutGrid[k]) {
603 fileName = "scenarioData_closeout.csv";
605 cubeInterpreter = QuantLib::ext::make_shared<CubeInterpretation>(true, true, asd, dateGrid);
606 } else {
607 fileName = "scenarioData.csv";
609 cubeInterpreter = QuantLib::ext::make_shared<CubeInterpretation>(true, false, asd);
610 }
611
612 if (!withCompounding){
613 compoundingStr = "woCompounding";
614 for (Size i =0; i<cube->dates().
size(); i++)
615 asd->set(i, 0, 0, AggregationScenarioDataType::IndexFixing, "EUR-EONIA");
616 }
617
618 vector<string> regressors = {"EUR-EURIBOR-6M"};
619 QuantLib::ext::shared_ptr<InputParameters> inputs = QuantLib::ext::make_shared<InputParameters>();
620 QuantLib::ext::shared_ptr<RegressionDynamicInitialMarginCalculator> dimCalculator =
621 QuantLib::ext::make_shared<RegressionDynamicInitialMarginCalculator>(inputs, portfolio, cube, cubeInterpreter, *asd,
622 0.99, 14, 2, regressors);
623
624 BOOST_TEST_MESSAGE("initial NPV at "<< QuantLib::io::iso_date(referenceDate)<<": "<<cube->getT0(0));
625 for (Size i = 0; i<cube->dates().
size(); i++)
626 BOOST_TEST_MESSAGE("defaultValue at "<< QuantLib::io::iso_date(dateGrid->valuationDates()[i])<<": "<<cubeInterpreter->getDefaultNpv(cube, 0, i, 0));
627
628 for (Size i = 0; i<cube->dates().
size(); i++){
629 if (withCloseOutGrid[k]){
630 if (i != cube->dates().size()-1)
631 BOOST_TEST_MESSAGE("closeOutValue at "<< QuantLib::io::iso_date(dateGrid->closeOutDates()[i])<<": "<<cubeInterpreter->getCloseOutNpv(cube, 0, i, 0));
632 }
633 else{
634 if (i != cube->dates().size()-1)
635 BOOST_TEST_MESSAGE("closeOutValue at "<< QuantLib::io::iso_date(dateGrid->valuationDates()[i])<<": "<<cubeInterpreter->getCloseOutNpv(cube, 0, i, 0));
636 }
637
638 }
639
640 for(auto calcType : calcTypes){
642 calcTypeStr = "Symmetric";
644 calcTypeStr = "AsymmetricCVA";
646 calcTypeStr = "AsymmetricDVA";
648 calcTypeStr = "NoLag";
649 else
650 QL_FAIL("Collateral calculation type not covered");
651 BOOST_TEST_MESSAGE("Calculation type: "<< calcTypeStr);
652
653 QuantLib::ext::shared_ptr<ExposureCalculator> exposureCalculator = QuantLib::ext::make_shared<ExposureCalculator>(portfolio, cube, cubeInterpreter,
654 initMarket, false, "EUR", "Market",
655 0.99, calcType, false, false);
656 exposureCalculator->build();
657 nettingSetDefaultValue = exposureCalculator->nettingSetDefaultValue();
658 nettingSetCloseOutValue = exposureCalculator->nettingSetCloseOutValue();
659 nettingSetMporPositiveFlow = exposureCalculator->nettingSetMporPositiveFlow();
660 nettingSetMporNegativeFlow = exposureCalculator->nettingSetMporNegativeFlow();
661 QuantLib::ext::shared_ptr<NettedExposureCalculator> nettedExposureCalculator =
662 QuantLib::ext::make_shared<NettedExposureCalculator>(
663 portfolio, initMarket, cube, "EUR", "Market", 0.99, calcType, false, nettingSetManager, collateralBalances,
664 nettingSetDefaultValue, nettingSetCloseOutValue, nettingSetMporPositiveFlow,
665 nettingSetMporNegativeFlow, *asd, cubeInterpreter, false, dimCalculator, false, false, 0.1,
666 exposureCalculator->exposureCube(), 0, 0, false, mporStickyDate, MporCashFlowMode::Unspecified);
667 nettedExposureCalculator->build();
668 nettingSetValue = (calcType == CollateralExposureHelper::CalculationType::NoLag
669 ? nettedExposureCalculator->nettingSetCloseOutValue()
670 : nettedExposureCalculator->nettingSetDefaultValue());
671 collateralBalance = nettedExposureCalculator->expectedCollateral(nettingSetId);
672 BOOST_TEST_MESSAGE("defaultDate, defaultValue, closeOutDate, collateralBalance");
673 auto key = make_tuple(dateGridStr, nettingSetMpor, closeOutGridStr, mporModeStr, calcTypeStr, compoundingStr);
674
675 vector<Date> cdd = cachedDefaultDates[key];
676 vector<Real> cdv = cachedDefaultValues[key];
677 vector<Date> ccd = cachedCloseOutDates[key];
678 vector<Real> ccv = cachedCloseOutValues[key];
679 BOOST_TEST_MESSAGE("cdd "<<cdd.size());
680 BOOST_TEST_MESSAGE("cdv "<<cdv.size());
681 BOOST_TEST_MESSAGE("ccd "<<ccd.size());
682 BOOST_TEST_MESSAGE("ccv "<<ccv.size());
683 Real tolerance = 1E-2;
684 for (auto n : nettingSetValue){
685 vector<vector<Real>> defaultValue = n.second;
686 for (Size j = 0; j < cube->dates().
size(); j++){
687 BOOST_TEST_MESSAGE(io::iso_date(dateGrid->valuationDates()[j])<<", "<<defaultValue[j][0] <<", "<< collateralBalance[j+1]);
688
689 BOOST_CHECK_MESSAGE(dateGrid->valuationDates()[j] == cdd[j],
690 "default date "<< dateGrid->valuationDates()[j] << " does not match with cashed default date "<< cdd[j]);
691 BOOST_CHECK_MESSAGE(fabs(defaultValue[j][0] - cdv[j]) < tolerance,
692 "default value "<< defaultValue[j][0] << " does not match with cashed default value "<< cdv[j]);
693 BOOST_CHECK_MESSAGE(fabs(collateralBalance[j+1] - ccv[j]) < tolerance,
694 "collateral balance "<< collateralBalance[j+1] << " does not match with cashed collateral balance "<< ccv[j]);
695 }
696 }
697 }
698 }
699}
QuantLib::ext::shared_ptr< AggregationScenarioData > loadAggregationScenarioData(const std::string &filename)
Size size(const ValueType &v)