Skip to content

Commit cda7917

Browse files
mgronckijenkins
authored andcommitted
Work in progress, fix overlapping closeout grid
1 parent 9d31f9b commit cda7917

15 files changed

Lines changed: 162 additions & 138 deletions

OREAnalytics/orea/app/analytics/xvaanalytic.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,8 @@ void XvaAnalyticImpl::runAnalytic(const boost::shared_ptr<ore::data::InMemoryLoa
757757
map<string, string> nettingSetMap = analytic()->portfolio()->nettingSetMap();
758758
auto report = boost::make_shared<InMemoryReport>();
759759
ReportWriter(inputs_->reportNaString()).writeCube(*report, cube_, nettingSetMap);
760+
auto csvReprt = boost::make_shared<CSVFileReport>("test_report.csv");
761+
ReportWriter(inputs_->reportNaString()).writeCube(*csvReprt, cube_, nettingSetMap);
760762
analytic()->reports()["XVA"]["rawcube"] = report;
761763
}
762764

OREAnalytics/orea/engine/amcvaluationengine.cpp

Lines changed: 58 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,18 @@ Real discount(const boost::shared_ptr<CrossAssetModel>& model,
9090

9191
std::vector<QuantExt::RandomVariable>
9292
simulatePathInterface2(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 +

OREAnalytics/orea/engine/multithreadedvaluationengine.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,10 @@ void MultiThreadedValuationEngine::buildCube(
229229
miniNettingSetCubes_.clear();
230230
miniCptyCubes_.clear();
231231
for (Size i = 0; i < eff_nThreads; ++i) {
232-
miniCubes_.push_back(cubeFactory_(today_, portfolios[i]->ids(), dateGrid_->dates(), nSamples_));
233-
miniNettingSetCubes_.push_back(nettingSetCubeFactory_(today_, dateGrid_->dates(), nSamples_));
232+
miniCubes_.push_back(cubeFactory_(today_, portfolios[i]->ids(), dateGrid_->valuationDates(), nSamples_));
233+
miniNettingSetCubes_.push_back(nettingSetCubeFactory_(today_, dateGrid_->valuationDates(), nSamples_));
234234
miniCptyCubes_.push_back(
235-
cptyCubeFactory_(today_, portfolios[i]->counterparties(), dateGrid_->dates(), nSamples_));
235+
cptyCubeFactory_(today_, portfolios[i]->counterparties(), dateGrid_->valuationDates(), nSamples_));
236236
}
237237

238238
// build progress indicator consolidating the results from the threads

0 commit comments

Comments
 (0)