@@ -90,15 +90,18 @@ Real discount(const boost::shared_ptr<CrossAssetModel>& model,
9090
9191std::vector<QuantExt::RandomVariable>
9292simulatePathInterface2 (const boost::shared_ptr<AmcCalculator>& amcCalc, const std::vector<Real>& pathTimes,
93- std::vector<std::vector<RandomVariable>>& paths, const std::vector<bool >& isRelevantTime,
93+ std::vector<std::vector<RandomVariable>>& paths, const std::vector<size_t >& pathIdx,
94+ const std::vector<size_t >& timeIdx,
9495 const bool moveStateToPreviousTime, const std::string& tradeLabel,
9596 const std::string& tradeType) {
97+ QL_REQUIRE (pathIdx.size () == timeIdx.size (),
98+ " internal error, mismatch between relevant path idx and timegrid idx, please contact dev" );
9699 try {
97- return amcCalc->simulatePath (pathTimes, paths, isRelevantTime , moveStateToPreviousTime);
100+ return amcCalc->simulatePath (pathTimes, paths, pathIdx, timeIdx , moveStateToPreviousTime);
98101 } catch (const std::exception& e) {
99102 StructuredTradeErrorMessage (tradeLabel, tradeType, " error during amc path simulation for trade." , e.what ())
100103 .log ();
101- return std::vector<QuantExt::RandomVariable>(std::count (isRelevantTime. begin (), isRelevantTime. end (), true ) + 1 ,
104+ return std::vector<QuantExt::RandomVariable>(pathIdx. size ( ) + 1 ,
102105 RandomVariable (paths.front ().front ().size ()));
103106 }
104107}
@@ -406,44 +409,37 @@ void runCoreEngine(const boost::shared_ptr<ore::data::Portfolio>& portfolio,
406409 // Run AmcCalculators
407410
408411 LOG (" Run simulation..." );
409-
410- for (size_t i = 0 ; i < sgd->getGrid ()->dates ().size (); i++){
411- std::cout << i << " Date " << sgd->getGrid ()->dates ()[i] << std::endl;
412- }
413-
414- for (size_t i = 0 ; i < sgd->getGrid ()->times ().size (); i++) {
415- std::cout << i << " time " << sgd->getGrid ()->times ()[i] << std::endl;
416- }
417-
418- for (size_t i = 0 ; i < sgd->getGrid ()->isCloseOutDate ().size (); i++) {
419- std::cout << i << " isCloseOutDate " << sgd->getGrid ()->isCloseOutDate ()[i] << std::endl;
420- }
421-
422- for (size_t i = 0 ; i < sgd->getGrid ()->isValuationDate ().size (); i++) {
423- std::cout << i << " isValuationDate " << sgd->getGrid ()->isValuationDate ()[i] << std::endl;
424- }
425-
426412 // set up vectors indicating valuation times, close-out times and all times
427413
428- std::vector<bool > allTimes (pathTimes.size (), true );
429- std::vector<bool > valuationTimes (pathTimes.size ()), closeOutTimes (pathTimes.size ());
430- for (Size i = 0 ; i < pathTimes.size (); ++i) {
431- std::cout << pathTimes[i] << " " << sgd->getGrid ()->isValuationDate ()[i] << " "
432- << sgd->getGrid ()->isCloseOutDate ()[i] << std::endl;
433- valuationTimes[i] = sgd->getGrid ()->isValuationDate ()[i];
434- closeOutTimes[i] = sgd->getGrid ()->isCloseOutDate ()[i];
414+ std::vector<size_t > allTimes;
415+ std::vector<size_t > valuationTimeIdx, closeOutTimeIdx;
416+ const auto & grid = sgd->getGrid ();
417+ const auto & dates = grid->dates ();
418+ size_t j = 0 ;
419+ for (size_t i = 0 ; i < pathTimes.size (); ++i) {
420+ allTimes.push_back (i);
421+ auto & d = dates[i];
422+ if (grid->isValuationDate ()[i]) {
423+ valuationTimeIdx.push_back (i);
424+ auto closeOutDate = grid->closeOutDateFromValuationDate (d);
425+ while (j < pathTimes.size () && dates[j] != closeOutDate) {
426+ ++j;
427+ }
428+ QL_REQUIRE (j < pathTimes.size (), " couldnt find close out date" );
429+ closeOutTimeIdx.push_back (j);
430+ }
435431 }
436432
437- // loop over amc calculators, get result and populate cube
433+ // loop over amc calculators, get result and populate cube
438434
439- timer.start ();
435+ timer.start ();
440436 for (Size j = 0 ; j < amcCalculators.size (); ++j) {
441437 auto resFee = feeContributions (j, sgd, model->irModel (0 )->termStructure ()->referenceDate (),
442438 outputCube->samples (), tradeFees, model, fxBuffer, irStateBuffer);
443439
444440 if (!sgd->withCloseOutLag ()) {
445441 // no close-out lag, fill depth 0 with npv on path
446- auto res = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, allTimes, false , tradeLabel[j],
442+ auto res = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, allTimes, allTimes, false , tradeLabel[j],
447443 tradeType[j]);
448444 Real v = outputCube->getT0 (tradeId[j], 0 );
449445 outputCube->setT0 (v +
@@ -467,16 +463,12 @@ void runCoreEngine(const boost::shared_ptr<ore::data::Portfolio>& portfolio,
467463 } else {
468464 // with close-out lag, fill depth 0 with valuation date npvs, depth 1 with (inflated) close-out npvs
469465 if (sgd->withMporStickyDate ()) {
470- std::cout << " Simulate with sticky date the valuationTimes" << std::endl;
471466 // sticky date mpor mode. simulate the valuation times...
472- auto res = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, valuationTimes, false ,
473- tradeLabel[j], tradeType[j]);
467+ auto res = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, valuationTimeIdx ,
468+ valuationTimeIdx, false , tradeLabel[j], tradeType[j]);
474469 // ... and then the close-out times, but times moved to the valuation times
475- std::cout << " Simulate with sticky date the closeOutTimes" << std::endl;
476-
477- auto resLag = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, closeOutTimes, true ,
478- tradeLabel[j], tradeType[j]);
479- std::cout << " Finished closeOutTime simulation" << std::endl;
470+ auto resLag = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, closeOutTimeIdx,
471+ valuationTimeIdx, true , tradeLabel[j], tradeType[j]);
480472 Real v = outputCube->getT0 (tradeId[j], 0 );
481473 outputCube->setT0 (v +
482474 res[0 ].at (0 ) * fx (fxBuffer, currencyIndex[j], 0 , 0 ) *
@@ -485,39 +477,33 @@ void runCoreEngine(const boost::shared_ptr<ore::data::Portfolio>& portfolio,
485477 resFee[0 ][0 ],
486478 tradeId[j], 0 );
487479 int dateIndex = -1 ;
488- std::map<QuantLib::Date, std::queue <std::tuple<QuantLib::Date, double , size_t >>> closeOutDateToValuationDate;
480+ std::map<QuantLib::Date, std::vector <std::tuple<QuantLib::Date, double , size_t >>> closeOutDateToValuationDate;
489481 for (Size k = 0 ; k < sgd->getGrid ()->dates ().size (); ++k) {
490482
491483 Real t = sgd->getGrid ()->timeGrid ()[k + 1 ];
492- std::cout << k << " " << t << std::endl;
493484 if (sgd->getGrid ()->isCloseOutDate ()[k]) {
494485 Date closeOutDate = sgd->getGrid ()->dates ()[k];
495486 auto dateIndexIt = closeOutDateToValuationDate.find (closeOutDate);
496487 QL_REQUIRE (dateIndexIt != closeOutDateToValuationDate.end () && !dateIndexIt->second .empty (),
497488 " The valuation date needs to before the corresponding close out date" );
498- Date valuationDate;
499- double valuationTime;
500- size_t valuationIndex;
501- std::tie (valuationDate, valuationTime, valuationIndex) = dateIndexIt->second .front ();
502- dateIndexIt->second .pop ();
503- std::cout << " Is closeOut date: " << to_string (closeOutDate) << " for valuation Date " << to_string (valuationDate) << std::endl;
504- for (Size i = 0 ; i < outputCube->samples (); ++i) {
505- Real v = outputCube->get (tradeId[j], valuationIndex, i, 1 );
506- outputCube->set (
507- v +
508- resLag[dateIndex + 1 ][i] * fx (fxBuffer, currencyIndex[j], k + 1 , i) *
509- num (model, irStateBuffer, currencyIndex[j], k + 1 , valuationTime, i) *
510- effectiveMultiplier[j] +
511- resFee[dateIndex + 1 ][i],
512- tradeId[j], valuationIndex, i, 1 );
489+ for (const auto & [valuationDate, valuationTime, valuationIndex] : dateIndexIt->second ){
490+ for (Size i = 0 ; i < outputCube->samples (); ++i) {
491+ Real v = outputCube->get (tradeId[j], valuationIndex, i, 1 );
492+ outputCube->set (
493+ v +
494+ resLag[valuationIndex + 1 ][i] * fx (fxBuffer, currencyIndex[j], k + 1 , i) *
495+ num (model, irStateBuffer, currencyIndex[j], k + 1 , valuationTime, i) *
496+ effectiveMultiplier[j] +
497+ resFee[valuationIndex + 1 ][i],
498+ tradeId[j], valuationIndex, i, 1 );
499+ }
513500 }
501+
514502 }
515503 if (sgd->getGrid ()->isValuationDate ()[k]) {
516504 Date valuationDate = sgd->getGrid ()->dates ()[k];
517505 Date closeOutDate = sgd->getGrid ()->closeOutDateFromValuationDate (valuationDate);
518- std::cout << " Is valuationDate date: " << to_string (valuationDate) << " with Index " << to_string (dateIndex + 1 )
519- << " and closeOutDate " << to_string (closeOutDate) << std::endl;
520- closeOutDateToValuationDate[closeOutDate].push (std::make_tuple (valuationDate, t, ++dateIndex));
506+ closeOutDateToValuationDate[closeOutDate].push_back (std::make_tuple (valuationDate, t, ++dateIndex));
521507 for (Size i = 0 ; i < outputCube->samples (); ++i) {
522508 Real v = outputCube->get (tradeId[j], dateIndex, i, 0 );
523509 outputCube->set (v +
@@ -531,14 +517,14 @@ void runCoreEngine(const boost::shared_ptr<ore::data::Portfolio>& portfolio,
531517 }
532518 } else {
533519 // actual date mpor mode: simulate all times in one go
534- auto res = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, allTimes, false , tradeLabel[j] ,
535- tradeType[j]);
520+ auto res = simulatePathInterface2 (amcCalculators[j], pathTimes, paths, allTimes, allTimes, false ,
521+ tradeLabel[j], tradeType[j]);
536522 Real v = outputCube->getT0 (tradeId[j], 0 );
537523 outputCube->setT0 (v + res[0 ].at (0 ) * fx (fxBuffer, currencyIndex[j], 0 , 0 ) *
538524 numRatio (model, irStateBuffer, currencyIndex[j], 0 , 0.0 , 0 ) *
539525 effectiveMultiplier[j],
540526 tradeId[j], 0 );
541- std::map<QuantLib::Date, std::queue <std::tuple<QuantLib::Date, double , size_t >>>
527+ std::map<QuantLib::Date, std::vector <std::tuple<QuantLib::Date, double , size_t >>>
542528 closeOutDateToValuationDate;
543529 int dateIndex = -1 ;
544530 for (Size k = 1 ; k < res.size (); ++k) {
@@ -548,24 +534,22 @@ void runCoreEngine(const boost::shared_ptr<ore::data::Portfolio>& portfolio,
548534 auto dateIndexIt = closeOutDateToValuationDate.find (closeOutDate);
549535 QL_REQUIRE (dateIndexIt != closeOutDateToValuationDate.end () && !dateIndexIt->second .empty (),
550536 " The valuation date needs to before the corresponding close out date" );
551- Date valuationDate;
552- double valuationTime;
553- size_t valuationIndex;
554- std::tie (valuationDate, valuationTime, valuationIndex) = dateIndexIt->second .front ();
555- for (Size i = 0 ; i < outputCube->samples (); ++i) {
556- Real v = outputCube->get (tradeId[j], valuationIndex, i, 1 );
557- outputCube->set (v +
558- res[k][i] * fx (fxBuffer, currencyIndex[j], k, i) *
559- num (model, irStateBuffer, currencyIndex[j], k, t, i) *
560- effectiveMultiplier[j] +
561- resFee[k][i],
562- tradeId[j], valuationIndex, i, 1 );
537+ for (const auto & [valuationDate, valuationTime, valuationIndex] : dateIndexIt->second ) {
538+ for (Size i = 0 ; i < outputCube->samples (); ++i) {
539+ Real v = outputCube->get (tradeId[j], valuationIndex, i, 1 );
540+ outputCube->set (v +
541+ res[k][i] * fx (fxBuffer, currencyIndex[j], k, i) *
542+ num (model, irStateBuffer, currencyIndex[j], k, t, i) *
543+ effectiveMultiplier[j] +
544+ resFee[k][i],
545+ tradeId[j], valuationIndex, i, 1 );
546+ }
563547 }
564548 }
565549 if (sgd->getGrid ()->isValuationDate ()[k - 1 ]) {
566550 Date valuationDate = sgd->getGrid ()->dates ()[k - 1 ];
567551 Date closeOutDate = sgd->getGrid ()->closeOutDateFromValuationDate (valuationDate);
568- closeOutDateToValuationDate[closeOutDate].push (std::make_tuple (valuationDate, t, ++dateIndex));
552+ closeOutDateToValuationDate[closeOutDate].push_back (std::make_tuple (valuationDate, t, ++dateIndex));
569553 for (Size i = 0 ; i < outputCube->samples (); ++i) {
570554 Real v = outputCube->get (tradeId[j], dateIndex, i, 0 );
571555 outputCube->set (v +
0 commit comments