1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2007, 2009 Chris Kenyon
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/indexes/inflationindex.hpp>
21#include <ql/termstructures/inflationtermstructure.hpp>
22#include <utility>
23
24namespace QuantLib {
25
26 InflationTermStructure::InflationTermStructure(
27 Rate baseRate,
28 const Period& observationLag,
29 Frequency frequency,
30 const DayCounter& dayCounter,
31 ext::shared_ptr<Seasonality> seasonality)
32 : TermStructure(dayCounter), seasonality_(std::move(seasonality)),
33 observationLag_(observationLag), frequency_(frequency),
34 baseRate_(baseRate) {
35 if (seasonality_ != nullptr) {
36 QL_REQUIRE(seasonality_->isConsistent(*this),
37 "Seasonality inconsistent with inflation term structure");
38 }
39 }
40
41 InflationTermStructure::InflationTermStructure(
42 const Date& referenceDate,
43 Rate baseRate,
44 const Period& observationLag,
45 Frequency frequency,
46 const Calendar& calendar,
47 const DayCounter& dayCounter,
48 ext::shared_ptr<Seasonality> seasonality)
49 : TermStructure(referenceDate, calendar, dayCounter), seasonality_(std::move(seasonality)),
50 observationLag_(observationLag), frequency_(frequency), baseRate_(baseRate) {
51 if (seasonality_ != nullptr) {
52 QL_REQUIRE(seasonality_->isConsistent(*this),
53 "Seasonality inconsistent with inflation term structure");
54 }
55 }
56
57 InflationTermStructure::InflationTermStructure(
58 Natural settlementDays,
59 const Calendar& calendar,
60 Rate baseRate,
61 const Period& observationLag,
62 Frequency frequency,
63 const DayCounter &dayCounter,
64 ext::shared_ptr<Seasonality> seasonality)
65 : TermStructure(settlementDays, calendar, dayCounter), seasonality_(std::move(seasonality)),
66 observationLag_(observationLag), frequency_(frequency),
67 baseRate_(baseRate) {
68 if (seasonality_ != nullptr) {
69 QL_REQUIRE(seasonality_->isConsistent(*this),
70 "Seasonality inconsistent with inflation term structure");
71 }
72 }
73
74 void InflationTermStructure::setSeasonality(
75 const ext::shared_ptr<Seasonality>& seasonality) {
76 // always reset, whether with null or new pointer
77 seasonality_ = seasonality;
78 if (seasonality_ != nullptr) {
79 QL_REQUIRE(seasonality_->isConsistent(*this),
80 "Seasonality inconsistent with inflation term structure");
81 }
82 update();
83 }
84
85
86 void InflationTermStructure::checkRange(const Date& d,
87 bool extrapolate) const {
88 QL_REQUIRE(d >= baseDate(),
89 "date (" << d << ") is before base date (" << baseDate() << ")");
90 QL_REQUIRE(extrapolate || allowsExtrapolation() || d <= maxDate(),
91 "date (" << d << ") is past max curve date ("
92 << maxDate() << ")");
93 }
94
95 void InflationTermStructure::checkRange(Time t,
96 bool extrapolate) const {
97 QL_REQUIRE(t >= timeFromReference(baseDate()),
98 "time (" << t << ") is before base date");
99 QL_REQUIRE(extrapolate || allowsExtrapolation() || t <= maxTime(),
100 "time (" << t << ") is past max curve time ("
101 << maxTime() << ")");
102 }
103
104
105
106 ZeroInflationTermStructure::ZeroInflationTermStructure(
107 const DayCounter& dayCounter,
108 Rate baseZeroRate,
109 const Period& observationLag,
110 Frequency frequency,
111 const ext::shared_ptr<Seasonality> &seasonality)
112 : InflationTermStructure(baseZeroRate, observationLag, frequency,
113 dayCounter, seasonality) {}
114
115 ZeroInflationTermStructure::ZeroInflationTermStructure(
116 const Date& referenceDate,
117 const Calendar& calendar,
118 const DayCounter& dayCounter,
119 Rate baseZeroRate,
120 const Period& observationLag,
121 Frequency frequency,
122 const ext::shared_ptr<Seasonality> &seasonality)
123 : InflationTermStructure(referenceDate, baseZeroRate, observationLag, frequency,
124 calendar, dayCounter, seasonality) {}
125
126 ZeroInflationTermStructure::ZeroInflationTermStructure(
127 Natural settlementDays,
128 const Calendar& calendar,
129 const DayCounter& dayCounter,
130 Rate baseZeroRate,
131 const Period& observationLag,
132 Frequency frequency,
133 const ext::shared_ptr<Seasonality> &seasonality)
134 : InflationTermStructure(settlementDays, calendar, baseZeroRate, observationLag, frequency,
135 dayCounter, seasonality) {}
136
137 Rate ZeroInflationTermStructure::zeroRate(const Date &d, const Period& instObsLag,
138 bool forceLinearInterpolation,
139 bool extrapolate) const {
140
141 Period useLag = instObsLag;
142 if (instObsLag == Period(-1,Days)) {
143 useLag = observationLag();
144 }
145
146 Rate zeroRate;
147 if (forceLinearInterpolation) {
148 std::pair<Date,Date> dd = inflationPeriod(d-useLag, frequency());
149 dd.second = dd.second + Period(1,Days);
150 Real dp = dd.second - dd.first;
151 Real dt = d - dd.first;
152 // if we are interpolating we only check the exact point
153 // this prevents falling off the end at curve maturity
154 InflationTermStructure::checkRange(d, extrapolate);
155 Time t1 = timeFromReference(d: dd.first);
156 Time t2 = timeFromReference(d: dd.second);
157 Rate z1 = zeroRateImpl(t: t1);
158 Rate z2 = zeroRateImpl(t: t2);
159 zeroRate = z1 + (z2-z1) * (dt/dp);
160 } else {
161 std::pair<Date,Date> dd = inflationPeriod(d-useLag, frequency());
162 InflationTermStructure::checkRange(d: dd.first, extrapolate);
163 Time t = timeFromReference(d: dd.first);
164 zeroRate = zeroRateImpl(t);
165 }
166
167 if (hasSeasonality()) {
168 zeroRate = seasonality()->correctZeroRate(d: d-useLag, r: zeroRate, iTS: *this);
169 }
170 return zeroRate;
171 }
172
173 Rate ZeroInflationTermStructure::zeroRate(Time t,
174 bool extrapolate) const {
175 checkRange(t, extrapolate);
176 return zeroRateImpl(t);
177 }
178
179
180 YoYInflationTermStructure::YoYInflationTermStructure(
181 const DayCounter& dayCounter,
182 Rate baseYoYRate,
183 const Period& observationLag,
184 Frequency frequency,
185 bool indexIsInterpolated,
186 const ext::shared_ptr<Seasonality> &seasonality)
187 : InflationTermStructure(baseYoYRate, observationLag, frequency,
188 dayCounter, seasonality),
189 indexIsInterpolated_(indexIsInterpolated) {}
190
191 YoYInflationTermStructure::YoYInflationTermStructure(
192 const Date& referenceDate,
193 const Calendar& calendar,
194 const DayCounter& dayCounter,
195 Rate baseYoYRate,
196 const Period& observationLag,
197 Frequency frequency,
198 bool indexIsInterpolated,
199 const ext::shared_ptr<Seasonality> &seasonality)
200 : InflationTermStructure(referenceDate, baseYoYRate, observationLag, frequency,
201 calendar, dayCounter, seasonality),
202 indexIsInterpolated_(indexIsInterpolated) {}
203
204 YoYInflationTermStructure::YoYInflationTermStructure(
205 Natural settlementDays,
206 const Calendar& calendar,
207 const DayCounter& dayCounter,
208 Rate baseYoYRate,
209 const Period& observationLag,
210 Frequency frequency,
211 bool indexIsInterpolated,
212 const ext::shared_ptr<Seasonality> &seasonality)
213 : InflationTermStructure(settlementDays, calendar, baseYoYRate, observationLag,
214 frequency, dayCounter, seasonality),
215 indexIsInterpolated_(indexIsInterpolated) {}
216
217
218 Rate YoYInflationTermStructure::yoyRate(const Date &d, const Period& instObsLag,
219 bool forceLinearInterpolation,
220 bool extrapolate) const {
221
222 Period useLag = instObsLag;
223 if (instObsLag == Period(-1,Days)) {
224 useLag = observationLag();
225 }
226
227 Rate yoyRate;
228 if (forceLinearInterpolation) {
229 std::pair<Date,Date> dd = inflationPeriod(d-useLag, frequency());
230 dd.second = dd.second + Period(1,Days);
231 Real dp = dd.second - dd.first;
232 Real dt = (d-useLag) - dd.first;
233 // if we are interpolating we only check the exact point
234 // this prevents falling off the end at curve maturity
235 InflationTermStructure::checkRange(d, extrapolate);
236 Time t1 = timeFromReference(d: dd.first);
237 Time t2 = timeFromReference(d: dd.second);
238 Rate y1 = yoyRateImpl(time: t1);
239 Rate y2 = yoyRateImpl(time: t2);
240 yoyRate = y1 + (y2-y1) * (dt/dp);
241 } else {
242 if (indexIsInterpolated()) {
243 InflationTermStructure::checkRange(d: d-useLag, extrapolate);
244 Time t = timeFromReference(d: d-useLag);
245 yoyRate = yoyRateImpl(time: t);
246 } else {
247 std::pair<Date,Date> dd = inflationPeriod(d-useLag, frequency());
248 InflationTermStructure::checkRange(d: dd.first, extrapolate);
249 Time t = timeFromReference(d: dd.first);
250 yoyRate = yoyRateImpl(time: t);
251 }
252 }
253
254 if (hasSeasonality()) {
255 yoyRate = seasonality()->correctYoYRate(d: d-useLag, r: yoyRate, iTS: *this);
256 }
257 return yoyRate;
258 }
259
260 Rate YoYInflationTermStructure::yoyRate(Time t,
261 bool extrapolate) const {
262 checkRange(t, extrapolate);
263 return yoyRateImpl(time: t);
264 }
265
266
267
268
269 std::pair<Date,Date> inflationPeriod(const Date& d,
270 Frequency frequency) {
271
272 Month month = d.month();
273 Year year = d.year();
274
275 Month startMonth, endMonth;
276 switch (frequency) {
277 case Annual:
278 startMonth = January;
279 endMonth = December;
280 break;
281 case Semiannual:
282 if (month <= June) {
283 startMonth = January;
284 endMonth = June;
285 } else {
286 startMonth = July;
287 endMonth = December;
288 }
289 break;
290 case Quarterly:
291 if (month <= March) {
292 startMonth = January;
293 endMonth = March;
294 } else if (month <= June) {
295 startMonth = April;
296 endMonth = June;
297 } else if (month <= September) {
298 startMonth = July;
299 endMonth = September;
300 } else {
301 startMonth = October;
302 endMonth = December;
303 }
304 break;
305 case Monthly:
306 startMonth = endMonth = month;
307 break;
308 default:
309 QL_FAIL("Frequency not handled: " << frequency);
310 break;
311 };
312
313 Date startDate = Date(1, startMonth, year);
314 Date endDate = Date::endOfMonth(d: Date(1, endMonth, year));
315
316 return std::make_pair(x&: startDate,y&: endDate);
317 }
318
319
320 Time inflationYearFraction(Frequency f, bool indexIsInterpolated,
321 const DayCounter &dayCounter,
322 const Date &d1, const Date &d2) {
323
324 Time t=0;
325 if (indexIsInterpolated) {
326 // N.B. we do not use linear interpolation between flat
327 // fixing forecasts for forecasts. This avoids awkwardnesses
328 // when bootstrapping the inflation curve.
329 t = dayCounter.yearFraction(d1, d2);
330 } else {
331 // I.e. fixing is constant for the whole inflation period.
332 // Use the value for half way along the period.
333 // But the inflation time is the time between period starts
334 std::pair<Date,Date> limD1 = inflationPeriod(d: d1, frequency: f);
335 std::pair<Date,Date> limD2 = inflationPeriod(d: d2, frequency: f);
336 t = dayCounter.yearFraction(d1: limD1.first, d2: limD2.first);
337 }
338
339 return t;
340 }
341
342
343}
344

source code of quantlib/ql/termstructures/inflationtermstructure.cpp

Morty Proxy This is a proxified and sanitized view of the page, visit original site.