From 4e0942ab029a69d22d6fc8f57dffd6f91f4fbca2 Mon Sep 17 00:00:00 2001 From: Luigi Ballabio Date: Mon, 18 Sep 2023 16:02:09 +0200 Subject: [PATCH] Inherit OIS from fixed-vs-floating swap --- ql/instruments/fixedvsfloatingswap.cpp | 15 ++- ql/instruments/fixedvsfloatingswap.hpp | 4 +- ql/instruments/overnightindexedswap.cpp | 134 +++++++----------------- ql/instruments/overnightindexedswap.hpp | 53 ++-------- test-suite/overnightindexedswap.cpp | 4 +- 5 files changed, 64 insertions(+), 146 deletions(-) diff --git a/ql/instruments/fixedvsfloatingswap.cpp b/ql/instruments/fixedvsfloatingswap.cpp index 3ab43309221..719eacba5de 100644 --- a/ql/instruments/fixedvsfloatingswap.cpp +++ b/ql/instruments/fixedvsfloatingswap.cpp @@ -40,12 +40,19 @@ namespace QuantLib { ext::shared_ptr iborIndex, Spread spread, DayCounter floatingDayCount, - ext::optional paymentConvention) + ext::optional paymentConvention, + Natural paymentLag, + const Calendar& paymentCalendar) : Swap(2), type_(type), fixedNominals_(std::move(fixedNominals)), fixedSchedule_(std::move(fixedSchedule)), fixedRate_(fixedRate), fixedDayCount_(std::move(fixedDayCount)), floatingNominals_(std::move(floatingNominals)), floatingSchedule_(std::move(floatingSchedule)), iborIndex_(std::move(iborIndex)), spread_(spread), floatingDayCount_(std::move(floatingDayCount)) { + QL_REQUIRE(iborIndex_, "null floating index provided"); + + if (fixedDayCount_ == DayCounter()) + fixedDayCount_ = iborIndex_->dayCounter(); + if (paymentConvention) // NOLINT(readability-implicit-bool-conversion) paymentConvention_ = *paymentConvention; else @@ -54,7 +61,11 @@ namespace QuantLib { legs_[0] = FixedRateLeg(fixedSchedule_) .withNotionals(fixedNominals_) .withCouponRates(fixedRate_, fixedDayCount_) - .withPaymentAdjustment(paymentConvention_); + .withPaymentAdjustment(paymentConvention_) + .withPaymentLag(paymentLag) + .withPaymentCalendar(paymentCalendar.empty() ? + fixedSchedule_.calendar() : + paymentCalendar); // legs_[1] to be built by derived class constructor diff --git a/ql/instruments/fixedvsfloatingswap.hpp b/ql/instruments/fixedvsfloatingswap.hpp index 20ad6694065..71187063c17 100644 --- a/ql/instruments/fixedvsfloatingswap.hpp +++ b/ql/instruments/fixedvsfloatingswap.hpp @@ -63,7 +63,9 @@ namespace QuantLib { ext::shared_ptr iborIndex, Spread spread, DayCounter floatingDayCount, - ext::optional paymentConvention = ext::nullopt); + ext::optional paymentConvention = ext::nullopt, + Natural paymentLag = 0, + const Calendar& paymentCalendar = Calendar()); //! \name Inspectors //@{ Type type() const; diff --git a/ql/instruments/overnightindexedswap.cpp b/ql/instruments/overnightindexedswap.cpp index 0481b11ebbb..2f1061c0f0c 100644 --- a/ql/instruments/overnightindexedswap.cpp +++ b/ql/instruments/overnightindexedswap.cpp @@ -113,7 +113,7 @@ namespace QuantLib { Rate fixedRate, DayCounter fixedDC, std::vector overnightNominals, - Schedule overnightSchedule, + const Schedule& overnightSchedule, ext::shared_ptr overnightIndex, Spread spread, Natural paymentLag, @@ -121,113 +121,49 @@ namespace QuantLib { const Calendar& paymentCalendar, bool telescopicValueDates, RateAveraging::Type averagingMethod) - : Swap(2), type_(type), fixedNominals_(std::move(fixedNominals)), - fixedSchedule_(std::move(fixedSchedule)), fixedRate_(fixedRate), fixedDC_(std::move(fixedDC)), - overnightNominals_(std::move(overnightNominals)), overnightSchedule_(std::move(overnightSchedule)), - overnightIndex_(std::move(overnightIndex)), spread_(spread), averagingMethod_(averagingMethod) { - if (fixedDC_ == DayCounter()) - fixedDC_ = overnightIndex_->dayCounter(); - legs_[0] = FixedRateLeg(fixedSchedule_) - .withNotionals(fixedNominals_) - .withCouponRates(fixedRate_, fixedDC_) - .withPaymentLag(paymentLag) - .withPaymentAdjustment(paymentAdjustment) - .withPaymentCalendar(paymentCalendar.empty() ? fixedSchedule_.calendar() : - paymentCalendar); + : FixedVsFloatingSwap(type, fixedNominals, fixedSchedule, fixedRate, fixedDC, + overnightNominals, overnightSchedule, overnightIndex, + spread, DayCounter(), ext::nullopt), + overnightIndex_(overnightIndex), averagingMethod_(averagingMethod) { legs_[1] = - OvernightLeg(overnightSchedule_, overnightIndex_) - .withNotionals(overnightNominals_) - .withSpreads(spread_) + OvernightLeg(overnightSchedule, overnightIndex_) + .withNotionals(overnightNominals) + .withSpreads(spread) .withTelescopicValueDates(telescopicValueDates) .withPaymentLag(paymentLag) .withPaymentAdjustment(paymentAdjustment) - .withPaymentCalendar(paymentCalendar.empty() ? overnightSchedule_.calendar() : - paymentCalendar) + .withPaymentCalendar(paymentCalendar.empty() ? + overnightSchedule.calendar() : + paymentCalendar) .withAveragingMethod(averagingMethod_); + } - for (Size j = 0; j < 2; ++j) { - for (auto& i : legs_[j]) - registerWith(i); - } - - switch (type_) { - case Payer: - payer_[0] = -1.0; - payer_[1] = +1.0; - break; - case Receiver: - payer_[0] = +1.0; - payer_[1] = -1.0; - break; - default: - QL_FAIL("Unknown overnight-swap type"); - } - - // These bools tell us if we can support the old methods nominal() and nominals(). - // There might be false negatives (i.e., if we pass constant vectors of different lengths - // as fixedNominals and floatingNominals) but we're going to assume that whoever uses the - // constructor with two vectors is mostly going to use the new methods instead. - sameNominals_ = std::equal(fixedNominals_.begin(), fixedNominals_.end(), - overnightNominals_.begin(), overnightNominals_.end()); - if (!sameNominals_) { - constantNominals_ = false; - } else { - constantNominals_ = true; - Real front = fixedNominals_[0]; - for (auto x : fixedNominals_) { - if (x != front) { - constantNominals_ = false; - break; - } + void OvernightIndexedSwap::setupFloatingArguments(arguments* args) const { + const Leg& floatingCoupons = floatingLeg(); + Size n = floatingCoupons.size(); + + args->floatingResetDates = args->floatingPayDates = args->floatingFixingDates = std::vector(n); + args->floatingAccrualTimes = std::vector