1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2009, 2012 Roland Lichters
5 Copyright (C) 2009, 2012 Ferdinando Ametrano
6
7 This file is part of QuantLib, a free-software/open-source library
8 for financial quantitative analysts and developers - http://quantlib.org/
9
10 QuantLib is free software: you can redistribute it and/or modify it
11 under the terms of the QuantLib license. You should have received a
12 copy of the license along with this program; if not, please email
13 <quantlib-dev@lists.sf.net>. The license is also available online at
14 <http://quantlib.org/license.shtml>.
15
16 This program is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18 FOR A PARTICULAR PURPOSE. See the license for more details.
19*/
20
21#include <ql/instruments/makeois.hpp>
22#include <ql/instruments/simplifynotificationgraph.hpp>
23#include <ql/pricingengines/swap/discountingswapengine.hpp>
24#include <ql/termstructures/yield/oisratehelper.hpp>
25#include <ql/utilities/null_deleter.hpp>
26#include <utility>
27
28namespace QuantLib {
29
30 OISRateHelper::OISRateHelper(Natural settlementDays,
31 const Period& tenor, // swap maturity
32 const Handle<Quote>& fixedRate,
33 const ext::shared_ptr<OvernightIndex>& overnightIndex,
34 Handle<YieldTermStructure> discount,
35 bool telescopicValueDates,
36 Natural paymentLag,
37 BusinessDayConvention paymentConvention,
38 Frequency paymentFrequency,
39 Calendar paymentCalendar,
40 const Period& forwardStart,
41 const Spread overnightSpread,
42 Pillar::Choice pillar,
43 Date customPillarDate,
44 RateAveraging::Type averagingMethod,
45 ext::optional<bool> endOfMonth)
46 : RelativeDateRateHelper(fixedRate), pillarChoice_(pillar), settlementDays_(settlementDays), tenor_(tenor),
47 discountHandle_(std::move(discount)), telescopicValueDates_(telescopicValueDates),
48 paymentLag_(paymentLag), paymentConvention_(paymentConvention),
49 paymentFrequency_(paymentFrequency), paymentCalendar_(std::move(paymentCalendar)),
50 forwardStart_(forwardStart), overnightSpread_(overnightSpread),
51 averagingMethod_(averagingMethod), endOfMonth_(endOfMonth) {
52
53 overnightIndex_ =
54 ext::dynamic_pointer_cast<OvernightIndex>(r: overnightIndex->clone(h: termStructureHandle_));
55 // We want to be notified of changes of fixings, but we don't
56 // want notifications from termStructureHandle_ (they would
57 // interfere with bootstrapping.)
58 overnightIndex_->unregisterWith(h: termStructureHandle_);
59
60 registerWith(h: overnightIndex_);
61 registerWith(h: discountHandle_);
62
63 pillarDate_ = customPillarDate;
64 OISRateHelper::initializeDates();
65 }
66
67 void OISRateHelper::initializeDates() {
68
69 // input discount curve Handle might be empty now but it could
70 // be assigned a curve later; use a RelinkableHandle here
71 MakeOIS tmp = MakeOIS(tenor_, overnightIndex_, 0.0, forwardStart_)
72 .withDiscountingTermStructure(discountingTermStructure: discountRelinkableHandle_)
73 .withSettlementDays(settlementDays: settlementDays_)
74 .withTelescopicValueDates(telescopicValueDates: telescopicValueDates_)
75 .withPaymentLag(lag: paymentLag_)
76 .withPaymentAdjustment(convention: paymentConvention_)
77 .withPaymentFrequency(f: paymentFrequency_)
78 .withPaymentCalendar(cal: paymentCalendar_)
79 .withOvernightLegSpread(sp: overnightSpread_)
80 .withAveragingMethod(averagingMethod: averagingMethod_);
81 if (endOfMonth_) {
82 swap_ = tmp.withEndOfMonth(flag: *endOfMonth_);
83 } else {
84 swap_ = tmp;
85 }
86
87 simplifyNotificationGraph(swap&: *swap_, unregisterCoupons: true);
88
89 earliestDate_ = swap_->startDate();
90 maturityDate_ = swap_->maturityDate();
91
92 Date lastPaymentDate = std::max(a: swap_->overnightLeg().back()->date(),
93 b: swap_->fixedLeg().back()->date());
94 latestRelevantDate_ = std::max(a: maturityDate_, b: lastPaymentDate);
95
96 switch (pillarChoice_) {
97 case Pillar::MaturityDate:
98 pillarDate_ = maturityDate_;
99 break;
100 case Pillar::LastRelevantDate:
101 pillarDate_ = latestRelevantDate_;
102 break;
103 case Pillar::CustomDate:
104 // pillarDate_ already assigned at construction time
105 QL_REQUIRE(pillarDate_ >= earliestDate_,
106 "pillar date (" << pillarDate_ << ") must be later "
107 "than or equal to the instrument's earliest date (" <<
108 earliestDate_ << ")");
109 QL_REQUIRE(pillarDate_ <= latestRelevantDate_,
110 "pillar date (" << pillarDate_ << ") must be before "
111 "or equal to the instrument's latest relevant date (" <<
112 latestRelevantDate_ << ")");
113 break;
114 default:
115 QL_FAIL("unknown Pillar::Choice(" << Integer(pillarChoice_) << ")");
116 }
117
118 latestDate_ = std::max(a: swap_->maturityDate(), b: lastPaymentDate);
119 }
120
121 void OISRateHelper::setTermStructure(YieldTermStructure* t) {
122 // do not set the relinkable handle as an observer -
123 // force recalculation when needed
124 bool observer = false;
125
126 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
127 termStructureHandle_.linkTo(h: temp, registerAsObserver: observer);
128
129 if (discountHandle_.empty())
130 discountRelinkableHandle_.linkTo(h: temp, registerAsObserver: observer);
131 else
132 discountRelinkableHandle_.linkTo(h: *discountHandle_, registerAsObserver: observer);
133
134 RelativeDateRateHelper::setTermStructure(t);
135 }
136
137 Real OISRateHelper::impliedQuote() const {
138 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
139 // we didn't register as observers - force calculation
140 swap_->deepUpdate();
141 return swap_->fairRate();
142 }
143
144 void OISRateHelper::accept(AcyclicVisitor& v) {
145 auto* v1 = dynamic_cast<Visitor<OISRateHelper>*>(&v);
146 if (v1 != nullptr)
147 v1->visit(*this);
148 else
149 RateHelper::accept(v);
150 }
151
152 DatedOISRateHelper::DatedOISRateHelper(const Date& startDate,
153 const Date& endDate,
154 const Handle<Quote>& fixedRate,
155 const ext::shared_ptr<OvernightIndex>& overnightIndex,
156 Handle<YieldTermStructure> discount,
157 bool telescopicValueDates,
158 RateAveraging::Type averagingMethod,
159 Natural paymentLag,
160 BusinessDayConvention paymentConvention,
161 Frequency paymentFrequency,
162 const Calendar& paymentCalendar,
163 const Period& forwardStart,
164 Spread overnightSpread,
165 ext::optional<bool> endOfMonth)
166 : RateHelper(fixedRate), discountHandle_(std::move(discount)),
167 telescopicValueDates_(telescopicValueDates), averagingMethod_(averagingMethod) {
168
169 auto clonedOvernightIndex =
170 ext::dynamic_pointer_cast<OvernightIndex>(r: overnightIndex->clone(h: termStructureHandle_));
171 // We want to be notified of changes of fixings, but we don't
172 // want notifications from termStructureHandle_ (they would
173 // interfere with bootstrapping.)
174 clonedOvernightIndex->unregisterWith(h: termStructureHandle_);
175
176 registerWith(h: clonedOvernightIndex);
177 registerWith(h: discountHandle_);
178
179 // input discount curve Handle might be empty now but it could
180 // be assigned a curve later; use a RelinkableHandle here
181 auto tmp = MakeOIS(Period(), clonedOvernightIndex, 0.0, forwardStart)
182 .withDiscountingTermStructure(discountingTermStructure: discountRelinkableHandle_)
183 .withEffectiveDate(startDate)
184 .withTerminationDate(endDate)
185 .withTelescopicValueDates(telescopicValueDates: telescopicValueDates_)
186 .withPaymentLag(lag: paymentLag)
187 .withPaymentAdjustment(convention: paymentConvention)
188 .withPaymentFrequency(f: paymentFrequency)
189 .withPaymentCalendar(cal: paymentCalendar)
190 .withOvernightLegSpread(sp: overnightSpread)
191 .withAveragingMethod(averagingMethod: averagingMethod_);
192 if (endOfMonth) {
193 swap_ = tmp.withEndOfMonth(flag: *endOfMonth);
194 } else {
195 swap_ = tmp;
196 }
197
198 earliestDate_ = swap_->startDate();
199 Date lastPaymentDate = std::max(a: swap_->overnightLeg().back()->date(),
200 b: swap_->fixedLeg().back()->date());
201 latestDate_ = std::max(a: swap_->maturityDate(), b: lastPaymentDate);
202 }
203
204 void DatedOISRateHelper::setTermStructure(YieldTermStructure* t) {
205 // do not set the relinkable handle as an observer -
206 // force recalculation when needed
207 bool observer = false;
208
209 ext::shared_ptr<YieldTermStructure> temp(t, null_deleter());
210 termStructureHandle_.linkTo(h: temp, registerAsObserver: observer);
211
212 if (discountHandle_.empty())
213 discountRelinkableHandle_.linkTo(h: temp, registerAsObserver: observer);
214 else
215 discountRelinkableHandle_.linkTo(h: *discountHandle_, registerAsObserver: observer);
216
217 RateHelper::setTermStructure(t);
218 }
219
220 Real DatedOISRateHelper::impliedQuote() const {
221 QL_REQUIRE(termStructure_ != nullptr, "term structure not set");
222 // we didn't register as observers - force calculation
223 swap_->deepUpdate();
224 return swap_->fairRate();
225 }
226
227 void DatedOISRateHelper::accept(AcyclicVisitor& v) {
228 auto* v1 = dynamic_cast<Visitor<DatedOISRateHelper>*>(&v);
229 if (v1 != nullptr)
230 v1->visit(*this);
231 else
232 RateHelper::accept(v);
233 }
234
235}
236

source code of quantlib/ql/termstructures/yield/oisratehelper.cpp