Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
oisratehelper.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19#include <ql/cashflows/cashflows.hpp>
20#include <ql/instruments/makeois.hpp>
21#include <ql/pricingengines/swap/discountingswapengine.hpp>
22#include <ql/utilities/null_deleter.hpp>
23
25
26namespace QuantExt {
27
28OISRateHelper::OISRateHelper(Natural settlementDays, const Period& swapTenor, const Handle<Quote>& fixedRate,
29 const QuantLib::ext::shared_ptr<OvernightIndex>& overnightIndex, const DayCounter& fixedDayCounter,
30 const Calendar& fixedCalendar, Natural paymentLag, bool endOfMonth,
31 Frequency paymentFrequency, BusinessDayConvention fixedConvention,
32 BusinessDayConvention paymentAdjustment, DateGeneration::Rule rule,
33 const Handle<YieldTermStructure>& discountingCurve, bool telescopicValueDates,
34 Pillar::Choice pillar, Date customPillarDate)
35 : RelativeDateRateHelper(fixedRate), settlementDays_(settlementDays), swapTenor_(swapTenor),
36 overnightIndex_(overnightIndex), fixedDayCounter_(fixedDayCounter), fixedCalendar_(fixedCalendar),
37 paymentLag_(paymentLag), endOfMonth_(endOfMonth), paymentFrequency_(paymentFrequency),
38 fixedConvention_(fixedConvention), paymentAdjustment_(paymentAdjustment), rule_(rule),
39 discountHandle_(discountingCurve), telescopicValueDates_(telescopicValueDates), pillarChoice_(pillar) {
40
41 pillarDate_ = customPillarDate;
42
43 bool onIndexHasCurve = !overnightIndex_->forwardingTermStructure().empty();
44 bool haveDiscountCurve = !discountHandle_.empty();
45 QL_REQUIRE(!(onIndexHasCurve && haveDiscountCurve), "Have both curves nothing to solve for.");
46
47 if (!onIndexHasCurve) {
48 QuantLib::ext::shared_ptr<IborIndex> clonedIborIndex(overnightIndex_->clone(termStructureHandle_));
49 overnightIndex_ = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(clonedIborIndex);
51 }
52
53 registerWith(overnightIndex_);
54 registerWith(discountHandle_);
56}
57
59
60 Calendar paymentCalendar_ = overnightIndex_->fixingCalendar();
61
62 swap_ = MakeOIS(swapTenor_, overnightIndex_, 0.0)
63 .withSettlementDays(settlementDays_)
64 .withFixedLegDayCount(fixedDayCounter_)
65 .withEndOfMonth(endOfMonth_)
66 .withPaymentFrequency(paymentFrequency_)
67 .withRule(rule_)
68 .withPaymentCalendar(paymentCalendar_)
69 .withPaymentAdjustment(paymentAdjustment_)
70 .withPaymentLag(paymentLag_)
71 .withDiscountingTermStructure(discountRelinkableHandle_)
72 .withTelescopicValueDates(telescopicValueDates_);
73 // TODO: patch QL?
74 //.withFixedAccrualConvention(fixedConvention_)
75 //..withFixedCalendar(fixedCalendar_)
76
77 earliestDate_ = swap_->startDate();
78 maturityDate_ = swap_->maturityDate();
79
80 Date lastPaymentDate = std::max(swap_->overnightLeg().back()->date(), swap_->fixedLeg().back()->date());
81 latestRelevantDate_ = std::max(maturityDate_, lastPaymentDate);
82
83 switch (pillarChoice_) {
84 case Pillar::MaturityDate:
85 pillarDate_ = maturityDate_;
86 break;
87 case Pillar::LastRelevantDate:
88 pillarDate_ = latestRelevantDate_;
89 break;
90 case Pillar::CustomDate:
91 // pillarDate_ already assigned at construction time
92 QL_REQUIRE(pillarDate_ >= earliestDate_, "pillar date (" << pillarDate_
93 << ") must be later "
94 "than or equal to the instrument's earliest date ("
95 << earliestDate_ << ")");
96 QL_REQUIRE(pillarDate_ <= latestRelevantDate_, "pillar date ("
97 << pillarDate_
98 << ") must be before "
99 "or equal to the instrument's latest relevant date ("
100 << latestRelevantDate_ << ")");
101 break;
102 default:
103 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
104 }
105
106 // for backwards compatibility
107 latestDate_ = pillarDate_;
108}
109
110void OISRateHelper::setTermStructure(YieldTermStructure* t) {
111 // do not set the relinkable handle as an observer
112 // force recalculation when needed
113 bool observer = false;
114
115 QuantLib::ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
116 termStructureHandle_.linkTo(temp, observer);
117
118 if (discountHandle_.empty())
119 discountRelinkableHandle_.linkTo(temp, observer);
120 else
122
123 RelativeDateRateHelper::setTermStructure(t);
124}
125
127 QL_REQUIRE(termStructure_ != 0, "term structure not set");
128 // we didn't register as observers - force calculation
129 swap_->deepUpdate();
130 return swap_->fairRate();
131}
132
133void OISRateHelper::accept(AcyclicVisitor& v) {
134 Visitor<OISRateHelper>* v1 = dynamic_cast<Visitor<OISRateHelper>*>(&v);
135 if (v1 != 0)
136 v1->visit(*this);
137 else
138 RateHelper::accept(v);
139}
140
141DatedOISRateHelper::DatedOISRateHelper(const Date& startDate, const Date& endDate, const Handle<Quote>& fixedRate,
142 const QuantLib::ext::shared_ptr<OvernightIndex>& overnightIndex,
143 const DayCounter& fixedDayCounter, const Calendar& fixedCalendar,
144 Natural paymentLag, Frequency paymentFrequency,
145 BusinessDayConvention fixedConvention, BusinessDayConvention paymentAdjustment,
146 DateGeneration::Rule rule, const Handle<YieldTermStructure>& discountingCurve,
147 bool telescopicValueDates, Pillar::Choice pillar, Date customPillarDate)
148 : RateHelper(fixedRate), overnightIndex_(overnightIndex), fixedDayCounter_(fixedDayCounter),
149 fixedCalendar_(fixedCalendar), paymentLag_(paymentLag), paymentFrequency_(paymentFrequency),
150 fixedConvention_(fixedConvention), paymentAdjustment_(paymentAdjustment), rule_(rule),
151 discountHandle_(discountingCurve), telescopicValueDates_(telescopicValueDates), pillarChoice_(pillar) {
152
153 pillarDate_ = customPillarDate;
154
155 bool onIndexHasCurve = !overnightIndex_->forwardingTermStructure().empty();
156 bool haveDiscountCurve = !discountHandle_.empty();
157 QL_REQUIRE(!(onIndexHasCurve && haveDiscountCurve), "Have both curves nothing to solve for.");
158
159 if (!onIndexHasCurve) {
160 QuantLib::ext::shared_ptr<IborIndex> clonedIborIndex(overnightIndex_->clone(termStructureHandle_));
161 overnightIndex_ = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(clonedIborIndex);
162 overnightIndex_->unregisterWith(termStructureHandle_);
163 }
164
165 registerWith(overnightIndex_);
166 registerWith(discountHandle_);
167
168 swap_ = MakeOIS(Period(), overnightIndex_, 0.0)
169 .withEffectiveDate(startDate)
170 .withTerminationDate(endDate)
171 .withFixedLegDayCount(fixedDayCounter_)
172 .withPaymentFrequency(paymentFrequency_)
173 .withRule(rule_)
174 // TODO: patch QL
175 //.withFixedAccrualConvention(fixedConvention_)
176 // .withFixedCalendar(fixedCalendar_)
177 .withPaymentCalendar(overnightIndex_->fixingCalendar())
178 .withPaymentAdjustment(paymentAdjustment_)
179 .withPaymentLag(paymentLag_)
180 .withDiscountingTermStructure(termStructureHandle_)
181 .withTelescopicValueDates(telescopicValueDates_);
182
183 earliestDate_ = swap_->startDate();
184 maturityDate_ = swap_->maturityDate();
185
186 Date lastPaymentDate = std::max(swap_->overnightLeg().back()->date(), swap_->fixedLeg().back()->date());
187 latestRelevantDate_ = std::max(maturityDate_, lastPaymentDate);
188
189 switch (pillarChoice_) {
190 case Pillar::MaturityDate:
191 pillarDate_ = maturityDate_;
192 break;
193 case Pillar::LastRelevantDate:
194 pillarDate_ = latestRelevantDate_;
195 break;
196 case Pillar::CustomDate:
197 // pillarDate_ already assigned at construction time
198 QL_REQUIRE(pillarDate_ >= earliestDate_, "pillar date (" << pillarDate_
199 << ") must be later "
200 "than or equal to the instrument's earliest date ("
201 << earliestDate_ << ")");
202 QL_REQUIRE(pillarDate_ <= latestRelevantDate_, "pillar date ("
203 << pillarDate_
204 << ") must be before "
205 "or equal to the instrument's latest relevant date ("
206 << latestRelevantDate_ << ")");
207 break;
208 default:
209 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
210 }
211
212 // for backwards compatibility
213 latestDate_ = pillarDate_;
214}
215
216void DatedOISRateHelper::setTermStructure(YieldTermStructure* t) {
217 // do not set the relinkable handle as an observer -
218 // force recalculation when needed
219 bool observer = false;
220
221 QuantLib::ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
222 termStructureHandle_.linkTo(temp, observer);
223
224 if (discountHandle_.empty())
225 discountRelinkableHandle_.linkTo(temp, observer);
226 else
228
229 RateHelper::setTermStructure(t);
230}
231
233 QL_REQUIRE(termStructure_ != 0, "term structure not set");
234 // we didn't register as observers - force calculation
235 swap_->deepUpdate();
236 return swap_->fairRate();
237}
238
239void DatedOISRateHelper::accept(AcyclicVisitor& v) {
240 Visitor<DatedOISRateHelper>* v1 = dynamic_cast<Visitor<DatedOISRateHelper>*>(&v);
241 if (v1 != 0)
242 v1->visit(*this);
243 else
244 RateHelper::accept(v);
245}
246} // namespace QuantExt
BusinessDayConvention paymentAdjustment_
RelinkableHandle< YieldTermStructure > discountRelinkableHandle_
void setTermStructure(YieldTermStructure *) override
QuantLib::ext::shared_ptr< OvernightIndex > overnightIndex_
DatedOISRateHelper(const Date &startDate, const Date &endDate, const Handle< Quote > &fixedRate, const QuantLib::ext::shared_ptr< OvernightIndex > &overnightIndex, const DayCounter &fixedDayCounter, const Calendar &fixedCalendar, Natural paymentLag=0, Frequency paymentFrequency=Annual, BusinessDayConvention fixedConvention=Following, BusinessDayConvention paymentAdjustment=Following, DateGeneration::Rule rule=DateGeneration::Backward, const Handle< YieldTermStructure > &discountingCurve=Handle< YieldTermStructure >(), bool telescopicValueDates=false, Pillar::Choice pillar=Pillar::LastRelevantDate, Date customPillarDate=Date())
RelinkableHandle< YieldTermStructure > termStructureHandle_
Handle< YieldTermStructure > discountHandle_
QuantLib::ext::shared_ptr< OvernightIndexedSwap > swap_
void accept(AcyclicVisitor &) override
DateGeneration::Rule rule_
Real impliedQuote() const override
BusinessDayConvention paymentAdjustment_
RelinkableHandle< YieldTermStructure > discountRelinkableHandle_
void setTermStructure(YieldTermStructure *) override
QuantLib::ext::shared_ptr< OvernightIndex > overnightIndex_
RelinkableHandle< YieldTermStructure > termStructureHandle_
Pillar::Choice pillarChoice_
Handle< YieldTermStructure > discountHandle_
QuantLib::ext::shared_ptr< OvernightIndexedSwap > swap_
void accept(AcyclicVisitor &) override
DateGeneration::Rule rule_
void initializeDates() override
Real impliedQuote() const override
OISRateHelper(Natural settlementDays, const Period &swapTenor, const Handle< Quote > &fixedRate, const QuantLib::ext::shared_ptr< OvernightIndex > &overnightIndex, const DayCounter &fixedDayCounter, const Calendar &fixedCalendar, Natural paymentLag=0, bool endOfMonth=false, Frequency paymentFrequency=Annual, BusinessDayConvention fixedConvention=Following, BusinessDayConvention paymentAdjustment=Following, DateGeneration::Rule rule=DateGeneration::Backward, const Handle< YieldTermStructure > &discountingCurve=Handle< YieldTermStructure >(), bool telescopicValueDates=false, Pillar::Choice pillar=Pillar::LastRelevantDate, Date customPillarDate=Date())
Overnight Indexed Swap (aka OIS) rate helpers.