52 {
53
54 Settings::instance().evaluationDate() =
inputs_->asof();
55 ObservationMode::instance().setMode(
inputs_->observationModel());
56
57 QL_REQUIRE(
inputs_->portfolio(),
"PricingAnalytic::run: No portfolio loaded.");
58
62
63 CONSOLEW(
"Pricing: Build Portfolio");
66
67
68 for (const auto& rt : runTypes) {
69 if (std::find(
analytic()->analyticTypes().begin(),
analytic()->analyticTypes().end(), rt) ==
71 DLOG(
"requested analytic " << rt <<
" not covered by the PricingAnalytic");
72 }
73 }
74
75
76
78
79 for (
const auto& type :
analytic()->analyticTypes()) {
80 QuantLib::ext::shared_ptr<InMemoryReport> report = QuantLib::ext::make_shared<InMemoryReport>();
82
83 if (runTypes.find(type) == runTypes.end())
84 continue;
85
86 std::string effectiveResultCurrency =
88 if (type == "NPV") {
90 ReportWriter(
inputs_->reportNaString())
91 .writeNpv(*report, effectiveResultCurrency,
analytic()->market(),
inputs_->marketConfig(
"pricing"),
95 if (
inputs_->outputAdditionalResults()) {
96 CONSOLEW(
"Pricing: Additional Results");
97 QuantLib::ext::shared_ptr<InMemoryReport> addReport = QuantLib::ext::make_shared<InMemoryReport>();;
98 ReportWriter(
inputs_->reportNaString())
99 .writeAdditionalResultsReport(*addReport,
analytic()->portfolio(),
analytic()->market(),
100 effectiveResultCurrency,
inputs_->additionalResultsReportPrecision());
103 }
106 LOG(
"Write curves report");
107 QuantLib::ext::shared_ptr<InMemoryReport> curvesReport = QuantLib::ext::make_shared<InMemoryReport>();
109 std::string config =
inputs_->curvesMarketConfig();
110 ReportWriter(
inputs_->reportNaString())
111 .writeCurves(*curvesReport, config, grid, *
inputs_->todaysMarketParams(),
115 }
116 }
117 else if (type == "CASHFLOW") {
118 CONSOLEW(
"Pricing: Cashflow Report");
119 string marketConfig =
inputs_->marketConfig(
"pricing");
120 ReportWriter(
inputs_->reportNaString())
121 .writeCashflow(*report, effectiveResultCurrency,
analytic()->portfolio(),
123 marketConfig,
inputs_->includePastCashflows());
126 }
127 else if (type == "CASHFLOWNPV") {
128 CONSOLEW(
"Pricing: Cashflow NPV report");
129 string marketConfig =
inputs_->marketConfig(
"pricing");
130 ReportWriter(
inputs_->reportNaString())
131 .writeCashflow(tmpReport, effectiveResultCurrency,
analytic()->portfolio(),
133 marketConfig,
inputs_->includePastCashflows());
134 ReportWriter(
inputs_->reportNaString())
135 .writeCashflowNpv(*report, tmpReport,
analytic()->market(), marketConfig,
136 effectiveResultCurrency,
inputs_->cashflowHorizon());
139 }
140 else if (type == "SENSITIVITY") {
141 CONSOLEW(
"Risk: Sensitivity Report");
142 LOG(
"Sensi Analysis - Initialise");
143 bool recalibrateModels = true;
144 bool ccyConv = false;
145 std::string configuration =
inputs_->marketConfig(
"pricing");
146 QuantLib::ext::shared_ptr<SensitivityAnalysis> sensiAnalysis;
147 if (
inputs_->nThreads() == 1) {
148 LOG(
"Single-threaded sensi analysis");
149 sensiAnalysis = QuantLib::ext::make_shared<SensitivityAnalysis>(
151 analytic()->configurations().simMarketParams,
analytic()->configurations().sensiScenarioData,
152 recalibrateModels,
analytic()->configurations().curveConfig,
153 analytic()->configurations().todaysMarketParams, ccyConv,
inputs_->refDataManager(),
155 LOG(
"Single-threaded sensi analysis created");
156 }
157 else {
158 LOG(
"Multi-threaded sensi analysis");
159 sensiAnalysis = QuantLib::ext::make_shared<SensitivityAnalysis>(
161 inputs_->pricingEngine(),
analytic()->configurations().simMarketParams,
162 analytic()->configurations().sensiScenarioData, recalibrateModels,
163 analytic()->configurations().curveConfig,
analytic()->configurations().todaysMarketParams, ccyConv,
165 LOG(
"Multi-threaded sensi analysis created");
166 }
167
169 QuantLib::ext::shared_ptr<ParSensitivityAnalysis> parAnalysis = nullptr;
171 parAnalysis= QuantLib::ext::make_shared<ParSensitivityAnalysis>(
173 *
analytic()->configurations().sensiScenarioData,
"",
174 true, typesDisabled);
176 LOG(
"Sensi analysis - align pillars (for the par conversion or because alignPillars is enabled)");
177 parAnalysis->alignPillars();
178 sensiAnalysis->overrideTenors(true);
179 } else {
180 LOG(
"Sensi analysis - skip aligning pillars");
181 }
182 }
183
184 LOG(
"Sensi analysis - generate");
185 sensiAnalysis->registerProgressIndicator(QuantLib::ext::make_shared<ProgressLog>("sensitivities", 100, oreSeverity::notice));
186 sensiAnalysis->generateSensitivities();
187
188 LOG(
"Sensi analysis - write sensitivity report in memory");
189 auto baseCurrency = sensiAnalysis->simMarketData()->baseCcy();
190 auto ss = QuantLib::ext::make_shared<SensitivityCubeStream>(sensiAnalysis->sensiCubes(), baseCurrency);
191 ReportWriter(
inputs_->reportNaString())
192 .writeSensitivityReport(*report, ss,
inputs_->sensiThreshold());
194
195 LOG(
"Sensi analysis - write sensitivity scenario report in memory");
196 QuantLib::ext::shared_ptr<InMemoryReport> scenarioReport = QuantLib::ext::make_shared<InMemoryReport>();
197 ReportWriter(
inputs_->reportNaString())
198 .writeScenarioReport(*scenarioReport, sensiAnalysis->sensiCubes(),
201
202 auto simmSensitivityConfigReport = QuantLib::ext::make_shared<InMemoryReport>();
203 ReportWriter(
inputs_->reportNaString())
204 .writeSensitivityConfigReport(*simmSensitivityConfigReport,
205 sensiAnalysis->scenarioGenerator()->shiftSizes(),
206 sensiAnalysis->scenarioGenerator()->baseValues(),
207 sensiAnalysis->scenarioGenerator()->keyToFactor());
208 analytic()->
reports()[type][
"sensitivity_config"] = simmSensitivityConfigReport;
209
211 LOG(
"Sensi analysis - par conversion");
212
213 if (
inputs_->optimiseRiskFactors()){
214 std::set<RiskFactorKey> collectRiskFactors;
215
216 for(auto const& c : sensiAnalysis->sensiCubes()){
217 auto currentRF = c->relevantRiskFactors();
218
219 collectRiskFactors.insert(currentRF.begin(), currentRF.end());
220 }
221 parAnalysis->relevantRiskFactors() = collectRiskFactors;
222 LOG(
"optimiseRiskFactors active : parSensi risk factors set to zeroSensi risk factors");
223 }
224 parAnalysis->computeParInstrumentSensitivities(sensiAnalysis->simMarket());
225 QuantLib::ext::shared_ptr<ParSensitivityConverter> parConverter =
226 QuantLib::ext::make_shared<ParSensitivityConverter>(parAnalysis->parSensitivities(), parAnalysis->shiftSizes());
227 auto parCube = QuantLib::ext::make_shared<ZeroToParCube>(sensiAnalysis->sensiCubes(), parConverter, typesDisabled, true);
228 LOG(
"Sensi analysis - write par sensitivity report in memory");
229 QuantLib::ext::shared_ptr<ParSensitivityCubeStream> pss =
230 QuantLib::ext::make_shared<ParSensitivityCubeStream>(parCube, baseCurrency);
231
232
233 QuantLib::ext::shared_ptr<InMemoryReport> parSensiReport = QuantLib::ext::make_shared<InMemoryReport>();
234 ReportWriter(
inputs_->reportNaString())
235 .writeSensitivityReport(*parSensiReport, pss,
inputs_->sensiThreshold());
237
239 QuantLib::ext::shared_ptr<InMemoryReport> jacobiReport = QuantLib::ext::make_shared<InMemoryReport>();
242
243 QuantLib::ext::shared_ptr<InMemoryReport> jacobiInverseReport = QuantLib::ext::make_shared<InMemoryReport>();
244 parConverter->writeConversionMatrix(*jacobiInverseReport);
246 }
247 }
248 else {
249 LOG(
"Sensi Analysis - skip par conversion");
250 }
251
252 LOG(
"Sensi Analysis - Completed");
254 }
255 else {
256 QL_FAIL("PricingAnalytic type " << type << " invalid");
257 }
258 }
259}
Analytic * analytic() const
QuantLib::ext::shared_ptr< InputParameters > inputs_
analytic_reports & reports()
Result reports.
virtual void modifyPortfolio()
virtual void buildMarket(const QuantLib::ext::shared_ptr< ore::data::InMemoryLoader > &loader, const bool marketRequired=true)
virtual void buildPortfolio()
void writeParConversionMatrix(const ParSensitivityAnalysis::ParContainer &parSensitivities, Report &report)
Write par instrument sensitivity report.