Skip to content

Commit 29c14ef

Browse files
QPR-11232 Add explicit payment date lists for Libor legs
1 parent fe0a799 commit 29c14ef

3 files changed

Lines changed: 27 additions & 4 deletions

File tree

ql/cashflows/cashflowvectors.hpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ namespace QuantLib {
7575
Period exCouponPeriod = Period(),
7676
Calendar exCouponCalendar = Calendar(),
7777
BusinessDayConvention exCouponAdjustment = Unadjusted,
78-
bool exCouponEndOfMonth = false) {
78+
bool exCouponEndOfMonth = false,
79+
const std::vector<Date>& paymentDates = {}) {
7980

8081
Size n = schedule.size()-1;
8182
QL_REQUIRE(!nominals.empty(), "no notional given");
@@ -94,6 +95,11 @@ namespace QuantLib {
9495
QL_REQUIRE(floors.size()<=n,
9596
"too many floors (" << floors.size() <<
9697
"), only " << n << " required");
98+
QL_REQUIRE(paymentDates.empty() || paymentDates.size() == n,
99+
"Expected the number of explicit payment dates (" <<
100+
paymentDates.size() <<
101+
") to equal the number of calculation periods ("
102+
<< n << ")");
97103
QL_REQUIRE(!isZero || !isInArrears,
98104
"in-arrears and zero features are not compatible");
99105

@@ -112,8 +118,17 @@ namespace QuantLib {
112118
for (Size i=0; i<n; ++i) {
113119
refStart = start = schedule.date(i);
114120
refEnd = end = schedule.date(i+1);
115-
Date paymentDate =
116-
isZero ? lastPaymentDate : paymentCalendar.advance(end, paymentLag, Days, paymentAdj);
121+
Date paymentDate;
122+
if (isZero) {
123+
paymentDate = lastPaymentDate;
124+
} else {
125+
// If explicit payment dates provided, use them.
126+
if (!paymentDates.empty()) {
127+
paymentDate = paymentDates[i];
128+
} else {
129+
paymentDate = paymentCalendar.advance(end, paymentLag, Days, paymentAdj);
130+
}
131+
}
117132
if (i==0 && (schedule.hasIsRegular() && schedule.hasTenor() && !schedule.isRegular(i+1))) {
118133
BusinessDayConvention bdc = schedule.businessDayConvention();
119134
refStart = calendar.adjust(end - schedule.tenor(), bdc);

ql/cashflows/iborcoupon.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,13 +265,19 @@ namespace QuantLib {
265265
return *this;
266266
}
267267

268+
IborLeg& IborLeg::withPaymentDates(const std::vector<Date>& paymentDates) {
269+
paymentDates_ = paymentDates;
270+
return *this;
271+
}
272+
268273
IborLeg::operator Leg() const {
269274

270275
Leg leg = FloatingLeg<IborIndex, IborCoupon, CappedFlooredIborCoupon>(
271276
schedule_, notionals_, index_, paymentDayCounter_,
272277
paymentAdjustment_, fixingDays_, gearings_, spreads_,
273278
caps_, floors_, inArrears_, zeroPayments_, paymentLag_, paymentCalendar_,
274-
exCouponPeriod_, exCouponCalendar_, exCouponAdjustment_, exCouponEndOfMonth_);
279+
exCouponPeriod_, exCouponCalendar_, exCouponAdjustment_, exCouponEndOfMonth_,
280+
paymentDates_);
275281

276282
if (caps_.empty() && floors_.empty() && !inArrears_) {
277283
ext::shared_ptr<IborCouponPricer> pricer = ext::make_shared<BlackIborCouponPricer>(

ql/cashflows/iborcoupon.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ namespace QuantLib {
156156
bool endOfMonth = false);
157157
IborLeg& withIndexedCoupons(boost::optional<bool> b = true);
158158
IborLeg& withAtParCoupons(bool b = true);
159+
IborLeg& withPaymentDates(const std::vector<Date>& paymentDates);
159160
operator Leg() const;
160161

161162
private:
@@ -176,6 +177,7 @@ namespace QuantLib {
176177
BusinessDayConvention exCouponAdjustment_ = Unadjusted;
177178
bool exCouponEndOfMonth_ = false;
178179
boost::optional<bool> useIndexedCoupons_;
180+
std::vector<Date> paymentDates_;
179181
};
180182

181183
}

0 commit comments

Comments
 (0)