Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
xvaanalytic.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2022 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
35
38
39using namespace ore::data;
40using namespace boost::filesystem;
41
42namespace ore {
43namespace analytics {
44
45/******************************************************************************
46 * XVA Analytic: EXPOSURE, CVA, DVA, FVA, KVA, COLVA, COLLATERALFLOOR, DIM, MVA
47 ******************************************************************************/
48
50 LOG("XvaAnalytic::setUpConfigurations() called");
51 analytic()->configurations().todaysMarketParams = inputs_->todaysMarketParams();
52 analytic()->configurations().simMarketParams = inputs_->exposureSimMarketParams();
53 analytic()->configurations().scenarioGeneratorData = inputs_->scenarioGeneratorData();
54 analytic()->configurations().crossAssetModelData = inputs_->crossAssetModelData();
55}
56
57void XvaAnalyticImpl::checkConfigurations(const QuantLib::ext::shared_ptr<Portfolio>& portfolio) {
58 //find the unique nettingset keys in portfolio
59 std::map<std::string, std::string> nettingSetMap = portfolio->nettingSetMap();
60 std::vector<std::string> nettingSetKeys;
61 for(std::map<std::string, std::string>::iterator it = nettingSetMap.begin(); it != nettingSetMap.end(); ++it)
62 nettingSetKeys.push_back(it->second);
63 //unique nettingset keys
64 sort(nettingSetKeys.begin(), nettingSetKeys.end());
65 nettingSetKeys.erase(unique( nettingSetKeys.begin(), nettingSetKeys.end() ), nettingSetKeys.end());
66 //controls on calcType and grid type, if netting-set has an active CSA in place
67 for(auto const& key : nettingSetKeys){
68 LOG("For netting-set "<<key<<"CSA flag is "<<inputs_->nettingSetManager()->get(key)->activeCsaFlag());
69 if (inputs_->nettingSetManager()->get(key)->activeCsaFlag()){
70 string calculationType = inputs_->collateralCalculationType();
71 if (analytic()->configurations().scenarioGeneratorData->withCloseOutLag()){
72 QL_REQUIRE(calculationType == "NoLag", "For nettingSetID "<<key<< ", CSA is active and a close-out grid is configured in the simulation.xml. Therefore, calculation type "<<calculationType<<" is not admissable. It must be set to NoLag!");
73 LOG("For netting-set "<<key<<", calculation type is "<<calculationType);
74 }
75 else{
76 QL_REQUIRE(calculationType != "NoLag", "For nettingSetID "<<key<< ", CSA is active and a close-out grid is not configured in the simulation.xml. Therefore, calculation type " <<calculationType<<" is not admissable. It must be set to either Symmetric or AsymmerticCVA or AsymmetricDVA!" );
77 LOG("For netting-set "<<key<<", calculation type is "<<calculationType);
78 }
79 if (analytic()->configurations().scenarioGeneratorData->withCloseOutLag() && analytic()->configurations().scenarioGeneratorData->closeOutLag() != 0*Days){
80 Period mpor_simulation = analytic()->configurations().scenarioGeneratorData->closeOutLag();
81 Period mpor_netting = inputs_->nettingSetManager()->get(key)->csaDetails()->marginPeriodOfRisk();
82 if (mpor_simulation != mpor_netting)
84 "XvaAnalytic", "Inconsistent MPoR period",
85 "For netting set " + key + ", close-out lag is not consistent with the netting-set's mpor ")
86 .log();
87 }
88 }
89 }
90}
91
92QuantLib::ext::shared_ptr<EngineFactory> XvaAnalyticImpl::engineFactory() {
93 LOG("XvaAnalytic::engineFactory() called");
94 QuantLib::ext::shared_ptr<EngineData> edCopy = QuantLib::ext::make_shared<EngineData>(*inputs_->simulationPricingEngine());
95 edCopy->globalParameters()["GenerateAdditionalResults"] = inputs_->outputAdditionalResults() ? "true" : "false";
96 edCopy->globalParameters()["RunType"] = "Exposure";
97 map<MarketContext, string> configurations;
98 configurations[MarketContext::irCalibration] = inputs_->marketConfig("lgmcalibration");
99 configurations[MarketContext::fxCalibration] = inputs_->marketConfig("fxcalibration");
100 configurations[MarketContext::pricing] = inputs_->marketConfig("pricing");
101 //configurations[MarketContext::simulation] = inputs_->marketConfig("simulation");
102 std::vector<QuantLib::ext::shared_ptr<EngineBuilder>> extraEngineBuilders;
103 std::vector<QuantLib::ext::shared_ptr<LegBuilder>> extraLegBuilders;
104
105 if (runSimulation_) {
106 // link to the sim market here
107 QL_REQUIRE(simMarket_, "Simulaton market not set");
108 engineFactory_ = QuantLib::ext::make_shared<EngineFactory>(edCopy, simMarket_, configurations,
109 inputs_->refDataManager(), *inputs_->iborFallbackConfig());
110 } else {
111 // we just link to today's market if simulation is not required
112 engineFactory_ = QuantLib::ext::make_shared<EngineFactory>(edCopy, analytic()->market(), configurations, inputs_->refDataManager(),
113 *inputs_->iborFallbackConfig());
114 }
115 return engineFactory_;
116}
117
118
120
121 std::string configuration = inputs_->marketConfig("simulation");
122 simMarket_ = QuantLib::ext::make_shared<ScenarioSimMarket>(
123 analytic()->market(),
124 analytic()->configurations().simMarketParams,
125 QuantLib::ext::make_shared<FixingManager>(inputs_->asof()),
126 configuration,
127 *inputs_->curveConfigs().get(),
128 *analytic()->configurations().todaysMarketParams,
129 inputs_->continueOnError(),
130 false, true, false,
131 *inputs_->iborFallbackConfig(),
132 false, offsetScenario_);
133
134 if(offsetScenario_ == nullptr){
137 } else{
138 // set useSpreadedTermstructure to true, yield better results in calibration of the CAM
139 simMarketCalibration_ = QuantLib::ext::make_shared<ScenarioSimMarket>(
140 analytic()->market(), analytic()->configurations().simMarketParams,
141 QuantLib::ext::make_shared<FixingManager>(inputs_->asof()), configuration, *inputs_->curveConfigs().get(),
142 *analytic()->configurations().todaysMarketParams, inputs_->continueOnError(), true, true, false,
143 *inputs_->iborFallbackConfig(), false, offsetScenario_);
144
145 // Create a third market used for AMC and Postprocessor, holds a larger simmarket, e.g. default curves
146 offsetSimMarket_ = QuantLib::ext::make_shared<ScenarioSimMarket>(
147 analytic()->market(), offsetSimMarketParams_, QuantLib::ext::make_shared<FixingManager>(inputs_->asof()),
148 configuration, *inputs_->curveConfigs().get(), *analytic()->configurations().todaysMarketParams,
149 inputs_->continueOnError(), true, true, false, *inputs_->iborFallbackConfig(), false, offsetScenario_);
150
151 TLOG("XvaAnalytic: Offset Scenario used in building SimMarket");
152 TLOG("XvaAnalytic: Offset scenario is absolute = " << offsetScenario_->isAbsolute());
153 TLOG("RfKey,OffsetScenarioValue");
154 for (const auto& key : offsetScenario_->keys()) {
155 TLOG(key << " : " << offsetScenario_->get(key));
156 }
157 }
158
159 TLOG("XvaAnalytic:Finished building Scenario SimMarket");
160 TLOG("RfKey,BaseScenarioValue,BaseScenarioAbsValue");
161 for (const auto& key : simMarket_->baseScenario()->keys()) {
162 TLOG(key << "," << simMarket_->baseScenario()->get(key) << "," << simMarket_->baseScenarioAbsolute()->get(key));
163 }
164 TLOG("XvaAnalytic: Finished building Scenario SimMarket for model calibration (useSpreadedTermStructure)");
165 TLOG("RfKey,BaseScenarioValue,BaseScenarioAbsValue");
166 for (const auto& key : simMarketCalibration_->baseScenario()->keys()) {
167 TLOG(key << "," << simMarketCalibration_->baseScenario()->get(key) << ","
168 << simMarketCalibration_->baseScenarioAbsolute()->get(key));
169 }
170}
171
172void XvaAnalyticImpl::buildScenarioGenerator(const bool continueOnCalibrationError) {
173 if (!model_)
174 buildCrossAssetModel(continueOnCalibrationError);
175 ScenarioGeneratorBuilder sgb(analytic()->configurations().scenarioGeneratorData);
176 QuantLib::ext::shared_ptr<ScenarioFactory> sf = QuantLib::ext::make_shared<SimpleScenarioFactory>(true);
177 string config = inputs_->marketConfig("simulation");
178 auto market = offsetScenario_ == nullptr ? analytic()->market() : simMarketCalibration_;
179 scenarioGenerator_ = sgb.build(model_, sf, analytic()->configurations().simMarketParams, inputs_->asof(), market, config);
180 QL_REQUIRE(scenarioGenerator_, "failed to build the scenario generator");
182 LOG("simulation grid size " << grid_->size());
183 LOG("simulation grid valuation dates " << grid_->valuationDates().size());
184 LOG("simulation grid close-out dates " << grid_->closeOutDates().size());
185 LOG("simulation grid front date " << io::iso_date(grid_->dates().front()));
186 LOG("simulation grid back date " << io::iso_date(grid_->dates().back()));
187
188 if (inputs_->writeScenarios()) {
189 auto report = QuantLib::ext::make_shared<InMemoryReport>();
190 analytic()->reports()["XVA"]["scenario"] = report;
191 scenarioGenerator_ = QuantLib::ext::make_shared<ScenarioWriter>(scenarioGenerator_, report);
192 }
193}
194
195void XvaAnalyticImpl::buildCrossAssetModel(const bool continueOnCalibrationError) {
196 LOG("XVA: Build Simulation Model (continueOnCalibrationError = "
197 << std::boolalpha << continueOnCalibrationError << ")");
198 ext::shared_ptr<Market> market = offsetScenario_ != nullptr ? simMarketCalibration_ : analytic()->market();
199 QL_REQUIRE(market != nullptr, "Internal error, buildCrossAssetModel needs to be called after the market is built.");
200 CrossAssetModelBuilder modelBuilder(
201 market, analytic()->configurations().crossAssetModelData, inputs_->marketConfig("lgmcalibration"),
202 inputs_->marketConfig("fxcalibration"), inputs_->marketConfig("eqcalibration"),
203 inputs_->marketConfig("infcalibration"), inputs_->marketConfig("crcalibration"),
204 inputs_->marketConfig("simulation"), false, continueOnCalibrationError, "",
205 inputs_->salvageCorrelationMatrix() ? SalvagingAlgorithm::Spectral : SalvagingAlgorithm::None,
206 "xva cam building");
207 model_ = *modelBuilder.model();
208}
209
211 if (cubeDepth_ == 0) {
212 LOG("XVA: Set cube depth");
213 cubeDepth_ = cubeInterpreter_->requiredNpvCubeDepth();
214 LOG("XVA: Cube depth set to: " << cubeDepth_);
215 }
216}
217
218void XvaAnalyticImpl::initCube(QuantLib::ext::shared_ptr<NPVCube>& cube, const std::set<std::string>& ids, Size cubeDepth) {
219
220 LOG("Init cube with depth " << cubeDepth);
221
222 for (Size i = 0; i < grid_->valuationDates().size(); ++i)
223 DLOG("initCube: grid[" << i << "]=" << io::iso_date(grid_->valuationDates()[i]));
224
225 if (cubeDepth == 1)
226 cube = QuantLib::ext::make_shared<SinglePrecisionInMemoryCube>(inputs_->asof(),
227 ids, grid_->valuationDates(), samples_, 0.0f);
228 else
229 cube = QuantLib::ext::make_shared<SinglePrecisionInMemoryCubeN>(inputs_->asof(),
230 ids, grid_->valuationDates(), samples_, cubeDepth, 0.0f);
231}
232
233
234void XvaAnalyticImpl::initClassicRun(const QuantLib::ext::shared_ptr<Portfolio>& portfolio) {
235
236 LOG("XVA: initClassicRun");
237
239
240 // May have been set already
241 if (scenarioData_.empty()) {
242 LOG("XVA: Create asd " << grid_->valuationDates().size() << " x " << samples_);
243 scenarioData_.linkTo(
244 QuantLib::ext::make_shared<InMemoryAggregationScenarioData>(grid_->valuationDates().size(), samples_));
245 simMarket_->aggregationScenarioData() = *scenarioData_;
246
247 }
248
249 // We can skip the cube initialization if the mt val engine is used, since it builds its own cubes
250 if (inputs_->nThreads() == 1) {
251 if (portfolio->size() > 0)
252 initCube(cube_, portfolio->ids(), cubeDepth_);
253 // not required by any calculators in ore at the moment
254 nettingSetCube_ = nullptr;
255 // Init counterparty cube for the storage of survival probabilities
256 if (inputs_->storeSurvivalProbabilities()) {
257 // Use full list of counterparties, not just those in the sub-portflio
258 auto counterparties = inputs_->portfolio()->counterparties();
259 counterparties.insert(inputs_->dvaName());
260 initCube(cptyCube_, counterparties, 1);
261 } else {
262 cptyCube_ = nullptr;
263 }
264 }
265
266 LOG("XVA: initClassicRun completed");
267}
268
269
270QuantLib::ext::shared_ptr<Portfolio> XvaAnalyticImpl::classicRun(const QuantLib::ext::shared_ptr<Portfolio>& portfolio) {
271 LOG("XVA: classicRun");
272
273
274 Size n = portfolio->size();
275 // Create a new empty portfolio, fill it and link it to the simulation market
276 // We don't use Analytic::buildPortfolio() here because we are possibly dealing with a sub-portfolio only.
277 LOG("XVA: Build classic portfolio of size " << n << " linked to the simulation market");
278 const string msg = "XVA: Build Portfolio";
279 CONSOLEW(msg);
280 ProgressMessage(msg, 0, 1).log();
281 classicPortfolio_ = QuantLib::ext::make_shared<Portfolio>(inputs_->buildFailedTrades());
282 portfolio->reset();
283 for (const auto& [tradeId, trade] : portfolio->trades())
284 classicPortfolio_->add(trade);
285 QL_REQUIRE(analytic()->market(), "today's market not set");
286 QuantLib::ext::shared_ptr<EngineFactory> factory = engineFactory();
287 classicPortfolio_->build(factory, "analytic/" + label());
288 Date maturityDate = inputs_->asof();
289 if (inputs_->portfolioFilterDate() != Null<Date>())
290 maturityDate = inputs_->portfolioFilterDate();
291 LOG("Filter trades that expire before " << maturityDate);
292 classicPortfolio_->removeMatured(maturityDate);
293 CONSOLE("OK");
294 ProgressMessage(msg, 1, 1).log();
295
296 // Allocate cubes for the sub-portfolio we are processing here
298
299 // This is where the valuation work is done
301
302 LOG("XVA: classicRun completed");
303
304 return classicPortfolio_;
305}
306
307
308void XvaAnalyticImpl::buildClassicCube(const QuantLib::ext::shared_ptr<Portfolio>& portfolio) {
309
310 LOG("XVA::buildCube");
311
312 // set up valuation calculator factory
313 auto calculators = [this]() {
314 vector<QuantLib::ext::shared_ptr<ValuationCalculator>> calculators;
315 if (analytic()->configurations().scenarioGeneratorData->withCloseOutLag()) {
316 QuantLib::ext::shared_ptr<NPVCalculator> npvCalc =
317 QuantLib::ext::make_shared<NPVCalculator>(inputs_->exposureBaseCurrency());
318 calculators.push_back(QuantLib::ext::make_shared<MPORCalculator>(npvCalc, cubeInterpreter_->defaultDateNpvIndex(),
319 cubeInterpreter_->closeOutDateNpvIndex()));
320 } else
321 calculators.push_back(QuantLib::ext::make_shared<NPVCalculator>(inputs_->exposureBaseCurrency()));
322 if (inputs_->storeFlows())
323 calculators.push_back(QuantLib::ext::make_shared<CashflowCalculator>(
324 inputs_->exposureBaseCurrency(), inputs_->asof(), grid_, cubeInterpreter_->mporFlowsIndex()));
325 if(inputs_->storeCreditStateNPVs() > 0) {
326 calculators.push_back(QuantLib::ext::make_shared<MultiStateNPVCalculator>(inputs_->exposureBaseCurrency(),
327 cubeInterpreter_->creditStateNPVsIndex(),
328 inputs_->storeCreditStateNPVs()));
329 }
330 return calculators;
331 };
332
333 // set up cpty calculator factory
334
335 auto cptyCalculators = [this]() {
336 vector<QuantLib::ext::shared_ptr<CounterpartyCalculator>> cptyCalculators;
337 if (inputs_->storeSurvivalProbabilities()) {
338 string configuration = inputs_->marketConfig("simulation");
339 cptyCalculators.push_back(QuantLib::ext::make_shared<SurvivalProbabilityCalculator>(configuration));
340 }
341 return cptyCalculators;
342 };
343
344 // log message
345
346 ostringstream o;
347 o << "XVA: Build Cube " << portfolio->size() << " x " << grid_->valuationDates().size() << " x " << samples_;
348 CONSOLEW(o.str());
349 LOG(o.str());
350
351 // set up progress indicators
352
353 auto progressBar = QuantLib::ext::make_shared<SimpleProgressBar>(o.str(), ConsoleLog::instance().width(), ConsoleLog::instance().progressBarWidth());
354 auto progressLog = QuantLib::ext::make_shared<ProgressLog>("XVA: Building cube", 100, oreSeverity::notice);
355
356 if(inputs_->nThreads() == 1) {
357
358 // single-threaded engine run
359
360 ValuationEngine engine(inputs_->asof(), grid_, simMarket_);
361 engine.registerProgressIndicator(progressBar);
362 engine.registerProgressIndicator(progressLog);
363 engine.buildCube(portfolio, cube_, calculators(), analytic()->configurations().scenarioGeneratorData->withMporStickyDate(),
364 nettingSetCube_, cptyCube_, cptyCalculators());
365 } else {
366
367 // multi-threaded engine run
368
369 /* TODO we assume no netting output cube is needed. Currently there are no valuation calculators in ore that require this cube. */
370
371 auto cubeFactory = [this](const QuantLib::Date& asof, const std::set<std::string>& ids,
372 const std::vector<QuantLib::Date>& dates,
373 const Size samples) -> QuantLib::ext::shared_ptr<NPVCube> {
374 if (cubeDepth_ == 1)
375 return QuantLib::ext::make_shared<SinglePrecisionInMemoryCube>(asof, ids, dates, samples, 0.0f);
376 else
377 return QuantLib::ext::make_shared<SinglePrecisionInMemoryCubeN>(asof, ids, dates, samples,
378 cubeDepth_, 0.0f);
379 };
380
381 std::function<QuantLib::ext::shared_ptr<NPVCube>(const QuantLib::Date&, const std::set<std::string>&,
382 const std::vector<QuantLib::Date>&,
383 const QuantLib::Size)>
384 cptyCubeFactory;
385 if (inputs_->storeSurvivalProbabilities()) {
386 cptyCubeFactory = [](const QuantLib::Date& asof, const std::set<std::string>& ids,
387 const std::vector<QuantLib::Date>& dates,
388 const Size samples) -> QuantLib::ext::shared_ptr<NPVCube> {
389 return QuantLib::ext::make_shared<SinglePrecisionInMemoryCube>(asof, ids, dates, samples, 0.0f);
390 };
391 } else {
392 cptyCubeFactory = [](const QuantLib::Date& asof, const std::set<std::string>& ids,
393 const std::vector<QuantLib::Date>& dates,
394 const Size samples) -> QuantLib::ext::shared_ptr<NPVCube> { return nullptr; };
395 }
396
398 inputs_->nThreads(), inputs_->asof(), grid_, samples_, analytic()->loader(), scenarioGenerator_,
399 inputs_->simulationPricingEngine(), inputs_->curveConfigs().get(),
400 analytic()->configurations().todaysMarketParams, inputs_->marketConfig("simulation"),
401 analytic()->configurations().simMarketParams, false, false, QuantLib::ext::make_shared<ScenarioFilter>(),
402 inputs_->refDataManager(), *inputs_->iborFallbackConfig(), true, false, false, cubeFactory, {},
403 cptyCubeFactory, "xva-simulation", offsetScenario_);
404
406 engine.registerProgressIndicator(progressBar);
407 engine.registerProgressIndicator(progressLog);
408
409 engine.buildCube(portfolio, calculators, cptyCalculators,
410 analytic()->configurations().scenarioGeneratorData->withMporStickyDate());
411
412 cube_ = QuantLib::ext::make_shared<JointNPVCube>(engine.outputCubes(), portfolio->ids());
413
414 if (inputs_->storeSurvivalProbabilities())
415 cptyCube_ = QuantLib::ext::make_shared<JointNPVCube>(
416 engine.outputCptyCubes(), portfolio->counterparties(), false,
417 [](Real a, Real x) { return std::max(a, x); }, 0.0);
418 }
419
420 CONSOLE("OK");
421
422 LOG("XVA::buildCube done");
423
424 Settings::instance().evaluationDate() = inputs_->asof();
425}
426
427QuantLib::ext::shared_ptr<EngineFactory>
428XvaAnalyticImpl::amcEngineFactory(const QuantLib::ext::shared_ptr<QuantExt::CrossAssetModel>& cam,
429 const std::vector<Date>& grid) {
430 LOG("XvaAnalytic::engineFactory() called");
431 QuantLib::ext::shared_ptr<EngineData> edCopy = QuantLib::ext::make_shared<EngineData>(*inputs_->amcPricingEngine());
432 edCopy->globalParameters()["GenerateAdditionalResults"] = "false";
433 edCopy->globalParameters()["RunType"] = "NPV";
434 map<MarketContext, string> configurations;
435 configurations[MarketContext::irCalibration] = inputs_->marketConfig("lgmcalibration");
436 configurations[MarketContext::fxCalibration] = inputs_->marketConfig("fxcalibration");
437 configurations[MarketContext::pricing] = inputs_->marketConfig("pricing");
438 ext::shared_ptr<ore::data::Market> market =
440 auto factory = QuantLib::ext::make_shared<EngineFactory>(
441 edCopy, market, configurations, inputs_->refDataManager(), *inputs_->iborFallbackConfig(),
442 EngineBuilderFactory::instance().generateAmcEngineBuilders(cam, grid), true);
443 return factory;
444}
445
447 LOG("XVA: buildAmcPortfolio");
448 const string msg = "XVA: Build AMC portfolio";
449 CONSOLEW(msg);
450 ProgressMessage(msg, 0, 1).log();
451
452 LOG("buildAmcPortfolio: Check sim dates");
453 std::vector<Date> simDates =
454 analytic()->configurations().scenarioGeneratorData->withCloseOutLag() && !analytic()->configurations().scenarioGeneratorData->withMporStickyDate() ?
455 analytic()->configurations().scenarioGeneratorData->getGrid()->dates() : analytic()->configurations().scenarioGeneratorData->getGrid()->valuationDates();
456
457 LOG("buildAmcPortfolio: Register additional engine builders");
458 auto factory = amcEngineFactory(model_, simDates);
459
460 LOG("buildAmcPortfolio: Load Portfolio");
461 QuantLib::ext::shared_ptr<Portfolio> portfolio = inputs_->portfolio();
462
463 LOG("Build Portfolio with AMC Engine factory and select amc-enabled trades")
464 amcPortfolio_ = QuantLib::ext::make_shared<Portfolio>();
465 for (auto const& [tradeId, trade] : portfolio->trades()) {
466 if (inputs_->amcTradeTypes().find(trade->tradeType()) != inputs_->amcTradeTypes().end()) {
467 try {
468 trade->reset();
469 trade->build(factory);
470 amcPortfolio_->add(trade);
471 DLOG("trade " << tradeId << " is added to amc portfolio");
472 } catch (const std::exception& e) {
473 StructuredTradeErrorMessage(trade, "Error building trade for AMC simulation", e.what()).log();
474 }
475 }
476 }
477 LOG("AMC portfolio built, size is " << amcPortfolio_->size());
478
479 CONSOLE("OK");
480 ProgressMessage(msg, 1, 1).log();
481
482 LOG("XVA: buildAmcPortfolio completed");
483}
484
485void XvaAnalyticImpl::amcRun(bool doClassicRun) {
486
487 LOG("XVA: amcRun");
488
489 if (scenarioData_.empty()) {
490 LOG("XVA: Create asd " << grid_->valuationDates().size() << " x " << samples_);
491 scenarioData_.linkTo(
492 QuantLib::ext::make_shared<InMemoryAggregationScenarioData>(grid_->valuationDates().size(), samples_));
493 simMarket_->aggregationScenarioData() = *scenarioData_;
494 }
495
497
498 std::string message = "XVA: Build AMC Cube " + std::to_string(amcPortfolio_->size()) + " x " +
499 std::to_string(grid_->valuationDates().size()) + " x " + std::to_string(samples_) + "... ";
500 auto progressBar = QuantLib::ext::make_shared<SimpleProgressBar>(message, ConsoleLog::instance().width(), ConsoleLog::instance().progressBarWidth());
501 auto progressLog = QuantLib::ext::make_shared<ProgressLog>("XVA: Building AMC Cube...", 100, oreSeverity::notice);
502
503 if (inputs_->nThreads() == 1) {
505 ext::shared_ptr<ore::data::Market> market = offsetScenario_ == nullptr ? analytic()->market() : offsetSimMarket_;
506
507 AMCValuationEngine amcEngine(model_, inputs_->scenarioGeneratorData(), market,
508 inputs_->exposureSimMarketParams()->additionalScenarioDataIndices(),
509 inputs_->exposureSimMarketParams()->additionalScenarioDataCcys(),
510 inputs_->exposureSimMarketParams()->additionalScenarioDataNumberOfCreditStates());
511 amcEngine.registerProgressIndicator(progressBar);
512 amcEngine.registerProgressIndicator(progressLog);
513 if (!scenarioData_.empty())
515 amcEngine.buildCube(amcPortfolio_, amcCube_);
516 } else {
517 auto cubeFactory = [this](const QuantLib::Date& asof, const std::set<std::string>& ids,
518 const std::vector<QuantLib::Date>& dates,
519 const Size samples) -> QuantLib::ext::shared_ptr<NPVCube> {
520 if (cubeDepth_ == 1)
521 return QuantLib::ext::make_shared<SinglePrecisionInMemoryCube>(asof, ids, dates, samples, 0.0f);
522 else
523 return QuantLib::ext::make_shared<SinglePrecisionInMemoryCubeN>(asof, ids, dates, samples,
524 cubeDepth_, 0.0f);
525 };
526
527 auto simMarketParams =
529
530 AMCValuationEngine amcEngine(
531 inputs_->nThreads(), inputs_->asof(), samples_, analytic()->loader(), inputs_->scenarioGeneratorData(),
532 inputs_->exposureSimMarketParams()->additionalScenarioDataIndices(),
533 inputs_->exposureSimMarketParams()->additionalScenarioDataCcys(),
534 inputs_->exposureSimMarketParams()->additionalScenarioDataNumberOfCreditStates(),
535 inputs_->crossAssetModelData(), inputs_->amcPricingEngine(), inputs_->curveConfigs().get(),
536 analytic()->configurations().todaysMarketParams, inputs_->marketConfig("lgmcalibration"),
537 inputs_->marketConfig("fxcalibration"), inputs_->marketConfig("eqcalibration"),
538 inputs_->marketConfig("infcalibration"), inputs_->marketConfig("crcalibration"),
539 inputs_->marketConfig("simulation"), inputs_->refDataManager(), *inputs_->iborFallbackConfig(), true,
540 cubeFactory, offsetScenario_, simMarketParams);
541
542 amcEngine.registerProgressIndicator(progressBar);
543 amcEngine.registerProgressIndicator(progressLog);
544 if (!scenarioData_.empty())
546 amcEngine.buildCube(amcPortfolio_);
547 amcCube_ = QuantLib::ext::make_shared<JointNPVCube>(amcEngine.outputCubes());
548 }
549
550 CONSOLE("OK");
551
552 LOG("XVA: amcRun completed");
553}
554
556 QuantLib::ext::shared_ptr<NettingSetManager> netting = inputs_->nettingSetManager();
557 QuantLib::ext::shared_ptr<CollateralBalances> balances = inputs_->collateralBalances();
558 map<string, bool> analytics;
559 analytics["exerciseNextBreak"] = inputs_->exerciseNextBreak();
560 analytics["cva"] = inputs_->cvaAnalytic();
561 analytics["dva"] = inputs_->dvaAnalytic();
562 analytics["fva"] = inputs_->fvaAnalytic();
563 analytics["colva"] = inputs_->colvaAnalytic();
564 analytics["collateralFloor"] = inputs_->collateralFloorAnalytic();
565 analytics["mva"] = inputs_->mvaAnalytic();
566 analytics["kva"] = inputs_->kvaAnalytic();
567 analytics["dim"] = inputs_->dimAnalytic();
568 analytics["dynamicCredit"] = inputs_->dynamicCredit();
569 analytics["cvaSensi"] = inputs_->cvaSensi();
570 analytics["flipViewXVA"] = inputs_->flipViewXVA();
571 analytics["creditMigration"] = inputs_->creditMigrationAnalytic();
572
573 string baseCurrency = inputs_->xvaBaseCurrency();
574 string calculationType = inputs_->collateralCalculationType();
575 string allocationMethod = inputs_->exposureAllocationMethod();
576 Real marginalAllocationLimit = inputs_->marginalAllocationLimit();
577 Real quantile = inputs_->pfeQuantile();
578 string dvaName = inputs_->dvaName();
579 string fvaLendingCurve = inputs_->fvaLendingCurve();
580 string fvaBorrowingCurve = inputs_->fvaBorrowingCurve();
581
582 Real dimQuantile = inputs_->dimQuantile();
583 Size dimHorizonCalendarDays = inputs_->dimHorizonCalendarDays();
584 Size dimRegressionOrder = inputs_->dimRegressionOrder();
585 vector<string> dimRegressors = inputs_->dimRegressors();
586 Size dimLocalRegressionEvaluations = inputs_->dimLocalRegressionEvaluations();
587 Real dimLocalRegressionBandwidth = inputs_->dimLocalRegressionBandwidth();
588
589 Real kvaCapitalDiscountRate = inputs_->kvaCapitalDiscountRate();
590 Real kvaAlpha = inputs_->kvaAlpha();
591 Real kvaRegAdjustment = inputs_->kvaRegAdjustment();
592 Real kvaCapitalHurdle = inputs_->kvaCapitalHurdle();
593 Real kvaOurPdFloor = inputs_->kvaOurPdFloor();
594 Real kvaTheirPdFloor = inputs_->kvaTheirPdFloor();
595 Real kvaOurCvaRiskWeight = inputs_->kvaOurCvaRiskWeight();
596 Real kvaTheirCvaRiskWeight = inputs_->kvaTheirCvaRiskWeight();
597
598 string marketConfiguration = inputs_->marketConfig("simulation");
599
600 bool fullInitialCollateralisation = inputs_->fullInitialCollateralisation();
601
602 checkConfigurations(analytic()->portfolio());
603
604 if (!dimCalculator_ && (analytics["mva"] || analytics["dim"])) {
605 if (inputs_->dimModel() == "Regression") {
606 LOG("dim calculator not set, create RegressionDynamicInitialMarginCalculator");
607 std::map<std::string, Real> currentIM;
608 if (inputs_->collateralBalances()) {
609 for (auto const& [n, b] : inputs_->collateralBalances()->collateralBalances()) {
610 currentIM[n.nettingSetId()] =
611 b->initialMargin() * (b->currency() == baseCurrency
612 ? 1.0
613 : analytic()
614 ->market()
615 ->fxRate(b->currency() + baseCurrency, marketConfiguration)
616 ->value());
617 }
618 }
619 dimCalculator_ = QuantLib::ext::make_shared<RegressionDynamicInitialMarginCalculator>(
620 inputs_, analytic()->portfolio(), cube_, cubeInterpreter_, *scenarioData_, dimQuantile,
621 dimHorizonCalendarDays, dimRegressionOrder, dimRegressors, dimLocalRegressionEvaluations,
622 dimLocalRegressionBandwidth, currentIM);
623 } else {
624 LOG("dim calculator not set, create FlatDynamicInitialMarginCalculator");
625 dimCalculator_ = QuantLib::ext::make_shared<FlatDynamicInitialMarginCalculator>(
627 }
628 }
629
630 std::vector<Period> cvaSensiGrid = inputs_->cvaSensiGrid();
631 Real cvaSensiShiftSize = inputs_->cvaSensiShiftSize();
632
633 string flipViewBorrowingCurvePostfix = inputs_->flipViewBorrowingCurvePostfix();
634 string flipViewLendingCurvePostfix = inputs_->flipViewLendingCurvePostfix();
635
636 LOG("baseCurrency " << baseCurrency);
637
638 auto market = offsetScenario_ == nullptr ? analytic()->market() : offsetSimMarket_;
639
640 postProcess_ = QuantLib::ext::make_shared<PostProcess>(
641 analytic()->portfolio(), netting, balances, market, marketConfiguration, cube_, *scenarioData_, analytics,
642 baseCurrency, allocationMethod, marginalAllocationLimit, quantile, calculationType, dvaName, fvaBorrowingCurve,
643 fvaLendingCurve, dimCalculator_, cubeInterpreter_, fullInitialCollateralisation, cvaSensiGrid,
644 cvaSensiShiftSize, kvaCapitalDiscountRate, kvaAlpha, kvaRegAdjustment, kvaCapitalHurdle, kvaOurPdFloor,
645 kvaTheirPdFloor, kvaOurCvaRiskWeight, kvaTheirCvaRiskWeight, cptyCube_, flipViewBorrowingCurvePostfix,
646 flipViewLendingCurvePostfix, inputs_->creditSimulationParameters(), inputs_->creditMigrationDistributionGrid(),
647 inputs_->creditMigrationTimeSteps(), creditStateCorrelationMatrix(),
648 analytic()->configurations().scenarioGeneratorData->withMporStickyDate(), inputs_->mporCashFlowMode());
649 LOG("post done");
650}
651
652void XvaAnalyticImpl::runAnalytic(const QuantLib::ext::shared_ptr<ore::data::InMemoryLoader>& loader,
653 const std::set<std::string>& runTypes) {
654
655 if(inputs_->amcCg()) {
656 LOG("XVA analytic is running with amc cg engine (experimental).");
657 // note: market configs both set to simulation, see note in xvaenginecg, we'd need inccy config in sim market there...
658 XvaEngineCG engine(inputs_->nThreads(), inputs_->asof(), loader, inputs_->curveConfigs().get(),
659 analytic()->configurations().todaysMarketParams,
660 analytic()->configurations().simMarketParams, inputs_->amcPricingEngine(),
661 inputs_->crossAssetModelData(), inputs_->scenarioGeneratorData(), inputs_->portfolio(),
662 inputs_->marketConfig("simulation"), inputs_->marketConfig("simulation"),
663 inputs_->xvaCgSensiScenarioData(), inputs_->refDataManager(), *inputs_->iborFallbackConfig(),
664 inputs_->xvaCgBumpSensis());
665
666 analytic()->reports()["XVA"]["xvacg-exposure"] = engine.exposureReport();
667 analytic()->reports()["XVA"]["xvacg-cva-sensi-scenario"] = engine.sensiReport();
668 return;
669 }
670
671 LOG("XVA analytic called with asof " << io::iso_date(inputs_->asof()));
672 ProgressMessage("Running XVA Analytic", 0, 1).log();
673
674 if (runTypes.find("EXPOSURE") != runTypes.end() || runTypes.empty())
675 runSimulation_ = true;
676
677 if (runTypes.find("XVA") != runTypes.end() || runTypes.empty())
678 runXva_ = true;
679
680 Settings::instance().evaluationDate() = inputs_->asof();
681 ObservationMode::instance().setMode(inputs_->exposureObservationModel());
682
683 const string msg = "XVA: Build Today's Market";
684 LOG(msg);
685 CONSOLEW(msg);
686 ProgressMessage(msg, 0, 1).log();
687 analytic()->buildMarket(loader);
688 CONSOLE("OK");
689 ProgressMessage(msg, 1, 1).log();
690
692 cubeInterpreter_ = QuantLib::ext::make_shared<CubeInterpretation>(
693 inputs_->storeFlows(), analytic()->configurations().scenarioGeneratorData->withCloseOutLag(), scenarioData_,
694 grid_, inputs_->storeCreditStateNPVs(), inputs_->flipViewXVA());
695
696 if (runSimulation_) {
697 LOG("XVA: Build simulation market");
699
700 LOG("XVA: Build Scenario Generator");
701 auto globalParams = inputs_->simulationPricingEngine()->globalParameters();
702 auto continueOnCalErr = globalParams.find("ContinueOnCalibrationError");
703 bool continueOnErr = (continueOnCalErr != globalParams.end()) && parseBool(continueOnCalErr->second);
704 buildScenarioGenerator(continueOnErr);
705
706 LOG("XVA: Attach Scenario Generator to ScenarioSimMarket");
707 simMarket_->scenarioGenerator() = scenarioGenerator_;
708
709 // We may have to build two cubes below for complementary sub-portfolios, a classical cube and an AMC cube
710 bool doClassicRun = true;
711 bool doAmcRun = false;
712
713 // Initialize the residual "classical" portfolio that we do not process using AMC
714 auto residualPortfolio = QuantLib::ext::make_shared<Portfolio>(inputs_->buildFailedTrades());
715
716 if (inputs_->amc()) {
717 // Build a separate sub-portfolio for the AMC cube generation and perform its training
719
720 // Build the residual portfolio for the classic cube generation, i.e. strip out the AMC part
721 for (auto const& [tradeId, trade] : inputs_->portfolio()->trades()) {
722 if (inputs_->amcTradeTypes().find(trade->tradeType()) == inputs_->amcTradeTypes().end())
723 residualPortfolio->add(trade);
724 }
725
726 LOG("AMC portfolio size " << amcPortfolio_->size());
727 LOG("Residual portfolio size " << residualPortfolio->size());
728
729 doAmcRun = !amcPortfolio_->trades().empty();
730 doClassicRun = !residualPortfolio->trades().empty();
731 } else {
732 for (const auto& [tradeId, trade] : inputs_->portfolio()->trades())
733 residualPortfolio->add(trade);
734 }
735
736 /********************************************************************************
737 * This is where we build cubes and the "classic" valuation work is done
738 * The bulk of the AMC work is done before in the AMC portfolio building/training
739 ********************************************************************************/
740
741 if (doAmcRun)
742 amcRun(doClassicRun);
743 else
744 amcPortfolio_ = QuantLib::ext::make_shared<Portfolio>(inputs_->buildFailedTrades());
745
746 if (doClassicRun)
747 classicPortfolio_ = classicRun(residualPortfolio);
748 else
749 classicPortfolio_ = QuantLib::ext::make_shared<Portfolio>(inputs_->buildFailedTrades());
750
751 /***************************************************
752 * We may have two cubes now that need to be merged
753 ***************************************************/
754
755 if (doClassicRun && doAmcRun) {
756 LOG("Joining classical and AMC cube");
757 cube_ = QuantLib::ext::make_shared<JointNPVCube>(cube_, amcCube_);
758 } else if (!doClassicRun && doAmcRun) {
759 LOG("We have generated an AMC cube only");
760 cube_ = amcCube_;
761 } else {
762 WLOG("We have generated a classic cube only");
763 }
764
765 LOG("NPV cube generation completed");
766
767 /***********************************************************************
768 * We may have two non-empty portfolios to be merged for post processing
769 ***********************************************************************/
770
771 LOG("Classic portfolio size " << classicPortfolio_->size());
772 LOG("AMC portfolio size " << amcPortfolio_->size());
773 auto newPortfolio = QuantLib::ext::make_shared<Portfolio>();
774 for (const auto& [tradeId, trade] : classicPortfolio_->trades())
775 newPortfolio->add(trade);
776 for (const auto& [tradeId, trade] : amcPortfolio_->trades())
777 newPortfolio->add(trade);
778 LOG("Total portfolio size " << newPortfolio->size());
779 if (newPortfolio->size() < inputs_->portfolio()->size()) {
780 ALOG("input portfolio size is " << inputs_->portfolio()->size() <<
781 ", but we have built only " << newPortfolio->size() << " trades");
782 }
783 analytic()->setPortfolio(newPortfolio);
784 } else { // runSimulation_
785
786 // build the portfolio linked to today's market
788
789 // ... and load a pre-built cube for post-processing
790
791 LOG("Skip cube generation, load input cubes for XVA");
792 const string msg = "XVA: Load Cubes";
793 CONSOLEW(msg);
794 ProgressMessage(msg, 0, 1).log();
795 QL_REQUIRE(inputs_->cube(), "XVA without EXPOSURE requires an NPV cube as input");
796 cube_= inputs_->cube();
797 QL_REQUIRE(inputs_->mktCube(), "XVA without EXPOSURE requires a market cube as input");
798 scenarioData_.linkTo(inputs_->mktCube());
799 if (inputs_->nettingSetCube())
800 nettingSetCube_= inputs_->nettingSetCube();
801 if (inputs_->cptyCube())
802 cptyCube_ = inputs_->cptyCube();
803 CONSOLE("OK");
804 ProgressMessage(msg, 1, 1).log();
805 }
806
807 MEM_LOG;
808
809 // Return the cubes to serialalize
810 if (inputs_->writeCube()) {
811 analytic()->npvCubes()["XVA"]["cube"] = cube_;
812 analytic()->mktCubes()["XVA"]["scenariodata"] = *scenarioData_;
813 if (nettingSetCube_) {
814 analytic()->npvCubes()["XVA"]["nettingsetcube"] = nettingSetCube_;
815 }
816 if (cptyCube_) {
817 analytic()->npvCubes()["XVA"]["cptycube"] = cptyCube_;
818 }
819 }
820
821 // Generate cube reports to inspect
822 if (inputs_->rawCubeOutput()) {
823 map<string, string> nettingSetMap = analytic()->portfolio()->nettingSetMap();
824 auto report = QuantLib::ext::make_shared<InMemoryReport>();
825 ReportWriter(inputs_->reportNaString()).writeCube(*report, cube_, nettingSetMap);
826 analytic()->reports()["XVA"]["rawcube"] = report;
827 }
828
829 if (runXva_) {
830
831 /*********************************************************************
832 * This is where the aggregation work is done: call the post-processor
833 *********************************************************************/
834
835 string msg = "XVA: Aggregation";
836 CONSOLEW(msg);
837 ProgressMessage(msg, 0, 1).log();
839 CONSOLE("OK");
840 ProgressMessage(msg, 1, 1).log();
841
842 /******************************************************
843 * Finally generate various (in-memory) reports/outputs
844 ******************************************************/
845
846 msg = "XVA: Reports";
847 CONSOLEW(msg);
848 ProgressMessage(msg, 0, 1).log();
849 LOG("Generating XVA reports and cube outputs");
850
851 if (inputs_->exposureProfilesByTrade()) {
852 for (const auto& [tradeId, tradeIdCubePos] : postProcess_->tradeIds()) {
853 auto report = QuantLib::ext::make_shared<InMemoryReport>();
854 try {
855 ReportWriter(inputs_->reportNaString()).writeTradeExposures(*report, postProcess_, tradeId);
856 analytic()->reports()["XVA"]["exposure_trade_" + tradeId] = report;
857 } catch (const std::exception& e) {
858 StructuredAnalyticsErrorMessage("Trade Exposure Report", "Error processing trade.", e.what(),
859 {{"tradeId", tradeId}})
860 .log();
861 }
862 }
863 }
864
865 if (inputs_->exposureProfiles()) {
866 for (auto [nettingSet, nettingSetPosInCube] : postProcess_->nettingSetIds()) {
867 auto exposureReport = QuantLib::ext::make_shared<InMemoryReport>();
868 try {
869 ReportWriter(inputs_->reportNaString())
870 .writeNettingSetExposures(*exposureReport, postProcess_, nettingSet);
871 analytic()->reports()["XVA"]["exposure_nettingset_" + nettingSet] = exposureReport;
872 } catch (const std::exception& e) {
873 StructuredAnalyticsErrorMessage("Netting Set Exposure Report", "Error processing netting set.",
874 e.what(), {{"nettingSetId", nettingSet}})
875 .log();
876 }
877
878 auto colvaReport = QuantLib::ext::make_shared<InMemoryReport>();
879 try {
880 ReportWriter(inputs_->reportNaString())
881 .writeNettingSetColva(*colvaReport, postProcess_, nettingSet);
882 analytic()->reports()["XVA"]["colva_nettingset_" + nettingSet] = colvaReport;
883 } catch (const std::exception& e) {
884 StructuredAnalyticsErrorMessage("Netting Set Colva Report", "Error processing netting set.",
885 e.what(), {{"nettingSetId", nettingSet}})
886 .log();
887 }
888
889 auto cvaSensiReport = QuantLib::ext::make_shared<InMemoryReport>();
890 try {
891 ReportWriter(inputs_->reportNaString())
892 .writeNettingSetCvaSensitivities(*cvaSensiReport, postProcess_, nettingSet);
893 analytic()->reports()["XVA"]["cva_sensitivity_nettingset_" + nettingSet] = cvaSensiReport;
894 } catch (const std::exception& e) {
895 StructuredAnalyticsErrorMessage("Cva Sensi Report", "Error processing netting set.", e.what(),
896 {{"nettingSetId", nettingSet}})
897 .log();
898 }
899 }
900 }
901
902 auto xvaReport = QuantLib::ext::make_shared<InMemoryReport>();
903 ReportWriter(inputs_->reportNaString())
904 .writeXVA(*xvaReport, inputs_->exposureAllocationMethod(), analytic()->portfolio(), postProcess_);
905 analytic()->reports()["XVA"]["xva"] = xvaReport;
906
907 if (inputs_->netCubeOutput()) {
908 auto report = QuantLib::ext::make_shared<InMemoryReport>();
909 ReportWriter(inputs_->reportNaString()).writeCube(*report, postProcess_->netCube());
910 analytic()->reports()["XVA"]["netcube"] = report;
911 }
912
913 if (inputs_->dimAnalytic() || inputs_->mvaAnalytic()) {
914 // Generate DIM evolution report
915 auto dimEvolutionReport = QuantLib::ext::make_shared<InMemoryReport>();
916 postProcess_->exportDimEvolution(*dimEvolutionReport);
917 analytic()->reports()["XVA"]["dim_evolution"] = dimEvolutionReport;
918
919 // Generate DIM regression reports
920 vector<QuantLib::ext::shared_ptr<ore::data::Report>> dimRegReports;
921 for (Size i = 0; i < inputs_->dimOutputGridPoints().size(); ++i) {
922 auto rep = QuantLib::ext::make_shared<InMemoryReport>();
923 dimRegReports.push_back(rep);
924 analytic()->reports()["XVA"]["dim_regression_" + std::to_string(i)] = rep;
925 }
926 postProcess_->exportDimRegression(inputs_->dimOutputNettingSet(), inputs_->dimOutputGridPoints(),
927 dimRegReports);
928 }
929
930 if (inputs_->creditMigrationAnalytic()) {
931 QL_REQUIRE(
932 postProcess_->creditMigrationPdf().size() == inputs_->creditMigrationTimeSteps().size(),
933 "XvaAnalyticImpl::runAnalytic(): inconsistent post process results for credit migration pdf / cdf ("
934 << postProcess_->creditMigrationPdf().size() << ") and input credit migration time steps ("
935 << inputs_->creditMigrationTimeSteps().size() << ")");
936 for (Size i = 0; i < postProcess_->creditMigrationPdf().size(); ++i) {
937 auto rep = QuantLib::ext::make_shared<InMemoryReport>();
938 analytic()
939 ->reports()["XVA"]["credit_migration_" + std::to_string(inputs_->creditMigrationTimeSteps()[i])] =
940 rep;
941 (*rep)
942 .addColumn("upperBucketBound", double(), 6)
943 .addColumn("pdf", double(), 8)
944 .addColumn("cdf", double(), 8);
945 for (Size j = 0; j < postProcess_->creditMigrationPdf()[i].size(); ++j) {
946 (*rep)
947 .next()
948 .add(postProcess_->creditMigrationUpperBucketBounds()[j])
949 .add(postProcess_->creditMigrationPdf()[i][j])
950 .add(postProcess_->creditMigrationCdf()[i][j]);
951 }
952 rep->end();
953 }
954 }
955
956 CONSOLE("OK");
957 ProgressMessage(msg, 1, 1).log();
958 }
959
960 // reset that mode
961 ObservationMode::instance().setMode(inputs_->observationModel());
962 ProgressMessage("Running XVA Analytic", 1, 1).log();
963}
964
965Matrix XvaAnalyticImpl::creditStateCorrelationMatrix() const {
966
968 for (auto const& [pair, value] : analytic()->configurations().crossAssetModelData->correlations()) {
969 cmb.addCorrelation(pair.first, pair.second, value);
970 }
971
973 processInfo[CrossAssetModel::AssetType::CrState] = {
974 {"CrState", analytic()->configurations().simMarketParams->numberOfCreditStates()}};
975
976 return cmb.correlationMatrix(processInfo);
977}
978
979
980} // namespace analytics
981} // namespace ore
valuation engine for amc
std::vector< QuantLib::ext::shared_ptr< ore::analytics::NPVCube > > outputCubes() const
void buildCube(const QuantLib::ext::shared_ptr< ore::data::Portfolio > &portfolio, QuantLib::ext::shared_ptr< ore::analytics::NPVCube > &outputCube)
build cube in single threaded run
QuantLib::ext::shared_ptr< ore::analytics::AggregationScenarioData > & aggregationScenarioData()
Set aggregation data.
Analytic * analytic() const
Definition: analytic.hpp:193
const std::string & label() const
Definition: analytic.hpp:190
QuantLib::ext::shared_ptr< InputParameters > inputs_
Definition: analytic.hpp:216
analytic_reports & reports()
Result reports.
Definition: analytic.hpp:131
analytic_npvcubes & npvCubes()
Definition: analytic.hpp:132
Configurations & configurations()
Definition: analytic.hpp:128
void setPortfolio(const QuantLib::ext::shared_ptr< ore::data::Portfolio > &portfolio)
Definition: analytic.hpp:125
virtual void buildMarket(const QuantLib::ext::shared_ptr< ore::data::InMemoryLoader > &loader, const bool marketRequired=true)
Definition: analytic.cpp:178
const QuantLib::ext::shared_ptr< ore::data::Portfolio > & portfolio() const
Definition: analytic.hpp:122
const QuantLib::ext::shared_ptr< ore::data::Market > & market() const
Definition: analytic.hpp:117
analytic_mktcubes & mktCubes()
Definition: analytic.hpp:133
virtual void buildPortfolio()
Definition: analytic.cpp:222
std::vector< QuantLib::ext::shared_ptr< ore::analytics::NPVCube > > outputCubes() const
void setAggregationScenarioData(const QuantLib::ext::shared_ptr< AggregationScenarioData > &aggregationScenarioData)
std::vector< QuantLib::ext::shared_ptr< ore::analytics::NPVCube > > outputCptyCubes() const
void buildCube(const QuantLib::ext::shared_ptr< ore::data::Portfolio > &portfolio, const std::function< std::vector< QuantLib::ext::shared_ptr< ore::analytics::ValuationCalculator > >()> &calculators, const std::function< std::vector< QuantLib::ext::shared_ptr< ore::analytics::CounterpartyCalculator > >()> &cptyCalculators={}, bool mporStickyDate=true, bool dryRun=false)
Write ORE outputs to reports.
virtual void writeCube(ore::data::Report &report, const QuantLib::ext::shared_ptr< NPVCube > &cube, const std::map< std::string, std::string > &nettingSetMap=std::map< std::string, std::string >())
virtual void writeNettingSetCvaSensitivities(ore::data::Report &report, QuantLib::ext::shared_ptr< PostProcess > postProcess, const std::string &nettingSetId)
virtual void writeNettingSetExposures(ore::data::Report &report, QuantLib::ext::shared_ptr< PostProcess > postProcess, const std::string &nettingSetId)
virtual void writeTradeExposures(ore::data::Report &report, QuantLib::ext::shared_ptr< PostProcess > postProcess, const std::string &tradeId)
virtual void writeNettingSetColva(ore::data::Report &report, QuantLib::ext::shared_ptr< PostProcess > postProcess, const std::string &nettingSetId)
QuantLib::ext::shared_ptr< ScenarioGenerator > build(QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > model, QuantLib::ext::shared_ptr< ScenarioFactory > sf, QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > marketConfig, Date asof, QuantLib::ext::shared_ptr< ore::data::Market > initMarket, const std::string &configuration=ore::data::Market::defaultConfiguration, const QuantLib::ext::shared_ptr< PathGeneratorFactory > &pf=QuantLib::ext::make_shared< MultiPathGeneratorFactory >())
Build function.
void buildCube(const QuantLib::ext::shared_ptr< data::Portfolio > &portfolio, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCube, std::vector< QuantLib::ext::shared_ptr< ValuationCalculator > > calculators, bool mporStickyDate=true, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCubeNettingSet=nullptr, QuantLib::ext::shared_ptr< analytics::NPVCube > outputCptyCube=nullptr, std::vector< QuantLib::ext::shared_ptr< CounterpartyCalculator > > cptyCalculators={}, bool dryRun=false)
Build NPV cube.
void setUpConfigurations() override
Definition: xvaanalytic.cpp:49
void buildClassicCube(const QuantLib::ext::shared_ptr< Portfolio > &portfolio)
QuantLib::ext::shared_ptr< ScenarioSimMarket > simMarketCalibration_
Definition: xvaanalytic.hpp:72
QuantLib::ext::shared_ptr< NPVCube > amcCube_
Definition: xvaanalytic.hpp:78
QuantLib::ext::shared_ptr< CubeInterpretation > cubeInterpreter_
Definition: xvaanalytic.hpp:80
virtual void runAnalytic(const QuantLib::ext::shared_ptr< ore::data::InMemoryLoader > &loader, const std::set< std::string > &runTypes={}) override
void amcRun(bool doClassicRun)
QuantLib::ext::shared_ptr< ScenarioSimMarket > simMarket_
Definition: xvaanalytic.hpp:71
QuantLib::ext::shared_ptr< ScenarioGenerator > scenarioGenerator_
Definition: xvaanalytic.hpp:76
QuantLib::RelinkableHandle< AggregationScenarioData > scenarioData_
Definition: xvaanalytic.hpp:79
QuantLib::ext::shared_ptr< EngineFactory > engineFactory_
Definition: xvaanalytic.hpp:74
QuantLib::ext::shared_ptr< DateGrid > grid_
Definition: xvaanalytic.hpp:86
QuantLib::ext::shared_ptr< CrossAssetModel > model_
Definition: xvaanalytic.hpp:75
QuantLib::ext::shared_ptr< Portfolio > amcPortfolio_
Definition: xvaanalytic.hpp:77
QuantLib::ext::shared_ptr< EngineFactory > amcEngineFactory(const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > &cam, const std::vector< Date > &grid)
void checkConfigurations(const QuantLib::ext::shared_ptr< Portfolio > &portfolio)
Definition: xvaanalytic.cpp:57
QuantLib::ext::shared_ptr< DynamicInitialMarginCalculator > dimCalculator_
Definition: xvaanalytic.hpp:81
void initClassicRun(const QuantLib::ext::shared_ptr< Portfolio > &portfolio)
QuantLib::ext::shared_ptr< Scenario > offsetScenario_
Definition: xvaanalytic.hpp:83
QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > offsetSimMarketParams_
Definition: xvaanalytic.hpp:84
void buildScenarioGenerator(bool continueOnError)
void buildCrossAssetModel(bool continueOnError)
QuantLib::ext::shared_ptr< NPVCube > cptyCube_
Definition: xvaanalytic.hpp:78
QuantLib::ext::shared_ptr< ore::data::EngineFactory > engineFactory() override
build an engine factory
Definition: xvaanalytic.cpp:92
void initCube(QuantLib::ext::shared_ptr< NPVCube > &cube, const std::set< std::string > &ids, Size cubeDepth)
QuantLib::ext::shared_ptr< Portfolio > classicRun(const QuantLib::ext::shared_ptr< Portfolio > &portfolio)
QuantLib::ext::shared_ptr< PostProcess > postProcess_
Definition: xvaanalytic.hpp:82
QuantLib::ext::shared_ptr< Portfolio > classicPortfolio_
Definition: xvaanalytic.hpp:77
Matrix creditStateCorrelationMatrix() const
QuantLib::ext::shared_ptr< NPVCube > cube_
Definition: xvaanalytic.hpp:78
QuantLib::ext::shared_ptr< ScenarioSimMarket > offsetSimMarket_
Definition: xvaanalytic.hpp:73
QuantLib::ext::shared_ptr< NPVCube > nettingSetCube_
Definition: xvaanalytic.hpp:78
QuantLib::ext::shared_ptr< InMemoryReport > sensiReport()
Definition: xvaenginecg.hpp:68
QuantLib::ext::shared_ptr< InMemoryReport > exposureReport()
Definition: xvaenginecg.hpp:67
QuantLib::Matrix correlationMatrix(const std::vector< std::string > &ccys)
void addCorrelation(const std::string &factor1, const std::string &factor2, QuantLib::Real correlation)
std::map< QuantExt::CrossAssetModel::AssetType, std::vector< std::pair< std::string, QuantLib::Size > > > ProcessInfo
Handle< QuantExt::CrossAssetModel > model() const
void registerProgressIndicator(const QuantLib::ext::shared_ptr< ProgressIndicator > &indicator)
SafeStack< ValueType > value
The counterparty cube calculator interface.
Dynamic Initial Margin calculator by regression.
bool parseBool(const string &s)
join n cubes in terms of stored ids
#define MEM_LOG
#define LOG(text)
#define DLOG(text)
#define ALOG(text)
#define CONSOLEW(text)
#define WLOG(text)
#define CONSOLE(text)
#define TLOG(text)
The cube valuation calculator interface.
a calculator that computes npvs for a vector of credit states
multi-threaded valuation engine
RandomVariable log(RandomVariable x)
Size size(const ValueType &v)
Singleton class to hold global Observation Mode.
A Class to write ORE outputs to reports.
ScenarioWriter class.
factory classes for simple scenarios
QuantLib::ext::shared_ptr< ore::analytics::CrossAssetModelData > crossAssetModelData
Definition: analytic.hpp:72
QuantLib::ext::shared_ptr< ore::data::TodaysMarketParameters > todaysMarketParams
Definition: analytic.hpp:68
QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > simMarketParams
Definition: analytic.hpp:69
QuantLib::ext::shared_ptr< ore::analytics::ScenarioGeneratorData > scenarioGeneratorData
Definition: analytic.hpp:71
Structured analytics error.
Class for structured analytics warnings.
Date asof(14, Jun, 2018)
xva engine using cg infrastructure