2626#include < ql/cashflows/iborcoupon.hpp>
2727#include < ql/cashflows/lineartsrpricer.hpp>
2828#include < ql/indexes/iborindex.hpp>
29- #include < ql/instruments/vanillaswap.hpp>
3029#include < ql/instruments/overnightindexedswap.hpp>
30+ #include < ql/instruments/vanillaswap.hpp>
3131#include < ql/math/integrals/kronrodintegral.hpp>
3232#include < ql/math/solvers1d/brent.hpp>
3333#include < ql/pricingengines/blackformula.hpp>
@@ -123,23 +123,31 @@ namespace QuantLib {
123123
124124 today_ = QuantLib::Settings::instance ().evaluationDate ();
125125
126- if (paymentDate_ > today_ && !couponDiscountCurve_.empty ())
127- couponDiscountRatio_ =
128- couponDiscountCurve_->discount (paymentDate_) /
129- discountCurve_->discount (paymentDate_);
130- else
131- couponDiscountRatio_ = 1 .;
126+ Real couponCurvePaymentDiscount;
127+ if (!couponDiscountCurve_.empty () && paymentDate_ > couponDiscountCurve_->referenceDate ()) {
128+ couponCurvePaymentDiscount = couponDiscountCurve_->discount (paymentDate_);
129+ } else {
130+ couponCurvePaymentDiscount = 1.0 ;
131+ }
132+
133+ if (paymentDate_ > discountCurve_->referenceDate ()) {
134+ discountCurvePaymentDiscount_ = discountCurve_->discount (paymentDate_);
135+ } else {
136+ discountCurvePaymentDiscount_ = 1.0 ;
137+ }
138+
132139
133- spreadLegValue_ = spread_ * coupon_->accrualPeriod () *
134- discountCurve_->discount (paymentDate_) *
140+ couponDiscountRatio_ = couponCurvePaymentDiscount / discountCurvePaymentDiscount_;
141+
142+ spreadLegValue_ = spread_ * coupon_->accrualPeriod () * discountCurvePaymentDiscount_ *
135143 couponDiscountRatio_;
136144
137145 if (fixingDate_ > today_) {
138146
139147 swapTenor_ = swapIndex_->tenor ();
140148
141149 Leg swapFixedLeg;
142- if (auto on = boost ::dynamic_pointer_cast<OvernightIndexedSwapIndex>(swapIndex_)) {
150+ if (auto on = ext ::dynamic_pointer_cast<OvernightIndexedSwapIndex>(swapIndex_)) {
143151 onSwap_ = on->underlyingSwap (fixingDate_);
144152 swapRateValue_ = onSwap_->fairRate ();
145153 annuity_ = 1.0E4 * std::fabs (onSwap_->fixedLegBPS ());
@@ -371,8 +379,7 @@ namespace QuantLib {
371379
372380 Rate LinearTsrPricer::swapletRate () const {
373381 return swapletPrice () /
374- (coupon_->accrualPeriod () *
375- discountCurve_->discount (paymentDate_) * couponDiscountRatio_);
382+ (coupon_->accrualPeriod () * discountCurvePaymentDiscount_ * couponDiscountRatio_);
376383 }
377384
378385 Real LinearTsrPricer::capletPrice (Rate effectiveCap) const {
@@ -381,10 +388,8 @@ namespace QuantLib {
381388 // the fixing is determined
382389 const Rate Rs = std::max (
383390 coupon_->swapIndex ()->fixing (fixingDate_) - effectiveCap, 0 .);
384- Rate price =
385- (gearing_ * Rs) *
386- (coupon_->accrualPeriod () *
387- discountCurve_->discount (paymentDate_) * couponDiscountRatio_);
391+ Rate price = (gearing_ * Rs) * (coupon_->accrualPeriod () *
392+ discountCurvePaymentDiscount_ * couponDiscountRatio_);
388393 return price;
389394 } else {
390395 Real capletPrice = optionletPrice (Option::Call, effectiveCap);
@@ -394,8 +399,7 @@ namespace QuantLib {
394399
395400 Rate LinearTsrPricer::capletRate (Rate effectiveCap) const {
396401 return capletPrice (effectiveCap) /
397- (coupon_->accrualPeriod () *
398- discountCurve_->discount (paymentDate_) * couponDiscountRatio_);
402+ (coupon_->accrualPeriod () * discountCurvePaymentDiscount_ * couponDiscountRatio_);
399403 }
400404
401405 Real LinearTsrPricer::floorletPrice (Rate effectiveFloor) const {
@@ -404,10 +408,8 @@ namespace QuantLib {
404408 // the fixing is determined
405409 const Rate Rs = std::max (
406410 effectiveFloor - coupon_->swapIndex ()->fixing (fixingDate_), 0 .);
407- Rate price =
408- (gearing_ * Rs) *
409- (coupon_->accrualPeriod () *
410- discountCurve_->discount (paymentDate_) * couponDiscountRatio_);
411+ Rate price = (gearing_ * Rs) * (coupon_->accrualPeriod () *
412+ discountCurvePaymentDiscount_ * couponDiscountRatio_);
411413 return price;
412414 } else {
413415 Real floorletPrice = optionletPrice (Option::Put, effectiveFloor);
@@ -417,8 +419,7 @@ namespace QuantLib {
417419
418420 Rate LinearTsrPricer::floorletRate (Rate effectiveFloor) const {
419421 return floorletPrice (effectiveFloor) /
420- (coupon_->accrualPeriod () *
421- discountCurve_->discount (paymentDate_) * couponDiscountRatio_);
422+ (coupon_->accrualPeriod () * discountCurvePaymentDiscount_ * couponDiscountRatio_);
422423 }
423424
424425 Real LinearTsrPricer::swapletPrice () const {
@@ -427,14 +428,12 @@ namespace QuantLib {
427428 const Rate Rs = coupon_->swapIndex ()->fixing (fixingDate_);
428429 Rate price =
429430 (gearing_ * Rs + spread_) *
430- (coupon_->accrualPeriod () *
431- discountCurve_->discount (paymentDate_) * couponDiscountRatio_);
431+ (coupon_->accrualPeriod () * discountCurvePaymentDiscount_ * couponDiscountRatio_);
432432 return price;
433433 } else {
434434 Real atmCapletPrice = optionletPrice (Option::Call, swapRateValue_);
435435 Real atmFloorletPrice = optionletPrice (Option::Put, swapRateValue_);
436- return gearing_ * (coupon_->accrualPeriod () *
437- discountCurve_->discount (paymentDate_) *
436+ return gearing_ * (coupon_->accrualPeriod () * discountCurvePaymentDiscount_ *
438437 swapRateValue_ * couponDiscountRatio_ +
439438 atmCapletPrice - atmFloorletPrice) +
440439 spreadLegValue_;
0 commit comments