Skip to content

Commit

Permalink
minimize code changes
Browse files Browse the repository at this point in the history
  • Loading branch information
PaulXiCao committed Apr 17, 2024
1 parent 3119b30 commit 3d4b41a
Show file tree
Hide file tree
Showing 3 changed files with 133 additions and 57 deletions.
79 changes: 43 additions & 36 deletions ql/termstructures/yield/ratehelpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -532,17 +532,6 @@ namespace QuantLib {
std::move(discount), Null<Natural>(), pillarChoice, customPillarDate, endOfMonth,
useIndexedCoupons) {}

SwapRateHelper::Handles::Handles(const ext::shared_ptr<IborIndex>& iborIndex,
Handle<YieldTermStructure>&& discount)
: discount_(std::move(discount)) {
// take fixing into account
iborIndex_ = iborIndex->clone(termStructure_);
// We want to be notified of changes of fixings, but we don't
// want notifications from termStructureHandle_ (they would
// interfere with bootstrapping.)
iborIndex_->unregisterWith(termStructure_);
}

SwapRateHelper::SwapRateHelper(const Handle<Quote>& rate,
const Period& tenor,
Calendar calendar,
Expand All @@ -558,25 +547,24 @@ namespace QuantLib {
Date customPillarDate,
bool endOfMonth,
const ext::optional<bool>& useIndexedCoupons)
: RelativeDateRateHelper(rate), pillarChoice_(pillarChoice), spread_(std::move(spread)),
forwardStart_(fwdStart), handles_(Handles(iborIndex, std::move(discount))) {
registerWith(handles_->iborIndex_);
: RelativeDateRateHelper(rate), settlementDays_(settlementDays), tenor_(tenor),
pillarChoice_(pillarChoice), calendar_(std::move(calendar)),
fixedConvention_(fixedConvention), fixedFrequency_(fixedFrequency),
fixedDayCount_(std::move(fixedDayCount)), spread_(std::move(spread)), endOfMonth_(endOfMonth),
fwdStart_(fwdStart), discountHandle_(std::move(discount)),
useIndexedCoupons_(useIndexedCoupons), swapBuiltViaGivenBuilder(false) {
// take fixing into account
iborIndex_ = iborIndex->clone(termStructureHandle_);
// We want to be notified of changes of fixings, but we don't
// want notifications from termStructureHandle_ (they would
// interfere with bootstrapping.)
iborIndex_->unregisterWith(termStructureHandle_);

registerWith(iborIndex_);
registerWith(spread_);
registerWith(handles_->discount_);
registerWith(discountHandle_);

pillarDate_ = customPillarDate;
swap_ = MakeVanillaSwap(tenor, handles_->iborIndex_, 0.0, fwdStart)
.withSettlementDays(settlementDays)
.withFixedLegDayCount(fixedDayCount)
.withFixedLegTenor(Period(fixedFrequency))
.withFixedLegConvention(fixedConvention)
.withFixedLegTerminationDateConvention(fixedConvention)
.withFixedLegCalendar(calendar)
.withFixedLegEndOfMonth(endOfMonth)
.withFloatingLegCalendar(calendar)
.withFloatingLegEndOfMonth(endOfMonth)
.withIndexedCoupons(useIndexedCoupons)
.withDiscountingTermStructure(handles_->relinkableDiscount_);
SwapRateHelper::initializeDates();
}

Expand Down Expand Up @@ -617,7 +605,7 @@ namespace QuantLib {
Pillar::Choice pillar,
Date customPillarDate)
: RelativeDateRateHelper(rate), pillarChoice_(pillar), spread_(std::move(spread)),
forwardStart_(swapBuilder.forwardStart_) {
fwdStart_(swapBuilder.forwardStart_), swapBuiltViaGivenBuilder(true) {
registerWith(spread_);

pillarDate_ = customPillarDate;
Expand All @@ -637,6 +625,24 @@ namespace QuantLib {
customPillarDate) {}

void SwapRateHelper::initializeDates() {
if (not swapBuiltViaGivenBuilder)
// 1. do not pass the spread here, as it might be a Quote
// i.e. it can dynamically change
// 2. input discount curve Handle might be empty now but it could
// be assigned a curve later; use a RelinkableHandle here
swap_ = MakeVanillaSwap(tenor_, iborIndex_, 0.0, fwdStart_)
.withSettlementDays(settlementDays_)
.withDiscountingTermStructure(discountRelinkableHandle_)
.withFixedLegDayCount(fixedDayCount_)
.withFixedLegTenor(Period(fixedFrequency_))
.withFixedLegConvention(fixedConvention_)
.withFixedLegTerminationDateConvention(fixedConvention_)
.withFixedLegCalendar(calendar_)
.withFixedLegEndOfMonth(endOfMonth_)
.withFloatingLegCalendar(calendar_)
.withFloatingLegEndOfMonth(endOfMonth_)
.withIndexedCoupons(useIndexedCoupons_);

simplifyNotificationGraph(*swap_, true);

earliestDate_ = swap_->startDate();
Expand Down Expand Up @@ -672,18 +678,19 @@ namespace QuantLib {
}

void SwapRateHelper::setTermStructure(YieldTermStructure* t) {
if (swapBuiltViaGivenBuilder)
return;

// do not set the relinkable handle as an observer -
// force recalculation when needed
bool observer = false;

if (handles_) {
ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
handles_->termStructure_.linkTo(temp, observer);

Handle<YieldTermStructure>& dh = handles_->discount_;
RelinkableHandle<YieldTermStructure>& rdh = handles_->relinkableDiscount_;
rdh.linkTo((dh.empty() ? temp : *dh), observer);
}
ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
termStructureHandle_.linkTo(temp, observer);
if (discountHandle_.empty())
discountRelinkableHandle_.linkTo(temp, observer);
else
discountRelinkableHandle_.linkTo(*discountHandle_, observer);

RelativeDateRateHelper::setTermStructure(t);
}
Expand Down
38 changes: 17 additions & 21 deletions ql/termstructures/yield/ratehelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,14 +324,6 @@ namespace QuantLib {
Handle<Quote> spread = {},
Pillar::Choice pillar = Pillar::LastRelevantDate,
Date customPillarDate = Date());
// private:
// SwapRateHelper(const Handle<Quote>& rate,
// const MakeVanillaSwap& swapBuilder,
// Handle<YieldTermStructure> discountingCurve = {},
// Handle<Quote> spread = {},
// Pillar::Choice pillar = Pillar::LastRelevantDate,
// Date customPillarDate = Date());
// public:
//! \name RateHelper interface
//@{
Real impliedQuote() const override;
Expand All @@ -351,21 +343,25 @@ namespace QuantLib {
protected:
void initializeDates() override;

Natural settlementDays_;
Period tenor_;

Pillar::Choice pillarChoice_;
Calendar calendar_;
BusinessDayConvention fixedConvention_;
Frequency fixedFrequency_;
DayCounter fixedDayCount_;
ext::shared_ptr<IborIndex> iborIndex_;
ext::shared_ptr<VanillaSwap> swap_;
RelinkableHandle<YieldTermStructure> termStructureHandle_;
Handle<Quote> spread_;
Period forwardStart_;

struct Handles {
ext::shared_ptr<IborIndex> iborIndex_;
RelinkableHandle<YieldTermStructure> termStructure_;
Handle<YieldTermStructure> discount_;
RelinkableHandle<YieldTermStructure> relinkableDiscount_;

Handles(const ext::shared_ptr<IborIndex>& iborIndex, Handle<YieldTermStructure>&& discountingCurve);
};
// only set if iborIndex explicitly given in ctor
ext::optional<Handles> handles_;
bool endOfMonth_;
Period fwdStart_;
Handle<YieldTermStructure> discountHandle_;
RelinkableHandle<YieldTermStructure> discountRelinkableHandle_;
ext::optional<bool> useIndexedCoupons_;

bool swapBuiltViaGivenBuilder;

Check notice on line 364 in ql/termstructures/yield/ratehelpers.hpp

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

ql/termstructures/yield/ratehelpers.hpp#L364

class member 'SwapRateHelper::swapBuiltViaGivenBuilder' is never used.
};


Expand Down Expand Up @@ -507,7 +503,7 @@ namespace QuantLib {
}

inline const Period& SwapRateHelper::forwardStart() const {
return forwardStart_;
return fwdStart_;
}

}
Expand Down
73 changes: 73 additions & 0 deletions test-suite/ratehelpers.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
// /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */

// /*
// Copyright (C) 2024 Paul Xi Cao

// This file is part of QuantLib, a free-software/open-source library
// for financial quantitative analysts and developers - http://quantlib.org/

// QuantLib is free software: you can redistribute it and/or modify it
// under the terms of the QuantLib license. You should have received a
// copy of the license along with this program; if not, please email
// <[email protected]>. The license is also available online at
// <http://quantlib.org/license.shtml>.

// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the license for more details.
// */

// #include "toplevelfixture.hpp"
// #include "utilities.hpp"
// #include <ql/currencies/america.hpp>
// #include <ql/termstructures/yield/ratehelpers.hpp>
// #include <ql/time/calendars/weekendsonly.hpp>
// #include <ql/time/daycounters/actual360.hpp>

// using namespace QuantLib;
// using namespace boost::unit_test_framework;

// BOOST_FIXTURE_TEST_SUITE(QuantLibTests, TopLevelFixture)

// BOOST_AUTO_TEST_SUITE(RateHelpersTests)


// BOOST_AUTO_TEST_CASE(testSwapWithSwapBuilderArgument) {
// BOOST_TEST_MESSAGE("Testing SwapRateHelper construction with MakeVanillaSwap...");

// const Rate rate = 0.05;

// const MakeVanillaSwap swapBuilder = []() -> MakeVanillaSwap {
// const Period swapTenor = 3 * Months;
// const ext::shared_ptr<IborIndex> iborIndex =
// ext::make_shared<IborIndex>("IsdaIbor", swapTenor, /*settlementDays=*/2, USDCurrency(),
// WeekendsOnly(), ModifiedFollowing, false, Actual360());
// const Rate fixedRate = 0.07;
// const Period forwardStart = 2 * Days;
// return {swapTenor, iborIndex, fixedRate, forwardStart};
// }();

// const Handle<Quote> spread(ext::make_shared<SimpleQuote>(100));

// const Pillar::Choice pillar = Pillar::LastRelevantDate;
// Date customPillarDate = Date();

// SwapRateHelper helper(rate, swapBuilder, spread, pillar, customPillarDate);

// const ext::shared_ptr<VanillaSwap> swapPtr = helper.swap();
// const VanillaSwap& swap = *swapPtr;

// swap == swap;

// swap.
// }

// BOOST_AUTO_TEST_CASE(testSwapWithExplicitArguments) {
// BOOST_TEST_MESSAGE("Testing SwapRateHelper construction with explicit arguments (aka without "
// "MakeVanillaSwap)...");
// }


// BOOST_AUTO_TEST_SUITE_END()

// BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 3d4b41a

Please sign in to comment.