QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
Loading...
Searching...
No Matches
cpicoupon.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2009 Chris Kenyon
5 Copyright (C) 2022 Quaternion Risk Management Ltd
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
27#include <utility>
28
29
30namespace QuantLib {
31
33 const Date& paymentDate,
34 Real nominal,
35 const Date& startDate,
36 const Date& endDate,
37 const ext::shared_ptr<ZeroInflationIndex>& index,
38 const Period& observationLag,
39 CPI::InterpolationType observationInterpolation,
40 const DayCounter& dayCounter,
41 Real fixedRate,
42 const Date& refPeriodStart,
43 const Date& refPeriodEnd,
44 const Date& exCouponDate)
45 : CPICoupon(baseCPI, Date(), paymentDate, nominal, startDate, endDate,
46 index, observationLag, observationInterpolation, dayCounter,
47 fixedRate, refPeriodStart, refPeriodEnd, exCouponDate) {}
48
49 CPICoupon::CPICoupon(const Date& baseDate,
50 const Date& paymentDate,
51 Real nominal,
52 const Date& startDate,
53 const Date& endDate,
54 const ext::shared_ptr<ZeroInflationIndex>& index,
55 const Period& observationLag,
56 CPI::InterpolationType observationInterpolation,
57 const DayCounter& dayCounter,
58 Real fixedRate,
59 const Date& refPeriodStart,
60 const Date& refPeriodEnd,
61 const Date& exCouponDate)
62 : CPICoupon(Null<Real>(), baseDate, paymentDate, nominal, startDate, endDate,
63 index, observationLag, observationInterpolation, dayCounter,
64 fixedRate, refPeriodStart, refPeriodEnd, exCouponDate) {}
65
67 const Date& baseDate,
68 const Date& paymentDate,
69 Real nominal,
70 const Date& startDate,
71 const Date& endDate,
72 const ext::shared_ptr<ZeroInflationIndex>& index,
73 const Period& observationLag,
74 CPI::InterpolationType observationInterpolation,
75 const DayCounter& dayCounter,
76 Real fixedRate,
77 const Date& refPeriodStart,
78 const Date& refPeriodEnd,
79 const Date& exCouponDate)
80 : InflationCoupon(paymentDate, nominal, startDate, endDate, 0,
81 index, observationLag, dayCounter,
82 refPeriodStart, refPeriodEnd, exCouponDate),
83 baseCPI_(baseCPI), fixedRate_(fixedRate),
84 observationInterpolation_(observationInterpolation), baseDate_(baseDate) {
85
86 QL_REQUIRE(index_, "no index provided");
88 "baseCPI and baseDate can not be both null, provide a valid baseCPI or baseDate");
89 QL_REQUIRE(baseCPI_ == Null<Rate>() || std::fabs(baseCPI_) > 1e-16,
90 "|baseCPI_| < 1e-16, future divide-by-zero problem");
91 }
92
94 auto* v1 = dynamic_cast<Visitor<CPICoupon>*>(&v);
95 if (v1 != nullptr)
96 v1->visit(*this);
97 else
99 }
100
102 if (d <= accrualStartDate_ || d > paymentDate_) {
103 return 0.0;
104 } else {
105 auto pricer = ext::dynamic_pointer_cast<CPICouponPricer>(pricer_);
106 QL_REQUIRE(pricer, "pricer not set or of wrong type");
107 pricer->initialize(*this);
108 return nominal() * pricer->accruedRate(d) * accruedPeriod(d);
109 }
110 }
111
113
114 Rate I0 = baseCPI();
115
116 if (I0 == Null<Rate>()) {
121 }
122
124 d,
127
128 return I1 / I0;
129 }
130
132 const ext::shared_ptr<InflationCouponPricer>&pricer) const {
133 return static_cast<bool>(
134 ext::dynamic_pointer_cast<CPICouponPricer>(pricer));
135 }
136
137
138
140 const ext::shared_ptr<ZeroInflationIndex>& index,
141 const Date& baseDate,
142 Real baseFixing,
143 const Date& observationDate,
144 const Period& observationLag,
145 CPI::InterpolationType interpolation,
146 const Date& paymentDate,
147 bool growthOnly)
148 : IndexedCashFlow(notional, index, baseDate, observationDate - observationLag, paymentDate, growthOnly),
149 baseFixing_(baseFixing), observationDate_(observationDate), observationLag_(observationLag),
150 interpolation_(interpolation), frequency_(index ? index->frequency() : NoFrequency) {
151 QL_REQUIRE(index, "no index provided");
153 baseFixing_ != Null<Rate>() || baseDate != Date(),
154 "baseCPI and baseDate can not be both null, provide a valid baseCPI or baseDate");
155 QL_REQUIRE(baseFixing_ == Null<Rate>() || std::fabs(baseFixing_) > 1e-16,
156 "|baseCPI_| < 1e-16, future divide-by-zero problem");
157 }
158
161 if (base != Date()) {
162 return base;
163 } else {
164 QL_FAIL("no base date specified");
165 }
166 }
167
169 if (baseFixing_ != Null<Rate>())
170 return baseFixing_;
171 else
173 }
174
177 }
178
180 ext::shared_ptr<ZeroInflationIndex> index,
181 const Real baseCPI,
182 const Period& observationLag)
183 : schedule_(std::move(schedule)), index_(std::move(index)), baseCPI_(baseCPI),
184 observationLag_(observationLag), paymentDayCounter_(Thirty360(Thirty360::BondBasis)),
185 paymentCalendar_(schedule_.calendar()) {}
186
187
190 return *this;
191 }
192
193
195 fixedRates_ = std::vector<Real>(1,fixedRate);
196 return *this;
197 }
198
199 CPILeg& CPILeg::withFixedRates(const std::vector<Real>& fixedRates) {
200 fixedRates_ = fixedRates;
201 return *this;
202 }
203
205 notionals_ = std::vector<Real>(1,notional);
206 return *this;
207 }
208
209 CPILeg& CPILeg::withNotionals(const std::vector<Real>& notionals) {
210 notionals_ = notionals;
211 return *this;
212 }
213
215 subtractInflationNominal_ = growthOnly;
216 return *this;
217 }
218
220 paymentDayCounter_ = dayCounter;
221 return *this;
222 }
223
225 paymentAdjustment_ = convention;
226 return *this;
227 }
228
230 paymentCalendar_ = cal;
231 return *this;
232 }
233
235 caps_ = std::vector<Rate>(1,cap);
236 return *this;
237 }
238
239 CPILeg& CPILeg::withCaps(const std::vector<Rate>& caps) {
240 caps_ = caps;
241 return *this;
242 }
243
245 floors_ = std::vector<Rate>(1,floor);
246 return *this;
247 }
248
249 CPILeg& CPILeg::withFloors(const std::vector<Rate>& floors) {
250 floors_ = floors;
251 return *this;
252 }
253
255 const Period& period,
256 const Calendar& cal,
257 BusinessDayConvention convention,
258 bool endOfMonth) {
259 exCouponPeriod_ = period;
260 exCouponCalendar_ = cal;
261 exCouponAdjustment_ = convention;
262 exCouponEndOfMonth_ = endOfMonth;
263 return *this;
264 }
265
266 CPILeg& CPILeg::withBaseDate(const Date& baseDate) {
267 baseDate_ = baseDate;
268 return *this;
269 }
270
271
272 CPILeg::operator Leg() const {
273
274 QL_REQUIRE(!notionals_.empty(), "no notional given");
275 Size n = schedule_.size()-1;
276 Leg leg;
277 leg.reserve(n+1); // +1 for notional, we always have some sort ...
278
279 Date baseDate = baseDate_;
280 // BaseDate and baseCPI are not given, use the first date as startDate and the baseFixingg
281 // should be at startDate - observationLag
282
283 if (n>0) {
284 QL_REQUIRE(!fixedRates_.empty(), "no fixedRates given");
285
286 if (baseDate_ == Date() && baseCPI_ == Null<Real>()) {
287 baseDate = schedule_.date(0) - observationLag_;
288 }
289
290 Date refStart, start, refEnd, end;
291
292 for (Size i=0; i<n; ++i) {
293 refStart = start = schedule_.date(i);
294 refEnd = end = schedule_.date(i+1);
295 Date paymentDate = paymentCalendar_.adjust(end, paymentAdjustment_);
296
297 Date exCouponDate;
298 if (exCouponPeriod_ != Period())
299 {
300 exCouponDate = exCouponCalendar_.advance(paymentDate,
301 -exCouponPeriod_,
302 exCouponAdjustment_,
303 exCouponEndOfMonth_);
304 }
305
306 if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
307 BusinessDayConvention bdc = schedule_.businessDayConvention();
308 refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc);
309 }
310 if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
311 BusinessDayConvention bdc = schedule_.businessDayConvention();
312 refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc);
313 }
314 if (detail::get(fixedRates_, i, 1.0) == 0.0) { // fixed coupon
315 // this looks like an optimization but I'm not sure it's worth it?
316 leg.push_back(ext::make_shared<FixedRateCoupon>
317 (paymentDate, detail::get(notionals_, i, 0.0),
318 detail::effectiveFixedRate({},caps_,floors_,i),
319 paymentDayCounter_, start, end, refStart, refEnd, exCouponDate));
320 } else { // zero inflation coupon
321 if (detail::noOption(caps_, floors_, i)) { // just swaplet
322 leg.push_back(ext::make_shared<CPICoupon>
323 (baseCPI_, // all have same base for ratio
324 baseDate,
325 paymentDate,
326 detail::get(notionals_, i, 0.0),
327 start, end,
328 index_, observationLag_,
329 observationInterpolation_,
330 paymentDayCounter_,
331 detail::get(fixedRates_, i, 0.0),
332 refStart, refEnd, exCouponDate));
333 } else { // cap/floorlet
334 QL_FAIL("caps/floors on CPI coupons not implemented.");
335 }
336 }
337 }
338 }
339
340 // in CPI legs you always have a notional flow of some sort
341 Date paymentDate = paymentCalendar_.adjust(schedule_.date(n), paymentAdjustment_);
342 leg.push_back(ext::make_shared<CPICashFlow>
343 (detail::get(notionals_, n, 0.0), index_,
344 baseDate, baseCPI_,
345 schedule_.date(n), observationLag_, observationInterpolation_,
346 paymentDate, subtractInflationNominal_));
347
348 // no caps and floors here, so this is enough
349 setCouponPricer(leg, ext::make_shared<CPICouponPricer>());
350
351 return leg;
352 }
353
354}
Cash flow vector builders.
degenerate base class for the Acyclic Visitor pattern
Definition: visitor.hpp:33
CPICashFlow(Real notional, const ext::shared_ptr< ZeroInflationIndex > &index, const Date &baseDate, Real baseFixing, const Date &observationDate, const Period &observationLag, CPI::InterpolationType interpolation, const Date &paymentDate, bool growthOnly=false)
Definition: cpicoupon.cpp:139
ext::shared_ptr< ZeroInflationIndex > cpiIndex() const
Definition: cpicoupon.hpp:288
CPI::InterpolationType interpolation_
Definition: cpicoupon.hpp:198
Date baseDate() const override
you may not have a valid date
Definition: cpicoupon.cpp:159
Real baseFixing() const override
value used on base date
Definition: cpicoupon.cpp:168
Real indexFixing() const override
Definition: cpicoupon.cpp:175
Coupon paying the performance of a CPI (zero inflation) index
Definition: cpicoupon.hpp:55
bool checkPricerImpl(const ext::shared_ptr< InflationCouponPricer > &) const override
makes sure you were given the correct type of pricer
Definition: cpicoupon.cpp:131
CPICoupon(Real baseCPI, const Date &paymentDate, Real nominal, const Date &startDate, const Date &endDate, const ext::shared_ptr< ZeroInflationIndex > &index, const Period &observationLag, CPI::InterpolationType observationInterpolation, const DayCounter &dayCounter, Real fixedRate, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date(), const Date &exCouponDate=Date())
Definition: cpicoupon.cpp:32
Rate baseCPI() const
base value for the CPI index
Definition: cpicoupon.hpp:271
ext::shared_ptr< ZeroInflationIndex > cpiIndex() const
index used
Definition: cpicoupon.hpp:283
CPI::InterpolationType observationInterpolation() const
how do you observe the index? as-is, flat, linear?
Definition: cpicoupon.hpp:279
void accept(AcyclicVisitor &) override
Definition: cpicoupon.cpp:93
Rate indexRatio(Date d) const
the ratio between the index fixing at the passed date and the base CPI
Definition: cpicoupon.cpp:112
Date baseDate() const
base date for the base fixing of the CPI index
Definition: cpicoupon.hpp:275
Real accruedAmount(const Date &) const override
accrued amount at the given date
Definition: cpicoupon.cpp:101
Helper class building a sequence of capped/floored CPI coupons.
Definition: cpicoupon.hpp:209
CPILeg & withNotionals(Real notional)
Definition: cpicoupon.cpp:204
BusinessDayConvention paymentAdjustment_
Definition: cpicoupon.hpp:244
std::vector< Rate > caps_
Definition: cpicoupon.hpp:248
CPILeg & withPaymentAdjustment(BusinessDayConvention)
Definition: cpicoupon.cpp:224
BusinessDayConvention exCouponAdjustment_
Definition: cpicoupon.hpp:251
CPILeg & withSubtractInflationNominal(bool)
Definition: cpicoupon.cpp:214
Calendar paymentCalendar_
Definition: cpicoupon.hpp:245
CPILeg & withBaseDate(const Date &baseDate)
Definition: cpicoupon.cpp:266
CPILeg & withFixedRates(Real fixedRate)
Definition: cpicoupon.cpp:194
CPILeg & withExCouponPeriod(const Period &, const Calendar &, BusinessDayConvention, bool endOfMonth=false)
Definition: cpicoupon.cpp:254
std::vector< Real > notionals_
Definition: cpicoupon.hpp:241
CPILeg & withCaps(Rate cap)
Definition: cpicoupon.cpp:234
CPILeg & withPaymentDayCounter(const DayCounter &)
Definition: cpicoupon.cpp:219
CPILeg & withPaymentCalendar(const Calendar &)
Definition: cpicoupon.cpp:229
CPILeg & withFloors(Rate floor)
Definition: cpicoupon.cpp:244
CPILeg(Schedule schedule, ext::shared_ptr< ZeroInflationIndex > index, Real baseCPI, const Period &observationLag)
Definition: cpicoupon.cpp:179
bool exCouponEndOfMonth_
Definition: cpicoupon.hpp:252
std::vector< Real > fixedRates_
Definition: cpicoupon.hpp:242
CPI::InterpolationType observationInterpolation_
Definition: cpicoupon.hpp:246
Period exCouponPeriod_
Definition: cpicoupon.hpp:249
Calendar exCouponCalendar_
Definition: cpicoupon.hpp:250
std::vector< Rate > floors_
Definition: cpicoupon.hpp:248
bool subtractInflationNominal_
Definition: cpicoupon.hpp:247
CPILeg & withObservationInterpolation(CPI::InterpolationType)
Definition: cpicoupon.cpp:188
DayCounter paymentDayCounter_
Definition: cpicoupon.hpp:243
calendar class
Definition: calendar.hpp:61
Date adjust(const Date &, BusinessDayConvention convention=Following) const
Definition: calendar.cpp:84
Date paymentDate_
Definition: coupon.hpp:90
virtual Real nominal() const
Definition: coupon.hpp:100
Time accruedPeriod(const Date &) const
accrued period as fraction of year at the given date
Definition: coupon.cpp:57
Concrete date class.
Definition: date.hpp:125
static Date advance(const Date &d, Integer units, TimeUnit)
Definition: date.cpp:139
day counter class
Definition: daycounter.hpp:44
Cash flow dependent on an index ratio.
virtual Date baseDate() const
virtual ext::shared_ptr< Index > index() const
Base inflation-coupon class.
ext::shared_ptr< InflationCouponPricer > pricer_
ext::shared_ptr< InflationIndex > index_
ext::shared_ptr< InflationCouponPricer > pricer() const
void accept(AcyclicVisitor &) override
Period observationLag() const
how the coupon observes the index
template class providing a null value for a given type.
Definition: null.hpp:59
Payment schedule.
Definition: schedule.hpp:40
30/360 day count convention
Definition: thirty360.hpp:76
Visitor for a specific class
Definition: visitor.hpp:40
virtual void visit(T &)=0
Coupon paying a zero-inflation index.
zero inflation-coupon pricer
Calendar paymentCalendar_
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
Date d
BusinessDayConvention
Business Day conventions.
@ NoFrequency
null frequency
Definition: frequency.hpp:37
QL_REAL Real
real number
Definition: types.hpp:50
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
Coupon paying a variable index-based rate.
T get(const std::vector< T > &v, Size i, U defaultValue)
Definition: vectors.hpp:33
Rate effectiveFixedRate(const std::vector< Spread > &spreads, const std::vector< Rate > &caps, const std::vector< Rate > &floors, Size i)
bool noOption(const std::vector< Rate > &caps, const std::vector< Rate > &floors, Size i)
Definition: any.hpp:37
void setCouponPricer(const Leg &leg, const ext::shared_ptr< FloatingRateCouponPricer > &pricer)
std::vector< ext::shared_ptr< CashFlow > > Leg
Sequence of cash-flows.
Definition: cashflow.hpp:78
STL namespace.
ext::shared_ptr< BlackVolTermStructure > v
static Real laggedFixing(const ext::shared_ptr< ZeroInflationIndex > &index, const Date &date, const Period &observationLag, InterpolationType interpolationType)
interpolated inflation fixing
InterpolationType
when you observe an index, how do you interpolate between fixings?
30/360 day counters