@@ -222,19 +222,27 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
222222 bool runTradeLevel = tradeLevel && sensitivityStream_;
223223
224224 // Local P&L vectors to hold _all_ historical P&Ls
225- auto nScenarios = hisScenGen_->numScenarios ();
225+ Size nScenarios = hisScenGen_->numScenarios ();
226+ Size nCalculators = pnlCalculators.size ();
226227 vector<Real> allPnls (hisScenGen_->numScenarios (), 0.0 );
227228 vector<Real> allFoPnls (hisScenGen_->numScenarios (), 0.0 );
228-
229+
230+ // calculators,scenarios, trades
229231 using TradePnLStore = std::vector<std::vector<QuantLib::Real>>;
230- TradePnLStore tradePnls, foTradePnls;
232+ std::vector< TradePnLStore> tradePnls, foTradePnls;
231233
232234 // We may need to store trade level P&Ls.
233235 if (runTradeLevel) {
234236 tradePnls.clear ();
235- tradePnls.reserve (nScenarios );
237+ tradePnls.reserve (nCalculators );
236238 foTradePnls.clear ();
237- foTradePnls.reserve (nScenarios);
239+ foTradePnls.reserve (nCalculators);
240+ for (Size i = 0 ; i < nCalculators; i++) {
241+ tradePnls.push_back (std::vector<std::vector<QuantLib::Real>>());
242+ tradePnls.at (i).reserve (nScenarios);
243+ foTradePnls.push_back (std::vector<std::vector<QuantLib::Real>>());
244+ foTradePnls.at (i).reserve (nScenarios);
245+ }
238246 }
239247
240248 hisScenGen_->reset ();
@@ -252,14 +260,13 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
252260
253261 // Add trade level P&L vector if needed.
254262 if (runTradeLevel) {
255- bool inPeriod = false ;
256- for (const auto & c : pnlCalculators) {
257- if (c->isInTimePeriod (hisScenGen_->startDates ()[i], hisScenGen_->endDates ()[i]))
258- inPeriod = true ;
259- }
260- if (inPeriod) {
261- tradePnls.push_back (vector<Real>(tradeIds.size (), 0.0 ));
262- foTradePnls.push_back (vector<Real>(tradeIds.size (), 0.0 ));
263+ for (Size j = 0 ; j < pnlCalculators.size (); j++) {
264+ bool inPeriod =
265+ pnlCalculators.at (j)->isInTimePeriod (hisScenGen_->startDates ()[i], hisScenGen_->endDates ()[i]);
266+ if (inPeriod) {
267+ tradePnls.at (j).push_back (vector<Real>(tradeIds.size (), 0.0 ));
268+ foTradePnls.at (j).push_back (vector<Real>(tradeIds.size (), 0.0 ));
269+ }
263270 }
264271 }
265272
@@ -282,9 +289,11 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
282289 if (includeGammaMargin)
283290 allPnls[i] += gammaPnl;
284291
285- for (const auto & c : pnlCalculators) {
286- if (c->isInTimePeriod (hisScenGen_->startDates ()[i], hisScenGen_->endDates ()[i])) {
287- c->writePNL (i, true , sr.key_1 , shift, sr.delta , sr.gamma , deltaPnl, gammaPnl);
292+ for (Size k = 0 ; k < pnlCalculators.size (); k++) {
293+ if (pnlCalculators.at (k)->isInTimePeriod (hisScenGen_->startDates ()[i],
294+ hisScenGen_->endDates ()[i])) {
295+ pnlCalculators.at (k)->writePNL (i, true , sr.key_1 , shift, sr.delta , sr.gamma , deltaPnl,
296+ gammaPnl);
288297 if (!tradeSensiCache.empty ()) {
289298 auto itSr = tradeSensiCache.find (j);
290299 if (itSr != tradeSensiCache.end ()) {
@@ -295,15 +304,16 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
295304 Real tradeGamma = kv.second .second ;
296305 Real tradeGammaPnl = 0.5 * shift * shift * tradeGamma;
297306 // Attempt to write trade level P&L contribution row.
298- c->writePNL (i, true , sr.key_1 , shift, tradeDelta, tradeGamma, tradeDeltaPnl,
299- tradeGammaPnl, RiskFactorKey (), 0.0 , tradeId);
307+ pnlCalculators.at (k)->writePNL (i, true , sr.key_1 , shift, tradeDelta, tradeGamma,
308+ tradeDeltaPnl, tradeGammaPnl, RiskFactorKey (), 0.0 ,
309+ tradeId);
300310 // Update the sensitivity based trade level P&Ls
301311 if (runTradeLevel) {
302- foTradePnls.back ()[kv.first ] += tradeDeltaPnl;
312+ foTradePnls.at (k). back ()[kv.first ] += tradeDeltaPnl;
303313 if (includeDeltaMargin)
304- tradePnls.back ()[kv.first ] += tradeDeltaPnl;
314+ tradePnls.at (k). back ()[kv.first ] += tradeDeltaPnl;
305315 if (includeGammaMargin)
306- tradePnls.back ()[kv.first ] += tradeGammaPnl;
316+ tradePnls.at (k). back ()[kv.first ] += tradeGammaPnl;
307317 }
308318 }
309319 }
@@ -319,7 +329,8 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
319329 if (includeGammaMargin)
320330 allPnls[i] += gammaPnl;
321331
322- for (const auto & c : pnlCalculators) {
332+ for (Size j = 0 ; j < pnlCalculators.size (); j++) {
333+ const auto & c = pnlCalculators[j];
323334 if (c->isInTimePeriod (hisScenGen_->startDates ()[i], hisScenGen_->endDates ()[i])) {
324335 c->writePNL (i, true , sr.key_1 , shift_1, sr.delta , sr.gamma , 0.0 , gammaPnl, sr.key_2 , shift_2);
325336 if (!tradeSensiCache.empty ()) {
@@ -334,7 +345,7 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
334345 sr.key_2 , shift_2, tradeId);
335346 // Update the sensitivity based trade level P&Ls
336347 if (runTradeLevel && includeGammaMargin) {
337- tradePnls.back ()[kv.first ] += tradeGammaPnl;
348+ tradePnls.at (j). back ()[kv.first ] += tradeGammaPnl;
338349 }
339350 }
340351 }
@@ -351,10 +362,10 @@ void HistoricalSensiPnlCalculator::calculateSensiPnl(
351362 covarianceCalculator->populateCovariance (keys);
352363
353364 LOG (" Populate the sensitivity backtesting P&L vectors" );
354- for (const auto & c : pnlCalculators) {
355- c ->populatePNLs (allPnls, allFoPnls, hisScenGen_->startDates (), hisScenGen_->endDates ());
365+ for (Size j = 0 ; j < pnlCalculators. size (); j++ ) {
366+ pnlCalculators. at (j) ->populatePNLs (allPnls, allFoPnls, hisScenGen_->startDates (), hisScenGen_->endDates ());
356367 if (runTradeLevel)
357- c ->populateTradePNLs (tradePnls, foTradePnls);
368+ pnlCalculators. at (j) ->populateTradePNLs (tradePnls. at (j) , foTradePnls. at (j) );
358369 }
359370}
360371
0 commit comments