@@ -197,6 +197,8 @@ void GaussianCam::performCalculations() const {
197197 }
198198
199199 indexPositionInProcess_.clear ();
200+ eqIndexInCam_.clear ();
201+ comIndexInCam_.clear ();
200202 for (Size i = 0 ; i < indices_.size (); ++i) {
201203 if (indices_[i].isFx ()) {
202204 // FX
@@ -209,8 +211,14 @@ void GaussianCam::performCalculations() const {
209211 Size eqIdx = cam_->eqIndex (indices_[i].eq ()->name ());
210212 indexPositionInProcess_.push_back (cam_->pIdx (CrossAssetModel::AssetType::EQ, eqIdx));
211213 eqIndexInCam_.push_back (eqIdx);
214+ } else if (indices_[i].isComm ()) {
215+ // COM
216+ Size comIdx = cam_->comIndex (indices_[i].commName ());
217+ indexPositionInProcess_.push_back (cam_->pIdx (CrossAssetModel::AssetType::COM, comIdx));
218+ comIndexInCam_.push_back (comIdx);
212219 } else {
213- QL_FAIL (" index '" << indices_[i].name () << " ' expected to be FX or EQ" );
220+ QL_FAIL (" GuassianCam::performCalculations(): index '" << indices_[i].name ()
221+ << " ' expected to be FX, EQ, COMM" );
214222 }
215223 }
216224
@@ -233,7 +241,7 @@ void GaussianCam::populatePathValues(const Size nSamples, std::map<Date, std::ve
233241
234242 // set reference date values, if there are no future simulation dates, we are done
235243
236- // FX and EQ indcies
244+ // FX, EQ, COMM indcies
237245 for (Size k = 0 ; k < indices_.size (); ++k) {
238246 paths[referenceDate_][k].setAll (process->initialValues ().at (indexPositionInProcess_[k]));
239247 }
@@ -351,7 +359,7 @@ void GaussianCam::populatePathValues(const Size nSamples, std::map<Date, std::ve
351359 }
352360 }
353361
354- // FX and EQ indcies
362+ // FX, EQ, COMM indices
355363 std::vector<std::vector<RandomVariable*>> rvs (
356364 indices_.size (), std::vector<RandomVariable*>(effectiveSimulationDates_.size () - 1 ));
357365 auto date = effectiveSimulationDates_.begin ();
@@ -417,8 +425,17 @@ void GaussianCam::populatePathValues(const Size nSamples, std::map<Date, std::ve
417425
418426RandomVariable GaussianCam::getIndexValue (const Size indexNo, const Date& d, const Date& fwd) const {
419427 auto res = underlyingPaths_.at (d).at (indexNo);
420- // compute forwarding factor
421- if (fwd != Null<Date>()) {
428+ if (comIndexInCam_[indexNo] != Null<Size>()) {
429+ // handle com (TODO: performace optimization via vectorized version of com model)
430+ RandomVariable tmp (res.size ());
431+ for (Size i = 0 ; i < tmp.size (); ++i) {
432+ tmp.set (i, cam_->comModel (comIndexInCam_[indexNo])
433+ ->forwardPrice (timeFromReference (d), timeFromReference (fwd != Null<Date>() ? fwd : d),
434+ Array (1 , std::log (res[i]))));
435+ }
436+ return tmp;
437+ } else if (fwd != Null<Date>()) {
438+ // handle fx, eq -> incorporate forwarding factor if applicable
422439 auto ccy = std::find (currencies_.begin (), currencies_.end (), indexCurrencies_[indexNo]);
423440 QL_REQUIRE (ccy != currencies_.end (), " GaussianCam::getIndexValue(): can not get currency for index #"
424441 << indexNo << " (" << indices_.at (indexNo) << " )" );
@@ -430,9 +447,11 @@ RandomVariable GaussianCam::getIndexValue(const Size indexNo, const Date& d, con
430447 res *= RandomVariable (size (), div->discount (fwd) / div->discount (d)) /
431448 getDiscount (std::distance (currencies_.begin (), ccy), d, fwd,
432449 cam_->eqbs (eqIndexInCam_[indexNo])->equityIrCurveToday ());
450+ } else if (comIndexInCam_[indexNo] != Null<Size>()) {
451+
433452 } else {
434- QL_FAIL (" GaussianGam::getIndexValue(): did not recognise index #" << indexNo << " (" << indices_. at (indexNo)
435- << " ) " );
453+ QL_FAIL (" GaussianGam::getIndexValue(): did not recognise index #" << indexNo << " ("
454+ << indices_. at (indexNo) );
436455 }
437456 }
438457 return res;
0 commit comments