1717*/
1818
1919#include < qle/cashflows/averageonindexedcoupon.hpp>
20+ #include < qle/cashflows/indexedcoupon.hpp>
2021#include < qle/cashflows/overnightindexedcoupon.hpp>
2122#include < qle/pricingengines/mcmultilegbaseengine.hpp>
2223
@@ -121,6 +122,10 @@ void McMultiLegBaseEngine::computePath(const MultiPath& p) const {
121122 else
122123 rate = std::min (rate, cappedRate_[i][j]);
123124 Real amount = rate * accrualTime_[i][j] * nominal_[i][j];
125+
126+ if (couponIndex_[i][j])
127+ amount *= couponIndexQuantity_[i][j] * couponIndex_[i][j]->fixing (couponIndexFixingDate_[i][j]);
128+
124129 Size payCcyNum = payCcyNum_[i][j];
125130 Real dsc = model_->discountBond (payCcyNum, t, payTime_[i][j], p[payCcyIndex_[i][j]][pathIndex],
126131 discountCurves_[payCcyNum]);
@@ -301,10 +306,13 @@ namespace {
301306boost::shared_ptr<FloatingRateCoupon> flrcpn (const boost::shared_ptr<CashFlow>& c) {
302307 auto cfc = boost::dynamic_pointer_cast<CappedFlooredCoupon>(c);
303308 if (cfc)
304- return cfc->underlying ();
309+ return flrcpn ( cfc->underlying () );
305310 auto scfc = boost::dynamic_pointer_cast<StrippedCappedFlooredCoupon>(c);
306- if (scfc && scfc->underlying ())
307- return scfc->underlying ()->underlying ();
311+ if (scfc)
312+ return flrcpn (scfc->underlying ());
313+ auto ic = boost::dynamic_pointer_cast<IndexedCoupon>(c);
314+ if (ic)
315+ return flrcpn (ic->underlying ());
308316 return boost::dynamic_pointer_cast<FloatingRateCoupon>(c);
309317}
310318
@@ -318,6 +326,8 @@ bool isFixedCoupon(const boost::shared_ptr<CashFlow>& c, const Date& today) {
318326 else if (boost::dynamic_pointer_cast<FixedRateCoupon>(c) != nullptr ||
319327 boost::dynamic_pointer_cast<SimpleCashFlow>(c) != nullptr )
320328 return true ;
329+ else if (auto indexed = boost::dynamic_pointer_cast<IndexedCoupon>(c))
330+ return isFixedCoupon (indexed->underlying (), today);
321331 else
322332 QL_FAIL (" McMultiLegBaseEngine: unrecognised coupon type" );
323333}
@@ -454,6 +464,9 @@ void McMultiLegBaseEngine::calculate() const {
454464 cappedRate_.clear ();
455465 flooredRate_.clear ();
456466 isNakedOption_.clear ();
467+ couponIndex_.clear ();
468+ couponIndexFixingDate_.clear ();
469+ couponIndexQuantity_.clear ();
457470 //
458471 indexCcyIndex_.resize (times_.size ());
459472 payCcyNum_.resize (times_.size ());
@@ -474,6 +487,9 @@ void McMultiLegBaseEngine::calculate() const {
474487 cappedRate_.resize (times_.size ());
475488 flooredRate_.resize (times_.size ());
476489 isNakedOption_.resize (times_.size ());
490+ couponIndex_.resize (times_.size ());
491+ couponIndexFixingDate_.resize (times_.size ());
492+ couponIndexQuantity_.resize (times_.size ());
477493 //
478494 trappedCoupons_.clear ();
479495 trappedCoupons_.resize (times_.size ());
@@ -710,6 +726,21 @@ void McMultiLegBaseEngine::calculate() const {
710726 << " not supported." );
711727 }
712728
729+ // indexed coupon
730+ boost::shared_ptr<Index> couponIndex = nullptr ;
731+ Date couponIndexFixingDate = Null<Date>();
732+ Real couponIndexQuantity = Null<Real>();
733+ if (auto ic = boost::dynamic_pointer_cast<IndexedCoupon>(leg_[i][j])) {
734+ couponIndex = ic->index ();
735+ couponIndexFixingDate = ic->fixingDate ();
736+ couponIndexQuantity = ic->quantity ();
737+ if (!QuantLib::close_enough (ic->multiplier (), 0.0 ))
738+ nominal_[index][nominal_[index].size ()-1 ] /= ic->multiplier ();
739+ }
740+ couponIndex_[index].push_back (couponIndex);
741+ couponIndexFixingDate_[index].push_back (couponIndexFixingDate);
742+ couponIndexQuantity_[index].push_back (couponIndexQuantity);
743+
713744 // other data
714745 payCcyNum_[index].push_back (model_->ccyIndex (currency_[i]));
715746 payCcyIndex_[index].push_back (model_->pIdx (CrossAssetModel::AssetType::IR, payCcyNum_[index].back ()));
0 commit comments