Skip to content

Commit f0758af

Browse files
alexchow-acadiajenkins
authored andcommitted
Add support for IndexedCoupon in amc
1 parent 511f367 commit f0758af

2 files changed

Lines changed: 37 additions & 3 deletions

File tree

QuantExt/qle/pricingengines/mcmultilegbaseengine.cpp

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
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 {
301306
boost::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()));

QuantExt/qle/pricingengines/mcmultilegbaseengine.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class McMultiLegBaseEngine {
101101
mutable std::vector<std::vector<Real>> gearing_, spread_, accrualTime_, nominal_, payTime_, cappedRate_,
102102
flooredRate_;
103103
mutable std::vector<std::vector<bool>> isNakedOption_;
104+
mutable std::vector<std::vector<boost::shared_ptr<Index>>> couponIndex_;
105+
mutable std::vector<std::vector<Date>> couponIndexFixingDate_;
106+
mutable std::vector<std::vector<Real>> couponIndexQuantity_;
104107
mutable Size maxUndValDirtyIdx_;
105108
mutable std::vector<Date> pathDates_; // dates coresponding to path times
106109

0 commit comments

Comments
 (0)