Coverage Report

Created: 2026-06-08 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/indexes/inflationindex.hpp
Line
Count
Source
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
 <https://www.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
/*! \file inflationindex.hpp
22
    \brief base classes for inflation indexes
23
*/
24
25
#ifndef quantlib_inflation_index_hpp
26
#define quantlib_inflation_index_hpp
27
28
#include <ql/currency.hpp>
29
#include <ql/handle.hpp>
30
#include <ql/index.hpp>
31
#include <ql/indexes/region.hpp>
32
#include <ql/termstructures/inflationtermstructure.hpp>
33
34
namespace QuantLib {
35
36
    class ZeroInflationIndex;
37
    class YoYInflationIndex;
38
39
    struct CPI {
40
41
        //! when you observe an index, how do you interpolate between fixings?
42
        /*! AsIndex was used to facilitate migration from the index to
43
            the coupons using it.  Deprecated in version 1.43.
44
        */
45
        enum InterpolationType {
46
            AsIndex [[deprecated("Use either Linear or Flat")]] = 0, //!< same interpolation as index
47
            Flat = 1,    //!< flat from previous fixing
48
            Linear = 2   //!< linearly between bracketing fixings
49
        };
50
51
        //! interpolated inflation fixing
52
        /*! \param index              The index whose fixing should be retrieved
53
            \param date               The date without lag; usually, the payment
54
                                      date for some inflation-based coupon.
55
            \param observationLag     The observation lag to be subtracted from the
56
                                      passed date; for instance, if the passed date is
57
                                      in May and the lag is three months, the inflation
58
                                      fixing from February (and March, in case of
59
                                      interpolation) will be observed.
60
            \param interpolationType  The interpolation type (flat or linear)
61
        */
62
        static Real laggedFixing(const ext::shared_ptr<ZeroInflationIndex>& index,
63
                                 const Date& date,
64
                                 const Period& observationLag,
65
                                 InterpolationType interpolationType);
66
67
68
        //! interpolated year-on-year inflation rate
69
        /*! \param index              The index whose fixing should be retrieved
70
            \param date               The date without lag; usually, the payment
71
                                      date for some inflation-based coupon.
72
            \param observationLag     The observation lag to be subtracted from the
73
                                      passed date; for instance, if the passed date is
74
                                      in May and the lag is three months, the year-on-year
75
                                      rate from February (and March, in case of
76
                                      interpolation) will be observed.
77
            \param interpolationType  The interpolation type (flat or linear)
78
        */
79
        static Real laggedYoYRate(const ext::shared_ptr<YoYInflationIndex>& index,
80
                                  const Date& date,
81
                                  const Period& observationLag,
82
                                  InterpolationType interpolationType);
83
    };
84
85
86
    //! Base class for inflation-rate indexes,
87
    class InflationIndex : public Index {
88
      public:
89
        InflationIndex(std::string familyName,
90
                       Region region,
91
                       bool revised,
92
                       Frequency frequency,
93
                       const Period& availabilitiyLag,
94
                       Currency currency);
95
96
        //! \name Index interface
97
        //@{
98
        std::string name() const override;
99
100
        /*! Inflation indices are not associated to a particular day,
101
            but to months or quarters.  Therefore, they do not have
102
            fixing calendars.  Since we're forced by the base `Index`
103
            interface to add one, this method returns a NullCalendar
104
            instance.
105
        */
106
        Calendar fixingCalendar() const override;
107
0
        bool isValidFixingDate(const Date&) const override { return true; }
108
109
        /*! Forecasting index values requires an inflation term
110
            structure, with a base date that is earlier than its asof
111
            date.  This must be so because indices are available only
112
            with a lag.  Usually, it makes sense for the base date to
113
            be the first day of the month of the last published
114
            fixing.
115
        */
116
        Real fixing(const Date& fixingDate, bool forecastTodaysFixing = false) const override = 0;
117
118
        //! returns a past fixing at the given date
119
        Real pastFixing(const Date& fixingDate) const override = 0;
120
121
        void addFixing(const Date& fixingDate, Rate fixing, bool forceOverwrite = false) override;
122
        //@}
123
124
        //! \name Inspectors
125
        //@{
126
        std::string familyName() const;
127
        Region region() const;
128
        bool revised() const;
129
        Frequency frequency() const;
130
        /*! The availability lag describes when the index might be
131
            available; for instance, the inflation value for January
132
            may only be available in April.  This doesn't mean that
133
            that inflation value is considered as the April fixing; it
134
            remains the January fixing, independently of the lag in
135
            availability.
136
        */
137
        Period availabilityLag() const;
138
        Currency currency() const;
139
        //@}
140
141
      protected:
142
        Date referenceDate_;
143
        std::string familyName_;
144
        Region region_;
145
        bool revised_;
146
        Frequency frequency_;
147
        Period availabilityLag_;
148
        Currency currency_;
149
150
      private:
151
        std::string name_;
152
    };
153
154
155
    //! Base class for zero inflation indices.
156
    class ZeroInflationIndex : public InflationIndex {
157
      public:
158
        ZeroInflationIndex(
159
            const std::string& familyName,
160
            const Region& region,
161
            bool revised,
162
            Frequency frequency,
163
            const Period& availabilityLag,
164
            const Currency& currency,
165
            Handle<ZeroInflationTermStructure> ts = {});
166
167
        //! \name Index interface
168
        //@{
169
        /*! \warning the forecastTodaysFixing parameter (required by
170
                     the Index interface) is currently ignored.
171
        */
172
        Real fixing(const Date& fixingDate, bool forecastTodaysFixing = false) const override;
173
        Real pastFixing(const Date& fixingDate) const override;
174
        //@}
175
        //! \name Other methods
176
        //@{
177
        Date lastFixingDate() const;
178
        Handle<ZeroInflationTermStructure> zeroInflationTermStructure() const;
179
        ext::shared_ptr<ZeroInflationIndex> clone(const Handle<ZeroInflationTermStructure>& h) const;
180
        bool needsForecast(const Date& fixingDate) const;
181
        //@}
182
      private:
183
        Real forecastFixing(const Date& fixingDate) const;
184
        Handle<ZeroInflationTermStructure> zeroInflation_;
185
    };
186
187
188
    //! Base class for year-on-year inflation indices.
189
    /*! These may be quoted indices published on, say, Bloomberg, or can be
190
        defined as the ratio of an index at different time points.
191
    */
192
    class YoYInflationIndex : public InflationIndex {
193
      public:
194
        //! \name Constructors
195
        //@{
196
        //! Constructor for year-on-year indices defined as a ratio.
197
        /*! An index build with this constructor won't store
198
            past fixings of its own; they will be calculated as a
199
            ratio from the past fixings stored in the underlying index.
200
        */
201
        explicit YoYInflationIndex(
202
            const ext::shared_ptr<ZeroInflationIndex>& underlyingIndex,
203
            Handle<YoYInflationTermStructure> ts = {});
204
205
        //! Constructor for quoted year-on-year indices.
206
        /*! An index built with this constructor needs its past
207
            fixings (i.e., the past year-on-year values) to be stored
208
            via the `addFixing` or `addFixings` method.
209
        */
210
        YoYInflationIndex(
211
            const std::string& familyName,
212
            const Region& region,
213
            bool revised,
214
            Frequency frequency,
215
            const Period& availabilityLag,
216
            const Currency& currency,
217
            Handle<YoYInflationTermStructure> ts = {});
218
219
        QL_DEPRECATED_DISABLE_WARNING
220
0
        ~YoYInflationIndex() override = default;
221
        QL_DEPRECATED_ENABLE_WARNING
222
223
        //! \name Index interface
224
        //@{
225
        /*! \warning the forecastTodaysFixing parameter (required by
226
                     the Index interface) is currently ignored.
227
        */
228
        Rate fixing(const Date& fixingDate, bool forecastTodaysFixing = false) const override;
229
        Real pastFixing(const Date& fixingDate) const override;
230
        //@}
231
232
        //! \name Other methods
233
        //@{
234
        Date lastFixingDate() const;
235
        /*! \deprecated Indexes no longer interpolate, coupons do.
236
                        Deprecated in version 1.43.
237
        */
238
        [[deprecated("Indexes no longer interpolate, coupons do")]]
239
        bool interpolated() const;
240
        bool ratio() const;
241
        ext::shared_ptr<ZeroInflationIndex> underlyingIndex() const;
242
        Handle<YoYInflationTermStructure> yoyInflationTermStructure() const;
243
244
        ext::shared_ptr<YoYInflationIndex> clone(const Handle<YoYInflationTermStructure>& h) const;
245
        bool needsForecast(const Date& fixingDate) const;
246
        //@}
247
248
      protected:
249
        /*! \deprecated Indexes no longer interpolate, coupons do.
250
                        Deprecated in version 1.43.
251
        */
252
        [[deprecated("Indexes no longer interpolate, coupons do")]]
253
        bool interpolated_ = false;
254
255
      private:
256
        Rate forecastFixing(const Date& fixingDate) const;
257
        bool ratio_;
258
        ext::shared_ptr<ZeroInflationIndex> underlyingIndex_;
259
        Handle<YoYInflationTermStructure> yoyInflation_;
260
    };
261
262
263
    namespace detail::CPI {
264
265
        // Returns either CPI::Flat or CPI::Linear depending on the combination of index and
266
        // CPI::InterpolationType.
267
        QuantLib::CPI::InterpolationType
268
        effectiveInterpolationType(const QuantLib::CPI::InterpolationType& type);
269
270
        QuantLib::CPI::InterpolationType
271
        effectiveInterpolationType(const QuantLib::CPI::InterpolationType& type,
272
                                   const ext::shared_ptr<YoYInflationIndex>& index);
273
274
        // checks whether the combination of index and CPI::InterpolationType results
275
        // effectively in CPI::Linear
276
        bool isInterpolated(const QuantLib::CPI::InterpolationType& type);
277
278
        bool isInterpolated(const QuantLib::CPI::InterpolationType& type,
279
                            const ext::shared_ptr<YoYInflationIndex>& index);
280
281
    }
282
283
284
    // inline
285
286
0
    inline std::string InflationIndex::name() const {
287
0
        return name_;
288
0
    }
289
290
0
    inline std::string InflationIndex::familyName() const {
291
0
        return familyName_;
292
0
    }
293
294
0
    inline Region InflationIndex::region() const {
295
0
        return region_;
296
0
    }
297
298
0
    inline bool InflationIndex::revised() const {
299
0
        return revised_;
300
0
    }
301
302
0
    inline Frequency InflationIndex::frequency() const {
303
0
        return frequency_;
304
0
    }
305
306
0
    inline Period InflationIndex::availabilityLag() const {
307
0
        return availabilityLag_;
308
0
    }
309
310
0
    inline Currency InflationIndex::currency() const {
311
0
        return currency_;
312
0
    }
313
314
    inline Handle<ZeroInflationTermStructure>
315
0
    ZeroInflationIndex::zeroInflationTermStructure() const {
316
0
        return zeroInflation_;
317
0
    }
318
319
    QL_DEPRECATED_DISABLE_WARNING
320
0
    inline bool YoYInflationIndex::interpolated() const {
321
0
        return interpolated_;
322
0
    }
323
    QL_DEPRECATED_ENABLE_WARNING
324
325
0
    inline bool YoYInflationIndex::ratio() const {
326
0
        return ratio_;
327
0
    }
328
329
0
    inline ext::shared_ptr<ZeroInflationIndex> YoYInflationIndex::underlyingIndex() const {
330
0
        return underlyingIndex_;
331
0
    }
332
333
    inline Handle<YoYInflationTermStructure>
334
0
    YoYInflationIndex::yoyInflationTermStructure() const {
335
0
        return yoyInflation_;
336
0
    }
337
338
}
339
340
#endif