1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2005, 2007 StatPro Italia srl
5 Copyright (C) 2011 Ferdinando Ametrano
6 Copyright (C) 2007 Chris Kenyon
7 Copyright (C) 2019 SoftSolutions! S.r.l.
8
9 This file is part of QuantLib, a free-software/open-source library
10 for financial quantitative analysts and developers - http://quantlib.org/
11
12 QuantLib is free software: you can redistribute it and/or modify it
13 under the terms of the QuantLib license. You should have received a
14 copy of the license along with this program; if not, please email
15 <quantlib-dev@lists.sf.net>. The license is also available online at
16 <http://quantlib.org/license.shtml>.
17
18 This program is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20 FOR A PARTICULAR PURPOSE. See the license for more details.
21*/
22
23/*! \file bootstraptraits.hpp
24 \brief bootstrap traits
25*/
26
27#ifndef ql_bootstrap_traits_hpp
28#define ql_bootstrap_traits_hpp
29
30#include <ql/termstructures/yield/discountcurve.hpp>
31#include <ql/termstructures/yield/zerocurve.hpp>
32#include <ql/termstructures/yield/interpolatedsimplezerocurve.hpp>
33#include <ql/termstructures/yield/forwardcurve.hpp>
34#include <ql/termstructures/bootstraphelper.hpp>
35
36namespace QuantLib {
37
38 namespace detail {
39 const Real avgRate = 0.05;
40 const Real maxRate = 1.0;
41 }
42
43 //! Discount-curve traits
44 struct Discount {
45 // interpolated curve type
46 template <class Interpolator>
47 struct curve {
48 typedef InterpolatedDiscountCurve<Interpolator> type;
49 };
50 // helper class
51 typedef BootstrapHelper<YieldTermStructure> helper;
52
53 // start of curve data
54 static Date initialDate(const YieldTermStructure* c) {
55 return c->referenceDate();
56 }
57 // value at reference date
58 static Real initialValue(const YieldTermStructure*) {
59 return 1.0;
60 }
61
62 // guesses
63 template <class C>
64 static Real guess(Size i,
65 const C* c,
66 bool validData,
67 Size) // firstAliveHelper
68 {
69 if (validData) // previous iteration value
70 return c->data()[i];
71
72 if (i==1) // first pillar
73 return 1.0/(1.0+detail::avgRate*c->times()[1]);
74
75 // flat rate extrapolation
76 Real r = -std::log(c->data()[i-1])/c->times()[i-1];
77 return std::exp(-r * c->times()[i]);
78 }
79
80 // possible constraints based on previous values
81 template <class C>
82 static Real minValueAfter(Size i,
83 const C* c,
84 bool validData,
85 Size) // firstAliveHelper
86 {
87 if (validData) {
88 return *(std::min_element(c->data().begin(),
89 c->data().end()))/2.0;
90 }
91 Time dt = c->times()[i] - c->times()[i-1];
92 return c->data()[i-1] * std::exp(x: - detail::maxRate * dt);
93 }
94 template <class C>
95 static Real maxValueAfter(Size i,
96 const C* c,
97 bool validData,
98 Size) // firstAliveHelper
99 {
100 Time dt = c->times()[i] - c->times()[i-1];
101 return c->data()[i-1] * std::exp(x: detail::maxRate * dt);
102 }
103
104 // root-finding update
105 static void updateGuess(std::vector<Real>& data,
106 Real discount,
107 Size i) {
108 data[i] = discount;
109 }
110 // upper bound for convergence loop
111 static Size maxIterations() { return 100; }
112 };
113
114
115 //! Zero-curve traits
116 struct ZeroYield {
117 // interpolated curve type
118 template <class Interpolator>
119 struct curve {
120 typedef InterpolatedZeroCurve<Interpolator> type;
121 };
122 // helper class
123 typedef BootstrapHelper<YieldTermStructure> helper;
124
125 // start of curve data
126 static Date initialDate(const YieldTermStructure* c) {
127 return c->referenceDate();
128 }
129 // dummy value at reference date
130 static Real initialValue(const YieldTermStructure*) {
131 return detail::avgRate;
132 }
133
134 // guesses
135 template <class C>
136 static Real guess(Size i,
137 const C* c,
138 bool validData,
139 Size) // firstAliveHelper
140 {
141 if (validData) // previous iteration value
142 return c->data()[i];
143
144 if (i==1) // first pillar
145 return detail::avgRate;
146
147 // extrapolate
148 Date d = c->dates()[i];
149 return c->zeroRate(d, c->dayCounter(),
150 Continuous, Annual, true);
151 }
152
153 // possible constraints based on previous values
154 template <class C>
155 static Real minValueAfter(Size,
156 const C* c,
157 bool validData,
158 Size) // firstAliveHelper
159 {
160 if (validData) {
161 Real r = *(std::min_element(c->data().begin(), c->data().end()));
162 return r<0.0 ? Real(r*2.0) : Real(r/2.0);
163 }
164 // no constraints.
165 // We choose as min a value very unlikely to be exceeded.
166 return -detail::maxRate;
167 }
168 template <class C>
169 static Real maxValueAfter(Size,
170 const C* c,
171 bool validData,
172 Size) // firstAliveHelper
173 {
174 if (validData) {
175 Real r = *(std::max_element(c->data().begin(), c->data().end()));
176 return r<0.0 ? Real(r/2.0) : Real(r*2.0);
177 }
178 // no constraints.
179 // We choose as max a value very unlikely to be exceeded.
180 return detail::maxRate;
181 }
182
183 // root-finding update
184 static void updateGuess(std::vector<Real>& data,
185 Real rate,
186 Size i) {
187 data[i] = rate;
188 if (i==1)
189 data[0] = rate; // first point is updated as well
190 }
191 // upper bound for convergence loop
192 static Size maxIterations() { return 100; }
193 };
194
195
196 //! Forward-curve traits
197 struct ForwardRate {
198 // interpolated curve type
199 template <class Interpolator>
200 struct curve {
201 typedef InterpolatedForwardCurve<Interpolator> type;
202 };
203 // helper class
204 typedef BootstrapHelper<YieldTermStructure> helper;
205
206 // start of curve data
207 static Date initialDate(const YieldTermStructure* c) {
208 return c->referenceDate();
209 }
210 // dummy value at reference date
211 static Real initialValue(const YieldTermStructure*) {
212 return detail::avgRate;
213 }
214
215 // guesses
216 template <class C>
217 static Real guess(Size i,
218 const C* c,
219 bool validData,
220 Size) // firstAliveHelper
221 {
222 if (validData) // previous iteration value
223 return c->data()[i];
224
225 if (i==1) // first pillar
226 return detail::avgRate;
227
228 // extrapolate
229 Date d = c->dates()[i];
230 return c->forwardRate(d, d, c->dayCounter(),
231 Continuous, Annual, true);
232 }
233
234 // possible constraints based on previous values
235 template <class C>
236 static Real minValueAfter(Size,
237 const C* c,
238 bool validData,
239 Size) // firstAliveHelper
240 {
241 if (validData) {
242 Real r = *(std::min_element(c->data().begin(), c->data().end()));
243 return r<0.0 ? Real(r*2.0) : Real(r/2.0);
244 }
245 // no constraints.
246 // We choose as min a value very unlikely to be exceeded.
247 return -detail::maxRate;
248 }
249 template <class C>
250 static Real maxValueAfter(Size,
251 const C* c,
252 bool validData,
253 Size) // firstAliveHelper
254 {
255 if (validData) {
256 Real r = *(std::max_element(c->data().begin(), c->data().end()));
257 return r<0.0 ? Real(r/2.0) : Real(r*2.0);
258 }
259 // no constraints.
260 // We choose as max a value very unlikely to be exceeded.
261 return detail::maxRate;
262 }
263
264 // root-finding update
265 static void updateGuess(std::vector<Real>& data,
266 Real forward,
267 Size i) {
268 data[i] = forward;
269 if (i==1)
270 data[0] = forward; // first point is updated as well
271 }
272 // upper bound for convergence loop
273 static Size maxIterations() { return 100; }
274 };
275
276 //! Simple Zero-curve traits
277 struct SimpleZeroYield {
278 // interpolated curve type
279 template <class Interpolator>
280 struct curve {
281 typedef InterpolatedSimpleZeroCurve<Interpolator> type;
282 };
283 // helper class
284 typedef BootstrapHelper<YieldTermStructure> helper;
285
286 // start of curve data
287 static Date initialDate(const YieldTermStructure* c) {
288 return c->referenceDate();
289 }
290 // dummy value at reference date
291 static Real initialValue(const YieldTermStructure*) {
292 return detail::avgRate;
293 }
294
295 // guesses
296 template <class C>
297 static Real guess(Size i,
298 const C* c,
299 bool validData,
300 Size) // firstAliveHelper
301 {
302 if (validData) // previous iteration value
303 return c->data()[i];
304
305 if (i==1) // first pillar
306 return detail::avgRate;
307
308 // extrapolate
309 Date d = c->dates()[i];
310 return c->zeroRate(d, c->dayCounter(),
311 Simple, Annual, true);
312 }
313
314 // possible constraints based on previous values
315 template <class C>
316 static Real minValueAfter(Size i,
317 const C* c,
318 bool validData,
319 Size) // firstAliveHelper
320 {
321 Real result;
322 if (validData) {
323 Real r = *(std::min_element(c->data().begin(), c->data().end()));
324 result = r<0.0 ? Real(r*2.0) : r/2.0;
325 } else {
326 // no constraints.
327 // We choose as min a value very unlikely to be exceeded.
328 result = -detail::maxRate;
329 }
330 Real t = c->timeFromReference(c->dates()[i]);
331 return std::max(a: result, b: -1.0 / t + 1E-8);
332 }
333 template <class C>
334 static Real maxValueAfter(Size,
335 const C* c,
336 bool validData,
337 Size) // firstAliveHelper
338 {
339 if (validData) {
340 Real r = *(std::max_element(c->data().begin(), c->data().end()));
341 return r<0.0 ? Real(r/2.0) : r*2.0;
342 }
343 // no constraints.
344 // We choose as max a value very unlikely to be exceeded.
345 return detail::maxRate;
346 }
347
348 // root-finding update
349 static void updateGuess(std::vector<Real>& data,
350 Real rate,
351 Size i) {
352 data[i] = rate;
353 if (i==1)
354 data[0] = rate; // first point is updated as well
355 }
356 // upper bound for convergence loop
357 static Size maxIterations() { return 100; }
358 };
359
360
361}
362
363#endif
364

source code of quantlib/ql/termstructures/yield/bootstraptraits.hpp