QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
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
35 const Date& paymentDate,
36 Real nominal,
37 const Date& startDate,
38 const Date& endDate,
39 const ext::shared_ptr<ZeroInflationIndex>& index,
40 const Period& observationLag,
41 CPI::InterpolationType observationInterpolation,
42 const DayCounter& dayCounter,
43 Real fixedRate,
44 const Date& refPeriodStart,
45 const Date& refPeriodEnd,
46 const Date& exCouponDate)
47 : CPICoupon(baseCPI, paymentDate, nominal, startDate, endDate, index,
48 observationLag, observationInterpolation, dayCounter,
49 fixedRate, 0.0, refPeriodStart, refPeriodEnd, exCouponDate) {}
50
51 CPICoupon::CPICoupon(const Date& baseDate,
52 const Date& paymentDate,
53 Real nominal,
54 const Date& startDate,
55 const Date& endDate,
56 const ext::shared_ptr<ZeroInflationIndex>& index,
57 const Period& observationLag,
58 CPI::InterpolationType observationInterpolation,
59 const DayCounter& dayCounter,
60 Real fixedRate,
61 const Date& refPeriodStart,
62 const Date& refPeriodEnd,
63 const Date& exCouponDate)
64 : CPICoupon(baseDate, paymentDate, nominal, startDate, endDate, index,
65 observationLag, observationInterpolation, dayCounter,
66 fixedRate, 0.0, refPeriodStart, refPeriodEnd, exCouponDate) {}
67
69 const Date& baseDate,
70 const Date& paymentDate,
71 Real nominal,
72 const Date& startDate,
73 const Date& endDate,
74 const ext::shared_ptr<ZeroInflationIndex>& index,
75 const Period& observationLag,
76 CPI::InterpolationType observationInterpolation,
77 const DayCounter& dayCounter,
78 Real fixedRate,
79 const Date& refPeriodStart,
80 const Date& refPeriodEnd,
81 const Date& exCouponDate)
82 : CPICoupon(baseCPI, baseDate, paymentDate, nominal, startDate, endDate, index,
83 observationLag, observationInterpolation, dayCounter,
84 fixedRate, 0.0, refPeriodStart, refPeriodEnd, exCouponDate) {}
85
87 const Date& paymentDate,
88 Real nominal,
89 const Date& startDate,
90 const Date& endDate,
91 const ext::shared_ptr<ZeroInflationIndex>& index,
92 const Period& observationLag,
93 CPI::InterpolationType observationInterpolation,
94 const DayCounter& dayCounter,
95 Real fixedRate,
96 Spread spread,
97 const Date& refPeriodStart,
98 const Date& refPeriodEnd,
99 const Date& exCouponDate)
100 : CPICoupon(baseCPI, Null<Date>(), paymentDate, nominal, startDate, endDate, index,
101 observationLag, observationInterpolation, dayCounter,
102 fixedRate, spread, refPeriodStart, refPeriodEnd, exCouponDate) {}
103
104 CPICoupon::CPICoupon(const Date& baseDate,
105 const Date& paymentDate,
106 Real nominal,
107 const Date& startDate,
108 const Date& endDate,
109 const ext::shared_ptr<ZeroInflationIndex>& index,
110 const Period& observationLag,
111 CPI::InterpolationType observationInterpolation,
112 const DayCounter& dayCounter,
113 Real fixedRate,
114 Spread spread,
115 const Date& refPeriodStart,
116 const Date& refPeriodEnd,
117 const Date& exCouponDate)
118 : CPICoupon(Null<Real>(), baseDate, paymentDate, nominal, startDate, endDate, index,
119 observationLag, observationInterpolation, dayCounter,
120 fixedRate, spread, refPeriodStart, refPeriodEnd, exCouponDate) {}
121
123 const Date& baseDate,
124 const Date& paymentDate,
125 Real nominal,
126 const Date& startDate,
127 const Date& endDate,
128 const ext::shared_ptr<ZeroInflationIndex>& index,
129 const Period& observationLag,
130 CPI::InterpolationType observationInterpolation,
131 const DayCounter& dayCounter,
132 Real fixedRate,
133 Spread spread,
134 const Date& refPeriodStart,
135 const Date& refPeriodEnd,
136 const Date& exCouponDate)
137 : InflationCoupon(paymentDate, nominal, startDate, endDate, 0,
138 index, observationLag, dayCounter,
139 refPeriodStart, refPeriodEnd, exCouponDate),
140 baseCPI_(baseCPI), fixedRate_(fixedRate), spread_(spread),
141 observationInterpolation_(observationInterpolation), baseDate_(baseDate) {
142
143 QL_REQUIRE(index_, "no index provided");
146 "baseCPI and baseDate can not be both null, provide a valid baseCPI or baseDate");
147 QL_REQUIRE(baseCPI_ == Null<Rate>() || std::fabs(baseCPI_) > 1e-16,
148 "|baseCPI_| < 1e-16, future divide-by-zero problem");
149 }
150
152
154 auto* v1 = dynamic_cast<Visitor<CPICoupon>*>(&v);
155 if (v1 != nullptr)
156 v1->visit(*this);
157 else
159 }
160
162 if (d <= accrualStartDate_ || d > paymentDate_) {
163 return 0.0;
164 } else {
165 auto pricer = ext::dynamic_pointer_cast<CPICouponPricer>(pricer_);
166 QL_REQUIRE(pricer, "pricer not set or of wrong type");
167 pricer->initialize(*this);
168 return nominal() * pricer->accruedRate(d) * accruedPeriod(d);
169 }
170 }
171
173
174 Rate I0 = baseCPI();
175
176 if (I0 == Null<Rate>()) {
181 }
182
184 d,
187
188 return I1 / I0;
189 }
190
192 const ext::shared_ptr<InflationCouponPricer>&pricer) const {
193 return static_cast<bool>(
194 ext::dynamic_pointer_cast<CPICouponPricer>(pricer));
195 }
196
197
198
200 const ext::shared_ptr<ZeroInflationIndex>& index,
201 const Date& baseDate,
202 Real baseFixing,
203 const Date& observationDate,
204 const Period& observationLag,
205 CPI::InterpolationType interpolation,
206 const Date& paymentDate,
207 bool growthOnly)
208 : IndexedCashFlow(notional, index, baseDate, observationDate - observationLag, paymentDate, growthOnly),
209 baseFixing_(baseFixing), observationDate_(observationDate), observationLag_(observationLag),
210 interpolation_(interpolation), frequency_(index ? index->frequency() : NoFrequency) {
211 QL_REQUIRE(index, "no index provided");
214 "baseCPI and baseDate can not be both null, provide a valid baseCPI or baseDate");
215 QL_REQUIRE(baseFixing_ == Null<Rate>() || std::fabs(baseFixing_) > 1e-16,
216 "|baseCPI_| < 1e-16, future divide-by-zero problem");
217 }
218
221 if (base != Date()) {
222 return base;
223 } else {
224 QL_FAIL("no base date specified");
225 }
226 }
227
229 return baseFixing_;
230 }
231
233 if (observationDate_ != Date()) {
235 } else {
236 // we get to this branch when the deprecated constructor was used; it will be phased out
239 }
240 }
241
243 Rate I0 = baseFixing();
244
245 // If BaseFixing is null, use the observed index fixing
246 if (I0 == Null<Rate>()) {
248 }
249
250 Rate I1 = indexFixing();
251
252 if (growthOnly())
253 return notional() * (I1 / I0 - 1.0);
254 else
255 return notional() * (I1 / I0);
256 }
257
259 ext::shared_ptr<ZeroInflationIndex> index,
260 const Real baseCPI,
261 const Period& observationLag)
262 : schedule_(std::move(schedule)), index_(std::move(index)), baseCPI_(baseCPI),
263 observationLag_(observationLag), paymentDayCounter_(Thirty360(Thirty360::BondBasis)),
264 paymentCalendar_(schedule_.calendar()),
265 spreads_(std::vector<Real>(1, 0)), baseDate_(Null<Date>()) {}
266
267
270 return *this;
271 }
272
273
275 fixedRates_ = std::vector<Real>(1,fixedRate);
276 return *this;
277 }
278
279 CPILeg& CPILeg::withFixedRates(const std::vector<Real>& fixedRates) {
280 fixedRates_ = fixedRates;
281 return *this;
282 }
283
285 notionals_ = std::vector<Real>(1,notional);
286 return *this;
287 }
288
289 CPILeg& CPILeg::withNotionals(const std::vector<Real>& notionals) {
290 notionals_ = notionals;
291 return *this;
292 }
293
295 subtractInflationNominal_ = growthOnly;
296 return *this;
297 }
298
300 paymentDayCounter_ = dayCounter;
301 return *this;
302 }
303
305 paymentAdjustment_ = convention;
306 return *this;
307 }
308
310 paymentCalendar_ = cal;
311 return *this;
312 }
313
315 spreads_ = std::vector<Spread>(1,spread);
316 return *this;
317 }
318
319 CPILeg& CPILeg::withSpreads(const std::vector<Spread>& spreads) {
320 spreads_ = spreads;
321 return *this;
322 }
323
325 caps_ = std::vector<Rate>(1,cap);
326 return *this;
327 }
328
329 CPILeg& CPILeg::withCaps(const std::vector<Rate>& caps) {
330 caps_ = caps;
331 return *this;
332 }
333
335 floors_ = std::vector<Rate>(1,floor);
336 return *this;
337 }
338
339 CPILeg& CPILeg::withFloors(const std::vector<Rate>& floors) {
340 floors_ = floors;
341 return *this;
342 }
343
345 const Period& period,
346 const Calendar& cal,
347 BusinessDayConvention convention,
348 bool endOfMonth) {
349 exCouponPeriod_ = period;
350 exCouponCalendar_ = cal;
351 exCouponAdjustment_ = convention;
352 exCouponEndOfMonth_ = endOfMonth;
353 return *this;
354 }
355
356 CPILeg& CPILeg::withBaseDate(const Date& baseDate) {
357 baseDate_ = baseDate;
358 return *this;
359 }
360
361
362 CPILeg::operator Leg() const {
363
364 QL_REQUIRE(!notionals_.empty(), "no notional given");
365 Size n = schedule_.size()-1;
366 Leg leg;
367 leg.reserve(n+1); // +1 for notional, we always have some sort ...
368
369 Date baseDate = baseDate_;
370 // BaseDate and baseCPI are not given, use the first date as startDate and the baseFixingg
371 // should be at startDate - observationLag
372
373 if (n>0) {
374 QL_REQUIRE(!fixedRates_.empty() || !spreads_.empty(),
375 "no fixedRates or spreads given");
376
377 if (baseDate_ == Null<Date>() && baseCPI_ == Null<Real>()) {
378 baseDate = schedule_.date(0) - observationLag_;
379 }
380
381 Date refStart, start, refEnd, end;
382
383 for (Size i=0; i<n; ++i) {
384 refStart = start = schedule_.date(i);
385 refEnd = end = schedule_.date(i+1);
386 Date paymentDate = paymentCalendar_.adjust(end, paymentAdjustment_);
387
388 Date exCouponDate;
389 if (exCouponPeriod_ != Period())
390 {
391 exCouponDate = exCouponCalendar_.advance(paymentDate,
392 -exCouponPeriod_,
393 exCouponAdjustment_,
394 exCouponEndOfMonth_);
395 }
396
397 if (i==0 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
398 BusinessDayConvention bdc = schedule_.businessDayConvention();
399 refStart = schedule_.calendar().adjust(end - schedule_.tenor(), bdc);
400 }
401 if (i==n-1 && schedule_.hasIsRegular() && !schedule_.isRegular(i+1)) {
402 BusinessDayConvention bdc = schedule_.businessDayConvention();
403 refEnd = schedule_.calendar().adjust(start + schedule_.tenor(), bdc);
404 }
405 if (detail::get(fixedRates_, i, 1.0) == 0.0) { // fixed coupon
406 leg.push_back(ext::make_shared<FixedRateCoupon>
407 (paymentDate, detail::get(notionals_, i, 0.0),
408 detail::effectiveFixedRate(spreads_,caps_,floors_,i),
409 paymentDayCounter_, start, end, refStart, refEnd, exCouponDate));
410 } else { // zero inflation coupon
411 if (detail::noOption(caps_, floors_, i)) { // just swaplet
413 leg.push_back(ext::make_shared<CPICoupon>
414 (baseCPI_, // all have same base for ratio
415 baseDate,
416 paymentDate,
417 detail::get(notionals_, i, 0.0),
418 start, end,
419 index_, observationLag_,
420 observationInterpolation_,
421 paymentDayCounter_,
422 detail::get(fixedRates_, i, 0.0),
423 detail::get(spreads_, i, 0.0),
424 refStart, refEnd, exCouponDate));
426 } else { // cap/floorlet
427 QL_FAIL("caps/floors on CPI coupons not implemented.");
428 }
429 }
430 }
431 }
432
433 // in CPI legs you always have a notional flow of some sort
434 Date paymentDate = paymentCalendar_.adjust(schedule_.date(n), paymentAdjustment_);
435 leg.push_back(ext::make_shared<CPICashFlow>
436 (detail::get(notionals_, n, 0.0), index_,
437 baseDate, baseCPI_,
438 schedule_.date(n), observationLag_, observationInterpolation_,
439 paymentDate, subtractInflationNominal_));
440
441 // no caps and floors here, so this is enough
442 setCouponPricer(leg, ext::make_shared<CPICouponPricer>());
443
444 return leg;
445 }
446
447}
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:199
ext::shared_ptr< ZeroInflationIndex > cpiIndex() const
Definition: cpicoupon.hpp:375
CPI::InterpolationType interpolation_
Definition: cpicoupon.hpp:266
Date baseDate() const override
you may not have a valid date
Definition: cpicoupon.cpp:219
Real amount() const override
returns the amount of the cash flow
Definition: cpicoupon.cpp:242
Real baseFixing() const override
value used on base date
Definition: cpicoupon.cpp:228
Real indexFixing() const override
Definition: cpicoupon.cpp:232
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:191
void accept(AcyclicVisitor &) override
Definition: cpicoupon.cpp:153
Rate baseCPI() const
base value for the CPI index
Definition: cpicoupon.hpp:358
ext::shared_ptr< ZeroInflationIndex > cpiIndex() const
index used
Definition: cpicoupon.hpp:370
CPI::InterpolationType observationInterpolation() const
how do you observe the index? as-is, flat, linear?
Definition: cpicoupon.hpp:366
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:34
Rate indexRatio(Date d) const
the ratio between the index fixing at the passed date and the base CPI
Definition: cpicoupon.cpp:172
Date baseDate() const
base date for the base fixing of the CPI index
Definition: cpicoupon.hpp:362
Real accruedAmount(const Date &) const override
accrued amount at the given date
Definition: cpicoupon.cpp:161
Helper class building a sequence of capped/floored CPI coupons.
Definition: cpicoupon.hpp:277
CPILeg & withNotionals(Real notional)
Definition: cpicoupon.cpp:284
BusinessDayConvention paymentAdjustment_
Definition: cpicoupon.hpp:322
std::vector< Rate > caps_
Definition: cpicoupon.hpp:327
CPILeg & withPaymentAdjustment(BusinessDayConvention)
Definition: cpicoupon.cpp:304
BusinessDayConvention exCouponAdjustment_
Definition: cpicoupon.hpp:330
CPILeg & withSubtractInflationNominal(bool)
Definition: cpicoupon.cpp:294
Calendar paymentCalendar_
Definition: cpicoupon.hpp:323
CPILeg & withBaseDate(const Date &baseDate)
Definition: cpicoupon.cpp:356
CPILeg & withFixedRates(Real fixedRate)
Definition: cpicoupon.cpp:274
CPILeg & withExCouponPeriod(const Period &, const Calendar &, BusinessDayConvention, bool endOfMonth=false)
Definition: cpicoupon.cpp:344
std::vector< Real > notionals_
Definition: cpicoupon.hpp:319
std::vector< Spread > spreads_
Definition: cpicoupon.hpp:326
CPILeg & withCaps(Rate cap)
Definition: cpicoupon.cpp:324
CPILeg & withPaymentDayCounter(const DayCounter &)
Definition: cpicoupon.cpp:299
CPILeg & withPaymentCalendar(const Calendar &)
Definition: cpicoupon.cpp:309
CPILeg & withSpreads(Spread spread)
Definition: cpicoupon.cpp:314
CPILeg & withFloors(Rate floor)
Definition: cpicoupon.cpp:334
CPILeg(Schedule schedule, ext::shared_ptr< ZeroInflationIndex > index, Real baseCPI, const Period &observationLag)
Definition: cpicoupon.cpp:258
bool exCouponEndOfMonth_
Definition: cpicoupon.hpp:331
std::vector< Real > fixedRates_
Definition: cpicoupon.hpp:320
CPI::InterpolationType observationInterpolation_
Definition: cpicoupon.hpp:324
Period exCouponPeriod_
Definition: cpicoupon.hpp:328
Calendar exCouponCalendar_
Definition: cpicoupon.hpp:329
std::vector< Rate > floors_
Definition: cpicoupon.hpp:327
bool subtractInflationNominal_
Definition: cpicoupon.hpp:325
CPILeg & withObservationInterpolation(CPI::InterpolationType)
Definition: cpicoupon.cpp:268
DayCounter paymentDayCounter_
Definition: cpicoupon.hpp:321
calendar class
Definition: calendar.hpp:61
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 fixingDate() const
virtual Real notional() const
virtual Real baseFixing() const
virtual Date baseDate() const
virtual bool growthOnly() 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:76
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
#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 Spread
spreads on interest rates
Definition: types.hpp:74
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:35
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:35
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
#define QL_DEPRECATED_DISABLE_WARNING
Definition: qldefines.hpp:216
#define QL_DEPRECATED_ENABLE_WARNING
Definition: qldefines.hpp:217
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