QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
inflationindex.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) 2007 Chris Kenyon
5 Copyright (C) 2021 Ralf Konrad Eckel
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
24#include <utility>
25
26namespace QuantLib {
27
28 Real CPI::laggedFixing(const ext::shared_ptr<ZeroInflationIndex>& index,
29 const Date& date,
30 const Period& observationLag,
31 CPI::InterpolationType interpolationType) {
32
33 switch (interpolationType) {
34 case AsIndex: {
35 return index->fixing(date - observationLag);
36 }
37 case Flat: {
38 auto fixingPeriod = inflationPeriod(date - observationLag, index->frequency());
39 return index->fixing(fixingPeriod.first);
40 }
41 case Linear: {
42 auto fixingPeriod = inflationPeriod(date - observationLag, index->frequency());
43 auto interpolationPeriod = inflationPeriod(date, index->frequency());
44
45 if (date == interpolationPeriod.first) {
46 // special case; no interpolation. This avoids asking for
47 // the fixing at the end of the period, which might need a
48 // forecast curve to be set.
49 return index->fixing(fixingPeriod.first);
50 }
51
52 static const auto oneDay = Period(1, Days);
53
54 auto I0 = index->fixing(fixingPeriod.first);
55 auto I1 = index->fixing(fixingPeriod.second + oneDay);
56
57 return I0 + (I1 - I0) * (date - interpolationPeriod.first) /
58 (Real)((interpolationPeriod.second + oneDay) - interpolationPeriod.first);
59 }
60 default:
61 QL_FAIL("unknown CPI interpolation type: " << int(interpolationType));
62 }
63 }
64
65
66 InflationIndex::InflationIndex(std::string familyName,
67 Region region,
68 bool revised,
69 Frequency frequency,
70 const Period& availabilityLag,
71 Currency currency)
72 : familyName_(std::move(familyName)), region_(std::move(region)), revised_(revised),
73 frequency_(frequency), availabilityLag_(availabilityLag), currency_(std::move(currency)) {
74 name_ = region_.name() + " " + familyName_;
75 registerWith(Settings::instance().evaluationDate());
77 }
78
80 static NullCalendar c;
81 return c;
82 }
83
84 void InflationIndex::addFixing(const Date& fixingDate,
85 Real fixing,
86 bool forceOverwrite) {
87
88 std::pair<Date,Date> lim = inflationPeriod(fixingDate, frequency_);
89 Size n = static_cast<QuantLib::Size>(lim.second - lim.first) + 1;
90 std::vector<Date> dates(n);
91 std::vector<Rate> rates(n);
92 for (Size i=0; i<n; ++i) {
93 dates[i] = lim.first + i;
94 rates[i] = fixing;
95 }
96
97 Index::addFixings(dates.begin(), dates.end(),
98 rates.begin(), forceOverwrite);
99 }
100
101 ZeroInflationIndex::ZeroInflationIndex(const std::string& familyName,
102 const Region& region,
103 bool revised,
104 Frequency frequency,
105 const Period& availabilityLag,
106 const Currency& currency,
108 : InflationIndex(familyName, region, revised, frequency, availabilityLag, currency),
109 zeroInflation_(std::move(zeroInflation)) {
111 }
112
114 bool /*forecastTodaysFixing*/) const {
115 if (!needsForecast(fixingDate)) {
116 std::pair<Date,Date> p = inflationPeriod(fixingDate, frequency_);
117 const TimeSeries<Real>& ts = timeSeries();
118
119 Real I1 = ts[p.first];
120 QL_REQUIRE(I1 != Null<Real>(),
121 "Missing " << name() << " fixing for " << p.first);
122
123 return I1;
124 } else {
125 return forecastFixing(fixingDate);
126 }
127 }
128
130 const auto& fixings = timeSeries();
131 QL_REQUIRE(!fixings.empty(), "no fixings stored for " << name());
132 // attribute fixing to first day of the underlying period
133 return inflationPeriod(fixings.lastDate(), frequency_).first;
134 }
135
136 bool ZeroInflationIndex::needsForecast(const Date& fixingDate) const {
137
138 // Stored fixings are always non-interpolated.
139 // If an interpolated fixing is required then
140 // the availability lag + one inflation period
141 // must have passed to use historical fixings
142 // (because you need the next one to interpolate).
143 // The interpolation is calculated (linearly) on demand.
144
146 Date todayMinusLag = today - availabilityLag_;
147
148 Date historicalFixingKnown =
149 inflationPeriod(todayMinusLag, frequency_).first-1;
150 Date latestNeededDate = fixingDate;
151
152 if (latestNeededDate <= historicalFixingKnown) {
153 // the fixing date is well before the availability lag, so
154 // we know that fixings were provided.
155 return false;
156 } else if (latestNeededDate > today) {
157 // the fixing can't be available, no matter what's in the
158 // time series
159 return true;
160 } else {
161 // we're not sure, but the fixing might be there so we
162 // check. Todo: check which fixings are not possible, to
163 // avoid using fixings in the future
164 Date first = Date(1, latestNeededDate.month(), latestNeededDate.year());
165 Real f = timeSeries()[first];
166 return (f == Null<Real>());
167 }
168 }
169
170
172 // the term structure is relative to the fixing value at the base date.
173 Date baseDate = zeroInflation_->baseDate();
174 QL_REQUIRE(!needsForecast(baseDate),
175 name() << " index fixing at base date " << baseDate << " is not available");
176 Real baseFixing = fixing(baseDate);
177
178 std::pair<Date, Date> p = inflationPeriod(fixingDate, frequency_);
179
180 Date firstDateInPeriod = p.first;
181 Rate Z1 = zeroInflation_->zeroRate(firstDateInPeriod, Period(0,Days), false);
182 Time t1 = inflationYearFraction(frequency_, false, zeroInflation_->dayCounter(),
183 baseDate, firstDateInPeriod);
184 return baseFixing * std::pow(1.0 + Z1, t1);
185 }
186
187
188 ext::shared_ptr<ZeroInflationIndex> ZeroInflationIndex::clone(
189 const Handle<ZeroInflationTermStructure>& h) const {
190 return ext::make_shared<ZeroInflationIndex>(
192 }
193
194
195 YoYInflationIndex::YoYInflationIndex(const ext::shared_ptr<ZeroInflationIndex>& underlyingIndex,
196 bool interpolated,
198 : InflationIndex("YYR_" + underlyingIndex->familyName(), underlyingIndex->region(),
199 underlyingIndex->revised(), underlyingIndex->frequency(),
200 underlyingIndex->availabilityLag(), underlyingIndex->currency()),
201 interpolated_(interpolated), ratio_(true), underlyingIndex_(underlyingIndex),
202 yoyInflation_(std::move(yoyInflation)) {
205 }
206
208
209 YoYInflationIndex::YoYInflationIndex(const std::string& familyName,
210 const Region& region,
211 bool revised,
212 bool interpolated,
213 Frequency frequency,
214 const Period& availabilityLag,
215 const Currency& currency,
217 : YoYInflationIndex(familyName, region, revised, interpolated, false,
218 frequency, availabilityLag, currency, std::move(yoyInflation)) {}
219
221
222 YoYInflationIndex::YoYInflationIndex(const std::string& familyName,
223 const Region& region,
224 bool revised,
225 bool interpolated,
226 bool ratio,
227 Frequency frequency,
228 const Period& availabilityLag,
229 const Currency& currency,
231 : InflationIndex(familyName, region, revised, frequency, availabilityLag, currency),
232 interpolated_(interpolated), ratio_(ratio), yoyInflation_(std::move(yoyInflation)) {
233 if (ratio)
234 underlyingIndex_ = ext::make_shared<ZeroInflationIndex>(familyName, region, revised,
237 }
238
239
241 bool /*forecastTodaysFixing*/) const {
242
244 Date todayMinusLag = today - availabilityLag_;
245 std::pair<Date,Date> lim = inflationPeriod(todayMinusLag, frequency_);
246 Date lastFix = lim.first-1;
247
248 Date flatMustForecastOn = lastFix+1;
249 Date interpMustForecastOn = lastFix+1 - Period(frequency_);
250
251 if (interpolated() && fixingDate >= interpMustForecastOn) {
252 return forecastFixing(fixingDate);
253 }
254
255 if (!interpolated() && fixingDate >= flatMustForecastOn) {
256 return forecastFixing(fixingDate);
257 }
258
259 const TimeSeries<Real>& ts = timeSeries();
260 if (ratio()) {
261
262 auto interpolationType = interpolated() ? CPI::Linear : CPI::Flat;
263
264 Rate pastFixing = CPI::laggedFixing(underlyingIndex_, fixingDate, Period(0, Months), interpolationType);
265 Rate previousFixing = CPI::laggedFixing(underlyingIndex_, fixingDate - 1*Years, Period(0, Months), interpolationType);
266
267 return pastFixing/previousFixing - 1.0;
268
269 } else { // NOT ratio
270
271 if (interpolated()) { // NOT ratio, IS interpolated
272
273 std::pair<Date,Date> lim = inflationPeriod(fixingDate, frequency_);
274 Real dp = lim.second + 1 - lim.first;
275 Real dl = fixingDate - lim.first;
276 Rate limFirstFix = ts[lim.first];
277 QL_REQUIRE(limFirstFix != Null<Rate>(),
278 "Missing " << name() << " fixing for "
279 << lim.first );
280 Rate limSecondFix = ts[lim.second+1];
281 QL_REQUIRE(limSecondFix != Null<Rate>(),
282 "Missing " << name() << " fixing for "
283 << lim.second+1 );
284 Real linearNow = limFirstFix + (limSecondFix-limFirstFix)*dl/dp;
285
286 return linearNow;
287
288 } else { // NOT ratio, NOT interpolated
289 // so just flat
290
291 std::pair<Date,Date> lim = inflationPeriod(fixingDate, frequency_);
292 Rate pastFixing = ts[lim.first];
293 QL_REQUIRE(pastFixing != Null<Rate>(),
294 "Missing " << name() << " fixing for " << lim.first);
295 return pastFixing;
296
297 }
298 }
299 }
300
301
302 Real YoYInflationIndex::forecastFixing(const Date& fixingDate) const {
303
304 Date d;
305 if (interpolated()) {
306 d = fixingDate;
307 } else {
308 // if the value is not interpolated use the starting value
309 // by internal convention this will be consistent
310 std::pair<Date,Date> lim = inflationPeriod(fixingDate, frequency_);
311 d = lim.first;
312 }
313 return yoyInflation_->yoyRate(d,0*Days);
314 }
315
316 ext::shared_ptr<YoYInflationIndex> YoYInflationIndex::clone(
317 const Handle<YoYInflationTermStructure>& h) const {
318 if (ratio_) {
319 return ext::make_shared<YoYInflationIndex>(underlyingIndex_, interpolated_, h);
320 } else {
321 return ext::make_shared<YoYInflationIndex>(familyName_, region_, revised_,
324 }
325 }
326
327
330 if (type == QuantLib::CPI::AsIndex) {
331 return QuantLib::CPI::Flat;
332 } else {
333 return type;
334 }
335 }
336
337}
calendar class
Definition: calendar.hpp:61
Currency specification
Definition: currency.hpp:36
Concrete date class.
Definition: date.hpp:125
Month month() const
Definition: date.cpp:82
Year year() const
Definition: date.cpp:93
Shared handle to an observable.
Definition: handle.hpp:41
const TimeSeries< Real > & timeSeries() const
returns the fixing TimeSeries
Definition: index.hpp:65
void addFixings(const TimeSeries< Real > &t, bool forceOverwrite=false)
stores historical fixings from a TimeSeries
Definition: index.cpp:33
Base class for inflation-rate indexes,.
InflationIndex(std::string familyName, Region region, bool revised, Frequency frequency, const Period &availabilitiyLag, Currency currency)
Calendar fixingCalendar() const override
std::string name() const override
Returns the name of the index.
void addFixing(const Date &fixingDate, Rate fixing, bool forceOverwrite=false) override
Frequency frequency() const
Period availabilityLag() const
std::string familyName() const
Real fixing(const Date &fixingDate, bool forecastTodaysFixing=false) const override=0
Calendar for reproducing theoretical calculations.
template class providing a null value for a given type.
Definition: null.hpp:76
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:228
Frequency frequency() const
Definition: period.cpp:69
Region class, used for inflation applicability.
Definition: region.hpp:36
const std::string & name() const
Definition: region.hpp:113
DateProxy & evaluationDate()
the date at which pricing is to be performed.
Definition: settings.hpp:147
static Settings & instance()
access to the unique instance
Definition: singleton.hpp:104
Container for historical data.
Definition: timeseries.hpp:51
Base class for year-on-year inflation indices.
Handle< YoYInflationTermStructure > yoyInflation_
ext::shared_ptr< YoYInflationIndex > clone(const Handle< YoYInflationTermStructure > &h) const
Rate forecastFixing(const Date &fixingDate) const
YoYInflationIndex(const ext::shared_ptr< ZeroInflationIndex > &underlyingIndex, bool interpolated, Handle< YoYInflationTermStructure > ts={})
Constructor for year-on-year indices defined as a ratio.
Rate fixing(const Date &fixingDate, bool forecastTodaysFixing=false) const override
ext::shared_ptr< ZeroInflationIndex > underlyingIndex_
ext::shared_ptr< ZeroInflationIndex > clone(const Handle< ZeroInflationTermStructure > &h) const
Handle< ZeroInflationTermStructure > zeroInflation_
ZeroInflationIndex(const std::string &familyName, const Region &region, bool revised, Frequency frequency, const Period &availabilityLag, const Currency &currency, Handle< ZeroInflationTermStructure > ts={})
Real forecastFixing(const Date &fixingDate) const
bool needsForecast(const Date &fixingDate) const
Real fixing(const Date &fixingDate, bool forecastTodaysFixing=false) const override
#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
Frequency
Frequency of events.
Definition: frequency.hpp:37
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
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
base classes for inflation indexes
Base classes for inflation term structures.
QuantLib::CPI::InterpolationType effectiveInterpolationType(const QuantLib::CPI::InterpolationType &type=QuantLib::CPI::AsIndex)
Definition: any.hpp:35
std::pair< Date, Date > inflationPeriod(const Date &d, Frequency frequency)
utility function giving the inflation period for a given date
Time inflationYearFraction(Frequency f, bool indexIsInterpolated, const DayCounter &dayCounter, const Date &d1, const Date &d2)
STL namespace.
Calendar for reproducing theoretical calculations.
#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?
@ AsIndex
same interpolation as index
@ Linear
linearly between bracketing fixings
@ Flat
flat from previous fixing