Skip to content

Commit

Permalink
Allow different frequencies in MakeOIS and OISRateHelper (#1837)
Browse files Browse the repository at this point in the history
  • Loading branch information
lballabio authored Dec 1, 2023
2 parents e0e8a08 + fd2ca08 commit 95775e1
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 42 deletions.
110 changes: 82 additions & 28 deletions ql/instruments/makeois.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <ql/instruments/makeois.hpp>
#include <ql/pricingengines/swap/discountingswapengine.hpp>
#include <ql/indexes/iborindex.hpp>
#include <ql/optional.hpp>
#include <ql/time/schedule.hpp>

namespace QuantLib {
Expand All @@ -33,9 +34,8 @@ namespace QuantLib {
const Period& forwardStart)
: swapTenor_(swapTenor), overnightIndex_(overnightIndex), fixedRate_(fixedRate),
forwardStart_(forwardStart),

calendar_(overnightIndex->fixingCalendar()),

fixedCalendar_(overnightIndex->fixingCalendar()),
overnightCalendar_(overnightIndex->fixingCalendar()),
fixedDayCount_(overnightIndex->dayCounter()) {}

MakeOIS::operator OvernightIndexedSwap() const {
Expand All @@ -52,45 +52,74 @@ namespace QuantLib {
Date refDate = Settings::instance().evaluationDate();
// if the evaluation date is not a business day
// then move to the next business day
refDate = calendar_.adjust(refDate);
Date spotDate = calendar_.advance(refDate,
settlementDays_*Days);
refDate = overnightCalendar_.adjust(refDate);
Date spotDate = overnightCalendar_.advance(refDate,
settlementDays_*Days);
startDate = spotDate+forwardStart_;
if (forwardStart_.length()<0)
startDate = calendar_.adjust(startDate, Preceding);
startDate = overnightCalendar_.adjust(startDate, Preceding);
else
startDate = calendar_.adjust(startDate, Following);
startDate = overnightCalendar_.adjust(startDate, Following);
}

// OIS end of month default
bool usedEndOfMonth =
isDefaultEOM_ ? calendar_.isEndOfMonth(startDate) : endOfMonth_;
isDefaultEOM_ ? overnightCalendar_.isEndOfMonth(startDate) : endOfMonth_;

Date endDate = terminationDate_;
if (endDate == Date()) {
if (usedEndOfMonth)
endDate = calendar_.advance(startDate,
swapTenor_,
ModifiedFollowing,
usedEndOfMonth);
endDate = overnightCalendar_.advance(startDate,
swapTenor_,
ModifiedFollowing,
usedEndOfMonth);
else
endDate = startDate + swapTenor_;
}

Schedule schedule(startDate, endDate,
Period(paymentFrequency_),
calendar_,
ModifiedFollowing,
ModifiedFollowing,
rule_,
usedEndOfMonth);
Frequency fixedPaymentFrequency, overnightPaymentFrequency;
DateGeneration::Rule fixedRule, overnightRule;
if (fixedPaymentFrequency_ == Once || fixedRule_ == DateGeneration::Zero) {
fixedPaymentFrequency = Once;
fixedRule = DateGeneration::Zero;
} else {
fixedPaymentFrequency = fixedPaymentFrequency_;
fixedRule = fixedRule_;
}
if (overnightPaymentFrequency_ == Once || overnightRule_ == DateGeneration::Zero) {
overnightPaymentFrequency = Once;
overnightRule = DateGeneration::Zero;
} else {
overnightPaymentFrequency = overnightPaymentFrequency_;
overnightRule = overnightRule_;
}

Schedule fixedSchedule(startDate, endDate,
Period(fixedPaymentFrequency),
fixedCalendar_,
ModifiedFollowing,
ModifiedFollowing,
fixedRule,
usedEndOfMonth);
ext::optional<Schedule> overnightSchedule;
if (fixedPaymentFrequency != overnightPaymentFrequency || fixedRule != overnightRule ||
fixedCalendar_ != overnightCalendar_) {
overnightSchedule.emplace(startDate, endDate,
Period(overnightPaymentFrequency),
overnightCalendar_,
ModifiedFollowing,
ModifiedFollowing,
overnightRule,
usedEndOfMonth);
}

Rate usedFixedRate = fixedRate_;
if (fixedRate_ == Null<Rate>()) {
OvernightIndexedSwap temp(type_, nominal_,
schedule,
fixedSchedule,
0.0, // fixed rate
fixedDayCount_,
overnightSchedule ? *overnightSchedule : fixedSchedule,
overnightIndex_, overnightSpread_,
paymentLag_, paymentAdjustment_,
paymentCalendar_, telescopicValueDates_);
Expand All @@ -112,8 +141,9 @@ namespace QuantLib {

ext::shared_ptr<OvernightIndexedSwap> ois(new
OvernightIndexedSwap(type_, nominal_,
schedule,
fixedSchedule,
usedFixedRate, fixedDayCount_,
overnightSchedule ? *overnightSchedule : fixedSchedule,
overnightIndex_, overnightSpread_,
paymentLag_, paymentAdjustment_,
paymentCalendar_, telescopicValueDates_,
Expand Down Expand Up @@ -165,9 +195,16 @@ namespace QuantLib {
}

MakeOIS& MakeOIS::withPaymentFrequency(Frequency f) {
paymentFrequency_ = f;
if (paymentFrequency_==Once)
rule_ = DateGeneration::Zero;
return withFixedLegPaymentFrequency(f).withOvernightLegPaymentFrequency(f);
}

MakeOIS& MakeOIS::withFixedLegPaymentFrequency(Frequency f) {
fixedPaymentFrequency_ = f;
return *this;
}

MakeOIS& MakeOIS::withOvernightLegPaymentFrequency(Frequency f) {
overnightPaymentFrequency_ = f;
return *this;
}

Expand All @@ -186,10 +223,27 @@ namespace QuantLib {
return *this;
}

MakeOIS& MakeOIS::withFixedLegCalendar(const Calendar& cal) {
fixedCalendar_ = cal;
return *this;
}

MakeOIS& MakeOIS::withOvernightLegCalendar(const Calendar& cal) {
overnightCalendar_ = cal;
return *this;
}

MakeOIS& MakeOIS::withRule(DateGeneration::Rule r) {
rule_ = r;
if (r==DateGeneration::Zero)
paymentFrequency_ = Once;
return withFixedLegRule(r).withOvernightLegRule(r);
}

MakeOIS& MakeOIS::withFixedLegRule(DateGeneration::Rule r) {
fixedRule_ = r;
return *this;
}

MakeOIS& MakeOIS::withOvernightLegRule(DateGeneration::Rule r) {
overnightRule_ = r;
return *this;
}

Expand Down
14 changes: 11 additions & 3 deletions ql/instruments/makeois.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,17 @@ namespace QuantLib {
MakeOIS& withEffectiveDate(const Date&);
MakeOIS& withTerminationDate(const Date&);
MakeOIS& withRule(DateGeneration::Rule r);
MakeOIS& withFixedLegRule(DateGeneration::Rule r);
MakeOIS& withOvernightLegRule(DateGeneration::Rule r);

MakeOIS& withPaymentFrequency(Frequency f);
MakeOIS& withFixedLegPaymentFrequency(Frequency f);
MakeOIS& withOvernightLegPaymentFrequency(Frequency f);
MakeOIS& withPaymentAdjustment(BusinessDayConvention convention);
MakeOIS& withPaymentLag(Integer lag);
MakeOIS& withPaymentCalendar(const Calendar& cal);
MakeOIS& withFixedLegCalendar(const Calendar& cal);
MakeOIS& withOvernightLegCalendar(const Calendar& cal);

MakeOIS& withEndOfMonth(bool flag = true);

Expand All @@ -83,14 +89,16 @@ namespace QuantLib {

Natural settlementDays_ = 2;
Date effectiveDate_, terminationDate_;
Calendar calendar_;
Calendar fixedCalendar_, overnightCalendar_;

Frequency paymentFrequency_ = Annual;
Frequency fixedPaymentFrequency_ = Annual;
Frequency overnightPaymentFrequency_ = Annual;
Calendar paymentCalendar_;
BusinessDayConvention paymentAdjustment_ = Following;
Integer paymentLag_ = 0;

DateGeneration::Rule rule_ = DateGeneration::Backward;
DateGeneration::Rule fixedRule_ = DateGeneration::Backward;
DateGeneration::Rule overnightRule_ = DateGeneration::Backward;
bool endOfMonth_ = false, isDefaultEOM_ = true;

Swap::Type type_ = Swap::Payer;
Expand Down
33 changes: 24 additions & 9 deletions ql/termstructures/yield/oisratehelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,16 @@ namespace QuantLib {
Pillar::Choice pillar,
Date customPillarDate,
RateAveraging::Type averagingMethod,
ext::optional<bool> endOfMonth)
ext::optional<bool> endOfMonth,
ext::optional<Frequency> fixedPaymentFrequency,
Calendar fixedCalendar)
: RelativeDateRateHelper(fixedRate), pillarChoice_(pillar), settlementDays_(settlementDays), tenor_(tenor),
discountHandle_(std::move(discount)), telescopicValueDates_(telescopicValueDates),
paymentLag_(paymentLag), paymentConvention_(paymentConvention),
paymentFrequency_(paymentFrequency), paymentCalendar_(std::move(paymentCalendar)),
forwardStart_(forwardStart), overnightSpread_(overnightSpread),
averagingMethod_(averagingMethod), endOfMonth_(endOfMonth) {
averagingMethod_(averagingMethod), endOfMonth_(endOfMonth),
fixedPaymentFrequency_(fixedPaymentFrequency), fixedCalendar_(std::move(fixedCalendar)) {

overnightIndex_ =
ext::dynamic_pointer_cast<OvernightIndex>(overnightIndex->clone(termStructureHandle_));
Expand Down Expand Up @@ -79,10 +82,15 @@ namespace QuantLib {
.withOvernightLegSpread(overnightSpread_)
.withAveragingMethod(averagingMethod_);
if (endOfMonth_) {
swap_ = tmp.withEndOfMonth(*endOfMonth_);
} else {
swap_ = tmp;
tmp.withEndOfMonth(*endOfMonth_);
}
if (fixedPaymentFrequency_) {
tmp.withFixedLegPaymentFrequency(*fixedPaymentFrequency_);
}
if (!fixedCalendar_.empty()) {
tmp.withFixedLegCalendar(fixedCalendar_);
}
swap_ = tmp;

simplifyNotificationGraph(*swap_, true);

Expand Down Expand Up @@ -162,7 +170,9 @@ namespace QuantLib {
const Calendar& paymentCalendar,
const Period& forwardStart,
Spread overnightSpread,
ext::optional<bool> endOfMonth)
ext::optional<bool> endOfMonth,
ext::optional<Frequency> fixedPaymentFrequency,
const Calendar& fixedCalendar)
: RateHelper(fixedRate), discountHandle_(std::move(discount)),
telescopicValueDates_(telescopicValueDates), averagingMethod_(averagingMethod) {

Expand Down Expand Up @@ -190,10 +200,15 @@ namespace QuantLib {
.withOvernightLegSpread(overnightSpread)
.withAveragingMethod(averagingMethod_);
if (endOfMonth) {
swap_ = tmp.withEndOfMonth(*endOfMonth);
} else {
swap_ = tmp;
tmp.withEndOfMonth(*endOfMonth);
}
if (fixedPaymentFrequency) {
tmp.withFixedLegPaymentFrequency(*fixedPaymentFrequency);
}
if (!fixedCalendar.empty()) {
tmp.withFixedLegCalendar(fixedCalendar);
}
swap_ = tmp;

earliestDate_ = swap_->startDate();
Date lastPaymentDate = std::max(swap_->overnightLeg().back()->date(),
Expand Down
10 changes: 8 additions & 2 deletions ql/termstructures/yield/oisratehelper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ namespace QuantLib {
Pillar::Choice pillar = Pillar::LastRelevantDate,
Date customPillarDate = Date(),
RateAveraging::Type averagingMethod = RateAveraging::Compound,
ext::optional<bool> endOfMonth = ext::nullopt);
ext::optional<bool> endOfMonth = ext::nullopt,
ext::optional<Frequency> fixedPaymentFrequency = ext::nullopt,
Calendar fixedCalendar = Calendar());
//! \name RateHelper interface
//@{
Real impliedQuote() const override;
Expand Down Expand Up @@ -88,6 +90,8 @@ namespace QuantLib {
Spread overnightSpread_;
RateAveraging::Type averagingMethod_;
ext::optional<bool> endOfMonth_;
ext::optional<Frequency> fixedPaymentFrequency_;
Calendar fixedCalendar_;
};

//! Rate helper for bootstrapping over Overnight Indexed Swap rates
Expand All @@ -107,7 +111,9 @@ namespace QuantLib {
const Calendar& paymentCalendar = Calendar(),
const Period& forwardStart = 0 * Days,
Spread overnightSpread = 0.0,
ext::optional<bool> endOfMonth = ext::nullopt);
ext::optional<bool> endOfMonth = ext::nullopt,
ext::optional<Frequency> fixedPaymentFrequency = ext::nullopt,
const Calendar& fixedCalendar = Calendar());
//! \name RateHelper interface
//@{
Real impliedQuote() const override;
Expand Down

0 comments on commit 95775e1

Please sign in to comment.