@@ -197,20 +197,29 @@ void GaussianCam::performCalculations() const {
197197 }
198198
199199 indexPositionInProcess_.clear ();
200+ eqIndexInCam_.resize (indices_.size ());
201+ comIndexInCam_.resize (indices_.size ());
202+ std::fill (eqIndexInCam_.begin (), eqIndexInCam_.end (), Null<Size>());
203+ std::fill (comIndexInCam_.begin (), comIndexInCam_.end (), Null<Size>());
200204 for (Size i = 0 ; i < indices_.size (); ++i) {
201205 if (indices_[i].isFx ()) {
202206 // FX
203207 Size ccyIdx = cam_->ccyIndex (parseCurrency (indexCurrencies_[i]));
204208 QL_REQUIRE (ccyIdx > 0 , " fx index '" << indices_[i] << " ' has unexpected for ccy = base ccy" );
205209 indexPositionInProcess_.push_back (cam_->pIdx (CrossAssetModel::AssetType::FX, ccyIdx - 1 ));
206- eqIndexInCam_.push_back (Null<Size>());
207210 } else if (indices_[i].isEq ()) {
208211 // EQ
209212 Size eqIdx = cam_->eqIndex (indices_[i].eq ()->name ());
210213 indexPositionInProcess_.push_back (cam_->pIdx (CrossAssetModel::AssetType::EQ, eqIdx));
211- eqIndexInCam_.push_back (eqIdx);
214+ eqIndexInCam_[i] = eqIdx;
215+ } else if (indices_[i].isComm ()) {
216+ // COM
217+ Size comIdx = cam_->comIndex (indices_[i].commName ());
218+ indexPositionInProcess_.push_back (cam_->pIdx (CrossAssetModel::AssetType::COM, comIdx));
219+ comIndexInCam_[i] = comIdx;
212220 } else {
213- QL_FAIL (" index '" << indices_[i].name () << " ' expected to be FX or EQ" );
221+ QL_FAIL (" GuassianCam::performCalculations(): index '" << indices_[i].name ()
222+ << " ' expected to be FX, EQ, COMM" );
214223 }
215224 }
216225
@@ -233,7 +242,7 @@ void GaussianCam::populatePathValues(const Size nSamples, std::map<Date, std::ve
233242
234243 // set reference date values, if there are no future simulation dates, we are done
235244
236- // FX and EQ indcies
245+ // FX, EQ, COMM indcies
237246 for (Size k = 0 ; k < indices_.size (); ++k) {
238247 paths[referenceDate_][k].setAll (process->initialValues ().at (indexPositionInProcess_[k]));
239248 }
@@ -351,7 +360,7 @@ void GaussianCam::populatePathValues(const Size nSamples, std::map<Date, std::ve
351360 }
352361 }
353362
354- // FX and EQ indcies
363+ // FX, EQ, COMM indices
355364 std::vector<std::vector<RandomVariable*>> rvs (
356365 indices_.size (), std::vector<RandomVariable*>(effectiveSimulationDates_.size () - 1 ));
357366 auto date = effectiveSimulationDates_.begin ();
@@ -417,8 +426,17 @@ void GaussianCam::populatePathValues(const Size nSamples, std::map<Date, std::ve
417426
418427RandomVariable GaussianCam::getIndexValue (const Size indexNo, const Date& d, const Date& fwd) const {
419428 auto res = underlyingPaths_.at (d).at (indexNo);
420- // compute forwarding factor
421- if (fwd != Null<Date>()) {
429+ if (comIndexInCam_[indexNo] != Null<Size>()) {
430+ // handle com (TODO: performace optimization via vectorized version of com model)
431+ RandomVariable tmp (res.size ());
432+ for (Size i = 0 ; i < tmp.size (); ++i) {
433+ tmp.set (i, cam_->comModel (comIndexInCam_[indexNo])
434+ ->forwardPrice (timeFromReference (d), timeFromReference (fwd != Null<Date>() ? fwd : d),
435+ Array (1 , std::log (res[i]))));
436+ }
437+ return tmp;
438+ } else if (fwd != Null<Date>()) {
439+ // handle fx, eq -> incorporate forwarding factor if applicable
422440 auto ccy = std::find (currencies_.begin (), currencies_.end (), indexCurrencies_[indexNo]);
423441 QL_REQUIRE (ccy != currencies_.end (), " GaussianCam::getIndexValue(): can not get currency for index #"
424442 << indexNo << " (" << indices_.at (indexNo) << " )" );
@@ -430,9 +448,11 @@ RandomVariable GaussianCam::getIndexValue(const Size indexNo, const Date& d, con
430448 res *= RandomVariable (size (), div->discount (fwd) / div->discount (d)) /
431449 getDiscount (std::distance (currencies_.begin (), ccy), d, fwd,
432450 cam_->eqbs (eqIndexInCam_[indexNo])->equityIrCurveToday ());
451+ } else if (comIndexInCam_[indexNo] != Null<Size>()) {
452+
433453 } else {
434- QL_FAIL (" GaussianGam::getIndexValue(): did not recognise index #" << indexNo << " (" << indices_. at (indexNo)
435- << " ) " );
454+ QL_FAIL (" GaussianGam::getIndexValue(): did not recognise index #" << indexNo << " ("
455+ << indices_. at (indexNo) );
436456 }
437457 }
438458 return res;
0 commit comments