21#include <ql/patterns/visitor.hpp>
22#include <ql/time/daycounter.hpp>
27 const Date& fixingDate)
28 :
Coupon(c->date(), 0.0, c->accrualStartDate(), c->accrualEndDate(), c->referencePeriodStart(),
29 c->referencePeriodEnd(), c->exCouponDate()),
30 c_(c), qty_(qty), index_(index), fixingDate_(fixingDate), initialFixing_(Null<Real>()) {
31 QL_REQUIRE(
index,
"IndexedCoupon: index is null");
32 QL_REQUIRE(
fixingDate != Date(),
"IndexedCoupon: fixingDate is null");
38 :
Coupon(c->date(), c->nominal(), c->accrualStartDate(), c->accrualEndDate(), c->referencePeriodStart(),
39 c->referencePeriodEnd(), c->exCouponDate()),
40 c_(c), qty_(qty), initialFixing_(initialFixing) {
41 QL_REQUIRE(
initialFixing != Null<Real>(),
"IndexedCoupon: initial fixing is null");
70 Visitor<IndexedCoupon>* v1 =
dynamic_cast<Visitor<IndexedCoupon>*
>(&v);
78 const QuantLib::ext::shared_ptr<Index>& index,
const Date& fixingDate)
79 : c_(c), qty_(qty), index_(index), fixingDate_(fixingDate), initialFixing_(Null<Real>()) {
80 QL_REQUIRE(
index,
"IndexWrappedCashFlow: index is null");
81 QL_REQUIRE(
fixingDate != Date(),
"IndexWrappedCashFlow: fixingDate is null");
87 const Real initialFixing)
88 : c_(c), qty_(qty), initialFixing_(initialFixing) {
89 QL_REQUIRE(
initialFixing != Null<Real>(),
"IndexWrappedCashFlow: initial fixing is null");
113 Visitor<IndexWrappedCashFlow>* v1 =
dynamic_cast<Visitor<IndexWrappedCashFlow>*
>(&v);
121 : underlyingLeg_(underlyingLeg), qty_(qty), index_(index), initialFixing_(Null<Real>()),
122 initialNotionalFixing_(Null<Real>()), fixingDays_(0), fixingCalendar_(NullCalendar()),
123 fixingConvention_(Preceding), inArrearsFixing_(true) {
124 QL_REQUIRE(index,
"IndexedCouponLeg: index required");
162IndexedCouponLeg::operator Leg()
const {
164 resultLeg.reserve(underlyingLeg_.size());
166 for (Size i = 0; i < underlyingLeg_.size(); ++i) {
167 bool firstValuationDate = (i == 0);
170 if (
auto cpn = QuantLib::ext::dynamic_pointer_cast<Coupon>(underlyingLeg_[i])) {
171 if (valuationSchedule_.empty()) {
172 fixingDate = inArrearsFixing_ ? cpn->accrualEndDate() : cpn->accrualStartDate();
174 if (valuationSchedule_.size() == underlyingLeg_.size() + 1) {
176 fixingDate = inArrearsFixing_ ? valuationSchedule_.date(i + 1) : valuationSchedule_.date(i);
180 auto valDates = valuationSchedule_.dates();
181 Date refDate = inArrearsFixing_ ? cpn->accrualEndDate() : cpn->accrualStartDate();
183 std::distance(valDates.begin(), std::upper_bound(valDates.begin(), valDates.end(), refDate));
184 QL_REQUIRE(index > 0,
"IndexedCouponLeg: First valuation date ("
185 << valDates.front() <<
") must be leq accrual "
186 << (inArrearsFixing_ ?
"end" :
"start") <<
" date ("
187 << cpn->accrualStartDate() <<
") of the " << (i + 1)
188 <<
"th coupon in the underlying leg");
189 fixingDate = valuationSchedule_.date(index - 1);
190 firstValuationDate = (index == 1);
194 fixingDate = fixingCalendar_.advance(fixingDate, -
static_cast<int>(fixingDays_), Days, fixingConvention_);
195 if (index_ !=
nullptr)
196 fixingDate = index_->fixingCalendar().adjust(fixingDate, Preceding);
198 if (firstValuationDate && initialFixing_ != Null<Real>()) {
199 resultLeg.push_back(QuantLib::ext::make_shared<IndexedCoupon>(cpn, qty_, initialFixing_));
201 resultLeg.push_back(QuantLib::ext::make_shared<IndexedCoupon>(cpn, qty_, index_, fixingDate));
203 }
else if (
auto csf = QuantLib::ext::dynamic_pointer_cast<CashFlow>(underlyingLeg_[i])) {
204 fixingDate = fixingCalendar_.advance(csf->date(), -
static_cast<int>(fixingDays_), Days, fixingConvention_);
205 if (firstValuationDate && initialNotionalFixing_ != Null<Real>()) {
207 resultLeg.push_back(QuantLib::ext::make_shared<IndexWrappedCashFlow>(csf, qty_, initialNotionalFixing_));
208 }
else if (!valuationSchedule_.empty() && valuationSchedule_.dates().size() > 0 &&
209 valuationSchedule_.date(0) == csf->date() && initialFixing_ != Null<Real>()) {
211 resultLeg.push_back(QuantLib::ext::make_shared<IndexWrappedCashFlow>(csf, qty_, initialFixing_));
214 resultLeg.push_back(QuantLib::ext::make_shared<IndexWrappedCashFlow>(csf, qty_, index_, fixingDate));
217 QL_FAIL(
"IndexedCouponLeg: coupon or cashflow required");
225 if (
auto cpn = QuantLib::ext::dynamic_pointer_cast<Coupon>(c))
232 if (
auto cpn = QuantLib::ext::dynamic_pointer_cast<IndexedCoupon>(c)) {
233 QuantLib::ext::shared_ptr<Coupon> unpacked_cpn = cpn->underlying();
240 if (
auto cf = QuantLib::ext::dynamic_pointer_cast<IndexWrappedCashFlow>(c)) {
241 QuantLib::ext::shared_ptr<CashFlow> unpacked_cf = cf->underlying();
248 if (
auto cpn = QuantLib::ext::dynamic_pointer_cast<IndexedCoupon>(c)) {
250 }
else if (
auto cf = QuantLib::ext::dynamic_pointer_cast<IndexWrappedCashFlow>(c)) {
257std::vector<std::tuple<Date, QuantLib::ext::shared_ptr<Index>, Real>>
259 if (
auto cpn = QuantLib::ext::dynamic_pointer_cast<IndexedCoupon>(c)) {
261 v.push_back(std::make_tuple(cpn->fixingDate(), cpn->index(), cpn->multiplier()));
263 }
else if (
auto cf = QuantLib::ext::dynamic_pointer_cast<IndexWrappedCashFlow>(c)) {
265 v.push_back(std::make_tuple(cf->fixingDate(), cf->index(), cf->multiplier()));
Real initialFixing() const
QuantLib::ext::shared_ptr< Index > index() const
QuantLib::ext::shared_ptr< Index > index_
Real amount() const override
void accept(AcyclicVisitor &) override
QuantLib::ext::shared_ptr< CashFlow > c_
QuantLib::ext::shared_ptr< CashFlow > underlying() const
IndexWrappedCashFlow(const QuantLib::ext::shared_ptr< CashFlow > &c, const Real qty, const QuantLib::ext::shared_ptr< Index > &index, const Date &fixingDate)
Date date() const override
const Date & fixingDate() const
Real initialFixing() const
QuantLib::ext::shared_ptr< Index > index() const
QuantLib::ext::shared_ptr< Index > index_
Real amount() const override
void accept(AcyclicVisitor &) override
Real nominal() const override
DayCounter dayCounter() const override
QuantLib::ext::shared_ptr< Coupon > underlying() const
QuantLib::ext::shared_ptr< Coupon > c_
IndexedCoupon(const QuantLib::ext::shared_ptr< Coupon > &c, const Real qty, const QuantLib::ext::shared_ptr< Index > &index, const Date &fixingDate)
const Date & fixingDate() const
Real accruedAmount(const Date &d) const override
Real rate() const override
IndexedCouponLeg(const Leg &underlyingLeg, const Real qty, const QuantLib::ext::shared_ptr< Index > &index)
IndexedCouponLeg & withInitialNotionalFixing(const Real initialNotionalFixing)
BusinessDayConvention fixingConvention_
Schedule valuationSchedule_
Real initialNotionalFixing_
IndexedCouponLeg & withFixingCalendar(const Calendar &fixingCalendar)
IndexedCouponLeg & inArrearsFixing(const bool inArrearsFixing=true)
IndexedCouponLeg & withInitialFixing(const Real initialFixing)
IndexedCouponLeg & withFixingDays(const Size fixingDays)
IndexedCouponLeg & withValuationSchedule(const Schedule &valuationSchedule)
IndexedCouponLeg & withFixingConvention(const BusinessDayConvention &fixingConvention)
coupon with an indexed notional
std::vector< std::tuple< Date, QuantLib::ext::shared_ptr< Index >, Real > > getIndexedCouponOrCashFlowFixingDetails(const QuantLib::ext::shared_ptr< CashFlow > &c)
QuantLib::ext::shared_ptr< Coupon > unpackIndexedCoupon(const QuantLib::ext::shared_ptr< Coupon > &c)
QuantLib::ext::shared_ptr< CashFlow > unpackIndexWrappedCashFlow(const QuantLib::ext::shared_ptr< CashFlow > &c)
Real getIndexedCouponOrCashFlowMultiplier(const QuantLib::ext::shared_ptr< CashFlow > &c)
QuantLib::ext::shared_ptr< CashFlow > unpackIndexedCouponOrCashFlow(const QuantLib::ext::shared_ptr< CashFlow > &c)