@@ -655,7 +655,6 @@ void XvaAnalyticImpl::buildScenarioGenerator(const bool continueOnCalibrationErr
655655 string config = inputs_->marketConfig (" simulation" );
656656 scenarioGenerator_ = sgb.build (model_, sf, analytic ()->configurations ().simMarketParams , inputs_->asof (), analytic ()->market (), config);
657657 QL_REQUIRE (scenarioGenerator_, " failed to build the scenario generator" );
658- grid_ = analytic ()->configurations ().scenarioGeneratorData ->getGrid ();
659658 samples_ = analytic ()->configurations ().scenarioGeneratorData ->samples ();
660659 LOG (" simulation grid size " << grid_->size ());
661660 LOG (" simulation grid valuation dates " << grid_->valuationDates ().size ());
@@ -683,25 +682,13 @@ void XvaAnalyticImpl::buildCrossAssetModel(const bool continueOnCalibrationError
683682}
684683
685684void XvaAnalyticImpl::initCubeDepth () {
686-
687685 if (cubeDepth_ == 0 ) {
688686 LOG (" XVA: Set cube depth" );
689- // Determine the required cube depth:
690- // - Without close-out grid and without storing flows we have a 3d cube (trades * dates * scenarios),
691- // otherwise we need a 4d "hypercube" with additonal dimension "depth"
692- // - If we build an auxiliary close-out grid then we store default values at depth 0 and close-out at depth 1
693- // - If we want to store cash flows that occur during the mpor, then we store them at depth 2
694- cubeDepth_ = 1 ;
695- if (analytic ()->configurations ().scenarioGeneratorData ->withCloseOutLag ())
696- cubeDepth_++;
697- if (inputs_->storeFlows ())
698- cubeDepth_++;
699-
687+ cubeDepth_ = cubeInterpreter_->requiredNpvCubeDepth ();
700688 LOG (" XVA: Cube depth set to: " << cubeDepth_);
701689 }
702690}
703691
704-
705692void XvaAnalyticImpl::initCube (boost::shared_ptr<NPVCube>& cube, const std::set<std::string>& ids, Size cubeDepth) {
706693
707694 LOG (" Init cube with depth " << cubeDepth);
@@ -725,10 +712,11 @@ void XvaAnalyticImpl::initClassicRun(const boost::shared_ptr<Portfolio>& portfol
725712 initCubeDepth ();
726713
727714 // May have been set already
728- if (! scenarioData_) {
715+ if (scenarioData_. empty () ) {
729716 LOG (" XVA: Create asd " << grid_->valuationDates ().size () << " x " << samples_);
730- scenarioData_ = boost::make_shared<InMemoryAggregationScenarioData>(grid_->valuationDates ().size (), samples_);
731- simMarket_->aggregationScenarioData () = scenarioData_;
717+ scenarioData_.linkTo (
718+ boost::make_shared<InMemoryAggregationScenarioData>(grid_->valuationDates ().size (), samples_));
719+ simMarket_->aggregationScenarioData () = *scenarioData_;
732720 }
733721
734722 // We can skip the cube initialization if the mt val engine is used, since it builds its own cubes
@@ -797,14 +785,15 @@ void XvaAnalyticImpl::buildClassicCube(const boost::shared_ptr<Portfolio>& portf
797785 if (analytic ()->configurations ().scenarioGeneratorData ->withCloseOutLag ()) {
798786 boost::shared_ptr<NPVCalculator> npvCalc =
799787 boost::make_shared<NPVCalculator>(inputs_->exposureBaseCurrency ());
800- calculators.push_back (boost::make_shared<MPORCalculator>(npvCalc, 0 , 1 ));
788+ calculators.push_back (boost::make_shared<MPORCalculator>(npvCalc, cubeInterpreter_->defaultDateNpvIndex (),
789+ cubeInterpreter_->closeOutDateNpvIndex ()));
801790 } else {
802791 calculators.push_back (boost::make_shared<NPVCalculator>(inputs_->exposureBaseCurrency ()));
803792 }
804793 if (inputs_->storeFlows ()) {
805794 // cash flow stored at index 1 (no close-out lag) or 2 (have close-out lag)
806- calculators.push_back (boost::make_shared<CashflowCalculator>(inputs_-> exposureBaseCurrency (),
807- inputs_->asof (), grid_, cubeDepth_ - 1 ));
795+ calculators.push_back (boost::make_shared<CashflowCalculator>(
796+ inputs_-> exposureBaseCurrency (), inputs_->asof (), grid_, cubeInterpreter_-> mporFlowsIndex () ));
808797 }
809798 return calculators;
810799 };
@@ -820,13 +809,6 @@ void XvaAnalyticImpl::buildClassicCube(const boost::shared_ptr<Portfolio>& portf
820809 return cptyCalculators;
821810 };
822811
823- // set cube interpretation depending on close-out lag
824-
825- if (analytic ()->configurations ().scenarioGeneratorData ->withCloseOutLag ())
826- cubeInterpreter_ = boost::make_shared<MporGridCubeInterpretation>(scenarioData_, grid_, inputs_->flipViewXVA ());
827- else
828- cubeInterpreter_ = boost::make_shared<RegularCubeInterpretation>(scenarioData_, inputs_->flipViewXVA ());
829-
830812 // log message
831813
832814 ostringstream o;
@@ -970,11 +952,12 @@ void XvaAnalyticImpl::buildAmcPortfolio() {
970952void XvaAnalyticImpl::amcRun (bool doClassicRun) {
971953
972954 LOG (" XVA: amcRun" );
973-
974- if (! scenarioData_) {
955+
956+ if (scenarioData_. empty () ) {
975957 LOG (" XVA: Create asd " << grid_->valuationDates ().size () << " x " << samples_);
976- scenarioData_ = boost::make_shared<InMemoryAggregationScenarioData>(grid_->valuationDates ().size (), samples_);
977- simMarket_->aggregationScenarioData () = scenarioData_;
958+ scenarioData_.linkTo (
959+ boost::make_shared<InMemoryAggregationScenarioData>(grid_->valuationDates ().size (), samples_));
960+ simMarket_->aggregationScenarioData () = *scenarioData_;
978961 }
979962
980963 initCubeDepth ();
@@ -993,7 +976,7 @@ void XvaAnalyticImpl::amcRun(bool doClassicRun) {
993976 amcEngine.registerProgressIndicator (progressLog);
994977 // We only need to generate asd, if this does not happen in the classic run
995978 if (!doClassicRun)
996- amcEngine.aggregationScenarioData () = scenarioData_;
979+ amcEngine.aggregationScenarioData () = * scenarioData_;
997980 amcEngine.buildCube (amcPortfolio_, amcCube_);
998981 } else {
999982 auto cubeFactory = [this ](const QuantLib::Date& asof, const std::set<std::string>& ids,
@@ -1019,7 +1002,7 @@ void XvaAnalyticImpl::amcRun(bool doClassicRun) {
10191002 amcEngine.registerProgressIndicator (progressLog);
10201003 // as for the single-threaded case, we only need to generate asd, if this does not happen in the classic run
10211004 if (!doClassicRun)
1022- amcEngine.aggregationScenarioData () = scenarioData_;
1005+ amcEngine.aggregationScenarioData () = * scenarioData_;
10231006 amcEngine.buildCube (amcPortfolio_);
10241007 amcCube_ = boost::make_shared<JointNPVCube>(amcEngine.outputCubes ());
10251008 }
@@ -1076,22 +1059,10 @@ void XvaAnalyticImpl::runPostProcessor() {
10761059
10771060 checkConfigurations (analytic ()->portfolio ());
10781061
1079- if (!cubeInterpreter_) {
1080- // FIXME: Can we get the grid from the cube instead?
1081- QL_REQUIRE (analytic ()->configurations ().scenarioGeneratorData , " scenario generator data not set" );
1082- boost::shared_ptr<ScenarioGeneratorData> sgd = analytic ()->configurations ().scenarioGeneratorData ;
1083- LOG (" withCloseOutLag=" << (sgd->withCloseOutLag () ? " Y" : " N" ));
1084- if (sgd->withCloseOutLag ())
1085- cubeInterpreter_ =
1086- boost::make_shared<MporGridCubeInterpretation>(scenarioData_, sgd->getGrid (), analytics[" flipViewXVA" ]);
1087- else
1088- cubeInterpreter_ = boost::make_shared<RegularCubeInterpretation>(scenarioData_, analytics[" flipViewXVA" ]);
1089- }
1090-
10911062 if (!dimCalculator_ && (analytics[" mva" ] || analytics[" dim" ])) {
10921063 ALOG (" dim calculator not set, create RegressionDynamicInitialMarginCalculator" );
10931064 dimCalculator_ = boost::make_shared<RegressionDynamicInitialMarginCalculator>(
1094- inputs_, analytic ()->portfolio (), cube_, cubeInterpreter_, scenarioData_, dimQuantile, dimHorizonCalendarDays, dimRegressionOrder,
1065+ inputs_, analytic ()->portfolio (), cube_, cubeInterpreter_, * scenarioData_, dimQuantile, dimHorizonCalendarDays, dimRegressionOrder,
10951066 dimRegressors, dimLocalRegressionEvaluations, dimLocalRegressionBandwidth);
10961067 }
10971068
@@ -1104,7 +1075,7 @@ void XvaAnalyticImpl::runPostProcessor() {
11041075 LOG (" baseCurrency " << baseCurrency);
11051076
11061077 postProcess_ = boost::make_shared<PostProcess>(
1107- analytic ()->portfolio (), netting, analytic ()->market (), marketConfiguration, cube_, scenarioData_, analytics,
1078+ analytic ()->portfolio (), netting, analytic ()->market (), marketConfiguration, cube_, * scenarioData_, analytics,
11081079 baseCurrency,
11091080 allocationMethod, marginalAllocationLimit, quantile, calculationType, dvaName, fvaBorrowingCurve,
11101081 fvaLendingCurve, dimCalculator_, cubeInterpreter_, fullInitialCollateralisation, cvaSensiGrid,
@@ -1132,7 +1103,11 @@ void XvaAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLoa
11321103 CONSOLEW (" XVA: Build Market" );
11331104 analytic ()->buildMarket (loader);
11341105 CONSOLE (" OK" );
1135-
1106+
1107+ cubeInterpreter_ = boost::make_shared<CubeInterpretation>(
1108+ inputs_->storeFlows (), analytic ()->configurations ().scenarioGeneratorData ->withCloseOutLag (), scenarioData_,
1109+ analytic ()->configurations ().scenarioGeneratorData ->getGrid (), inputs_->flipViewXVA ());
1110+
11361111 if (runSimulation_) {
11371112
11381113 LOG (" XVA: Build simulation market" );
@@ -1233,8 +1208,8 @@ void XvaAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLoa
12331208 CONSOLEW (" XVA: Load Cubes" );
12341209 QL_REQUIRE (inputs_->cube (), " XVA without EXPOSURE requires an NPV cube as input" );
12351210 cube_= inputs_->cube ();
1236- QL_REQUIRE (inputs_->mktCube (), " XVA without EXPOSURE requires a market cube as input" );
1237- scenarioData_ = inputs_->mktCube ();
1211+ QL_REQUIRE (inputs_->mktCube (), " XVA without EXPOSURE requires a market cube as input" );
1212+ scenarioData_. linkTo ( inputs_->mktCube () );
12381213 if (inputs_->nettingSetCube ())
12391214 nettingSetCube_= inputs_->nettingSetCube ();
12401215 if (inputs_->cptyCube ())
@@ -1247,7 +1222,7 @@ void XvaAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLoa
12471222 // Return the cubes to serialalize
12481223 if (inputs_->writeCube ()) {
12491224 analytic ()->npvCubes ()[" XVA" ][" cube" ] = cube_;
1250- analytic ()->mktCubes ()[" XVA" ][" scenariodata" ] = scenarioData_;
1225+ analytic ()->mktCubes ()[" XVA" ][" scenariodata" ] = * scenarioData_;
12511226 if (nettingSetCube_) {
12521227 analytic ()->npvCubes ()[" XVA" ][" nettingsetcube" ] = nettingSetCube_;
12531228 }
0 commit comments