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) 2007, 2008 StatPro Italia srl
6  Copyright (C) 2011 Ferdinando Ametrano
7 
8  This file is part of QuantLib, a free-software/open-source library
9  for financial quantitative analysts and developers - http://quantlib.org/
10 
11  QuantLib is free software: you can redistribute it and/or modify it
12  under the terms of the QuantLib license.  You should have received a
13  copy of the license along with this program; if not, please email
14  <quantlib-dev@lists.sf.net>. The license is also available online at
15  <http://quantlib.org/license.shtml>.
16 
17  This program is distributed in the hope that it will be useful, but WITHOUT
18  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19  FOR A PARTICULAR PURPOSE.  See the license for more details.
20 */
21 
22 /*! \file inflationtraits.hpp
23     \brief inflation bootstrap traits
24 */
25 
26 #ifndef ql_inflation_bootstrap_traits_hpp
27 #define ql_inflation_bootstrap_traits_hpp
28 
29 #include <ql/termstructures/inflation/interpolatedzeroinflationcurve.hpp>
30 #include <ql/termstructures/inflation/interpolatedyoyinflationcurve.hpp>
31 #include <ql/termstructures/bootstraphelper.hpp>
32 
33 namespace QuantLib {
34 
35     namespace detail {
36         const Rate avgInflation = 0.02;
37         const Rate maxInflation = 0.5;
38     }
39 
40     //! Bootstrap traits to use for PiecewiseZeroInflationCurve
41     class ZeroInflationTraits {
42       public:
43         typedef BootstrapHelper<ZeroInflationTermStructure> helper;
44 
45         // start of curve data
initialDate(const ZeroInflationTermStructure * t)46         static Date initialDate(const ZeroInflationTermStructure* t) {
47             if (t->indexIsInterpolated()) {
48                 return t->referenceDate() - t->observationLag();
49             } else {
50                 return inflationPeriod(t->referenceDate() - t->observationLag(),
51                                        t->frequency()).first;
52             }
53         }
54         // value at reference date
initialValue(const ZeroInflationTermStructure * t)55         static Rate initialValue(const ZeroInflationTermStructure* t) {
56             return t->baseRate();
57         }
58 
59         // guesses
60         template <class C>
guess(Size i,const C * c,bool validData,Size)61         static Rate guess(Size i,
62                           const C* c,
63                           bool validData,
64                           Size) // firstAliveHelper
65         {
66             if (validData) // previous iteration value
67                 return c->data()[i];
68 
69             if (i==1) // first pillar
70                 return detail::avgInflation;
71 
72             // could/should extrapolate
73             return detail::avgInflation;
74         }
75 
76         // constraints
77         template <class C>
minValueAfter(Size i,const C * c,bool validData,Size)78         static Rate minValueAfter(Size i,
79                                   const C* c,
80                                   bool validData,
81                                   Size) // firstAliveHelper
82         {
83             if (validData) {
84                 Rate r = *(std::min_element(c->data().begin(), c->data().end()));
85                 return r<0.0 ? r*2.0 : r/2.0;
86             }
87             return -detail::maxInflation;
88         }
89         template <class C>
maxValueAfter(Size i,const C * c,bool validData,Size)90         static Rate maxValueAfter(Size i,
91                                   const C* c,
92                                   bool validData,
93                                   Size) // firstAliveHelper
94         {
95             if (validData) {
96                 Rate r = *(std::max_element(c->data().begin(), c->data().end()));
97                 return r<0.0 ? r/2.0 : r*2.0;
98             }
99             // no constraints.
100             // We choose as max a value very unlikely to be exceeded.
101             return detail::maxInflation;
102         }
103 
104         // update with new guess
updateGuess(std::vector<Rate> & data,Rate level,Size i)105         static void updateGuess(std::vector<Rate>& data,
106                                 Rate level,
107                                 Size i) {
108             data[i] = level;
109         }
110         // upper bound for convergence loop
111         // calibration is trivial, should be immediate
maxIterations()112         static Size maxIterations() { return 5; }
113     };
114 
115     //! Bootstrap traits to use for PiecewiseZeroInflationCurve
116     class YoYInflationTraits {
117       public:
118         // helper class
119         typedef BootstrapHelper<YoYInflationTermStructure> helper;
120 
121         // start of curve data
initialDate(const YoYInflationTermStructure * t)122         static Date initialDate(const YoYInflationTermStructure* t) {
123             if (t->indexIsInterpolated()) {
124                 return t->referenceDate() - t->observationLag();
125             } else {
126                 return inflationPeriod(t->referenceDate() - t->observationLag(),
127                                        t->frequency()).first;
128             }
129         }
130         // value at reference date
initialValue(const YoYInflationTermStructure * t)131         static Rate initialValue(const YoYInflationTermStructure* t) {
132             return t->baseRate();
133         }
134 
135         // guesses
136         template <class C>
guess(Size i,const C * c,bool validData,Size)137         static Rate guess(Size i,
138                           const C* c,
139                           bool validData,
140                           Size) // firstAliveHelper
141         {
142             if (validData) // previous iteration value
143                 return c->data()[i];
144 
145             if (i==1) // first pillar
146                 return detail::avgInflation;
147 
148             // could/should extrapolate
149             return detail::avgInflation;
150         }
151 
152         // constraints
153         template <class C>
minValueAfter(Size i,const C * c,bool validData,Size)154         static Rate minValueAfter(Size i,
155                                   const C* c,
156                                   bool validData,
157                                   Size) // firstAliveHelper
158         {
159             if (validData) {
160                 Rate r = *(std::min_element(c->data().begin(), c->data().end()));
161                 return r<0.0 ? r*2.0 : r/2.0;
162             }
163             return -detail::maxInflation;
164         }
165         template <class C>
maxValueAfter(Size i,const C * c,bool validData,Size)166         static Rate maxValueAfter(Size i,
167                                   const C* c,
168                                   bool validData,
169                                   Size) // firstAliveHelper
170         {
171             if (validData) {
172                 Rate r = *(std::max_element(c->data().begin(), c->data().end()));
173                 return r<0.0 ? r/2.0 : r*2.0;
174             }
175             // no constraints.
176             // We choose as max a value very unlikely to be exceeded.
177             return detail::maxInflation;
178         }
179 
180         // update with new guess
updateGuess(std::vector<Rate> & data,Rate level,Size i)181         static void updateGuess(std::vector<Rate>& data,
182                                 Rate level,
183                                 Size i) {
184             data[i] = level;
185         }
186         // upper bound for convergence loop
maxIterations()187         static Size maxIterations() { return 40; }
188     };
189 
190 }
191 
192 #endif
193