1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 StatPro Italia srl
5  Copyright (C) 2009 Ferdinando Ametrano
6  Copyright (C) 2019 SoftSolutions! S.r.l.
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 interpolatedsimplezerocurve.hpp
23     \brief interpolated simply-compounded zero-rates structure
24 */
25 
26 #ifndef quantlib_zero_curve_simple_hpp
27 #define quantlib_zero_curve_simple_hpp
28 
29 #include <ql/math/comparison.hpp>
30 #include <ql/math/interpolations/linearinterpolation.hpp>
31 #include <ql/termstructures/interpolatedcurve.hpp>
32 #include <ql/termstructures/yieldtermstructure.hpp>
33 #include <ql/utilities/dataformatters.hpp>
34 #include <utility>
35 
36 namespace QuantLib {
37 
38 //! YieldTermStructure based on interpolation of zero rates
39 /*! \ingroup yieldtermstructures */
40 template <class Interpolator>
41 class InterpolatedSimpleZeroCurve : public YieldTermStructure, protected InterpolatedCurve<Interpolator> {
42   public:
43     // constructor
44     InterpolatedSimpleZeroCurve(const std::vector<Date> &dates, const std::vector<Rate> &yields,
45                                 const DayCounter &dayCounter, const Calendar &calendar = Calendar(),
46                                 const std::vector<Handle<Quote> > &jumps = std::vector<Handle<Quote> >(),
47                                 const std::vector<Date> &jumpDates = std::vector<Date>(),
48                                 const Interpolator &interpolator = Interpolator());
49     InterpolatedSimpleZeroCurve(const std::vector<Date> &dates, const std::vector<Rate> &yields,
50                                 const DayCounter &dayCounter, const Calendar &calendar,
51                                 const Interpolator &interpolator);
52     InterpolatedSimpleZeroCurve(const std::vector<Date> &dates, const std::vector<Rate> &yields,
53                                 const DayCounter &dayCounter, const Interpolator &interpolator);
54     //! \name TermStructure interface
55     //@{
56     Date maxDate() const;
57     //@}
58     //! \name other inspectors
59     //@{
60     const std::vector<Time> &times() const;
61     const std::vector<Date> &dates() const;
62     const std::vector<Real> &data() const;
63     const std::vector<Rate> &zeroRates() const;
64     std::vector<std::pair<Date, Real> > nodes() const;
65     //@}
66   protected:
67     explicit InterpolatedSimpleZeroCurve(const DayCounter &,
68                                          const Interpolator &interpolator = Interpolator());
69     InterpolatedSimpleZeroCurve(const Date &referenceDate, const DayCounter &,
70                                 const std::vector<Handle<Quote> > &jumps = std::vector<Handle<Quote> >(),
71                                 const std::vector<Date> &jumpDates = std::vector<Date>(),
72                                 const Interpolator &interpolator = Interpolator());
73     InterpolatedSimpleZeroCurve(Natural settlementDays, const Calendar &, const DayCounter &,
74                                 const std::vector<Handle<Quote> > &jumps = std::vector<Handle<Quote> >(),
75                                 const std::vector<Date> &jumpDates = std::vector<Date>(),
76                                 const Interpolator &interpolator = Interpolator());
77 
78     /*! \deprecated Passing jumps without a reference date never worked correctly.
79                     Use one of the other constructors instead.
80                     Deprecated in version 1.19.
81     */
82     QL_DEPRECATED
83     explicit InterpolatedSimpleZeroCurve(const DayCounter &,
84                                          const std::vector<Handle<Quote> > &jumps,
85                                          const std::vector<Date> &jumpDates = std::vector<Date>(),
86                                          const Interpolator &interpolator = Interpolator());
87     //! \name YieldTermStructure implementation
88     //@{
89     DiscountFactor discountImpl(Time t) const;
90     //@}
91     mutable std::vector<Date> dates_;
92 
93   private:
94     void initialize();
95 };
96 
97 
98 // inline definitions
99 
maxDate() const100 template <class T> inline Date InterpolatedSimpleZeroCurve<T>::maxDate() const { return dates_.back(); }
101 
times() const102 template <class T> inline const std::vector<Time> &InterpolatedSimpleZeroCurve<T>::times() const {
103     return this->times_;
104 }
105 
dates() const106 template <class T> inline const std::vector<Date> &InterpolatedSimpleZeroCurve<T>::dates() const { return dates_; }
107 
data() const108 template <class T> inline const std::vector<Real> &InterpolatedSimpleZeroCurve<T>::data() const { return this->data_; }
109 
zeroRates() const110 template <class T> inline const std::vector<Rate> &InterpolatedSimpleZeroCurve<T>::zeroRates() const {
111     return this->data_;
112 }
113 
nodes() const114 template <class T> inline std::vector<std::pair<Date, Real> > InterpolatedSimpleZeroCurve<T>::nodes() const {
115     std::vector<std::pair<Date, Real> > results(dates_.size());
116     for (Size i = 0; i < dates_.size(); ++i)
117         results[i] = std::make_pair(dates_[i], this->data_[i]);
118     return results;
119 }
120 
121 #ifndef __DOXYGEN__
122 
123 // template definitions
124 
discountImpl(Time t) const125 template <class T> DiscountFactor InterpolatedSimpleZeroCurve<T>::discountImpl(Time t) const {
126     Rate R;
127     if (t <= this->times_.back()) {
128         R = this->interpolation_(t, true);
129     } else {
130         // flat fwd extrapolation after last pillar,
131         // Notice that bbg uses flat extrapolation of non-annualized zero instead
132         Time tMax = this->times_.back();
133         Rate zMax = this->data_.back();
134         Rate instFwdMax = zMax + tMax * this->interpolation_.derivative(tMax);
135         R = (zMax * tMax + instFwdMax * (t - tMax)) / t;
136     }
137 
138 	return DiscountFactor(1.0 / (1.0 + R * t));
139 }
140 
141 template <class T>
InterpolatedSimpleZeroCurve(const DayCounter & dayCounter,const T & interpolator)142 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(const DayCounter &dayCounter, const T &interpolator)
143     : YieldTermStructure(dayCounter), InterpolatedCurve<T>(interpolator) {}
144 
145 template <class T>
InterpolatedSimpleZeroCurve(const Date & referenceDate,const DayCounter & dayCounter,const std::vector<Handle<Quote>> & jumps,const std::vector<Date> & jumpDates,const T & interpolator)146 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(const Date &referenceDate, const DayCounter &dayCounter,
147                                                             const std::vector<Handle<Quote> > &jumps,
148                                                             const std::vector<Date> &jumpDates, const T &interpolator)
149     : YieldTermStructure(referenceDate, Calendar(), dayCounter, jumps, jumpDates), InterpolatedCurve<T>(interpolator) {}
150 
151 template <class T>
InterpolatedSimpleZeroCurve(Natural settlementDays,const Calendar & calendar,const DayCounter & dayCounter,const std::vector<Handle<Quote>> & jumps,const std::vector<Date> & jumpDates,const T & interpolator)152 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(Natural settlementDays, const Calendar &calendar,
153                                                             const DayCounter &dayCounter,
154                                                             const std::vector<Handle<Quote> > &jumps,
155                                                             const std::vector<Date> &jumpDates, const T &interpolator)
156     : YieldTermStructure(settlementDays, calendar, dayCounter, jumps, jumpDates), InterpolatedCurve<T>(interpolator) {}
157 
158 #if defined(__GNUC__)
159 #pragma GCC diagnostic push
160 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
161 #endif
162 #if defined(__clang__)
163 #pragma clang diagnostic push
164 #pragma clang diagnostic ignored "-Wdeprecated-declarations"
165 #endif
166 #if defined(QL_PATCH_MSVC)
167 #pragma warning(push)
168 #pragma warning(disable:4996)
169 #endif
170 
171 template <class T>
InterpolatedSimpleZeroCurve(const DayCounter & dayCounter,const std::vector<Handle<Quote>> & jumps,const std::vector<Date> & jumpDates,const T & interpolator)172 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(const DayCounter &dayCounter,
173                                                             const std::vector<Handle<Quote> > &jumps,
174                                                             const std::vector<Date> &jumpDates,
175                                                             const T &interpolator)
176     : YieldTermStructure(dayCounter, jumps, jumpDates), InterpolatedCurve<T>(interpolator) {}
177 
178 #if defined(QL_PATCH_MSVC)
179 #pragma warning(pop)
180 #endif
181 #if defined(__clang__)
182 #pragma clang diagnostic pop
183 #endif
184 #if defined(__GNUC__)
185 #pragma GCC diagnostic pop
186 #endif
187 
188 template <class T>
InterpolatedSimpleZeroCurve(const std::vector<Date> & dates,const std::vector<Rate> & yields,const DayCounter & dayCounter,const Calendar & calendar,const std::vector<Handle<Quote>> & jumps,const std::vector<Date> & jumpDates,const T & interpolator)189 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(const std::vector<Date> &dates,
190                                                             const std::vector<Rate> &yields,
191                                                             const DayCounter &dayCounter, const Calendar &calendar,
192                                                             const std::vector<Handle<Quote> > &jumps,
193                                                             const std::vector<Date> &jumpDates, const T &interpolator)
194     : YieldTermStructure(dates.at(0), calendar, dayCounter, jumps, jumpDates),
195       InterpolatedCurve<T>(std::vector<Time>(), yields, interpolator), dates_(dates) {
196     initialize();
197 }
198 
199 template <class T>
InterpolatedSimpleZeroCurve(const std::vector<Date> & dates,const std::vector<Rate> & yields,const DayCounter & dayCounter,const Calendar & calendar,const T & interpolator)200 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(const std::vector<Date> &dates,
201                                                             const std::vector<Rate> &yields,
202                                                             const DayCounter &dayCounter, const Calendar &calendar,
203                                                             const T &interpolator)
204     : YieldTermStructure(dates.at(0), calendar, dayCounter), InterpolatedCurve<T>(std::vector<Time>(), yields,
205                                                                                   interpolator),
206       dates_(dates) {
207     initialize();
208 }
209 
210 template <class T>
InterpolatedSimpleZeroCurve(const std::vector<Date> & dates,const std::vector<Rate> & yields,const DayCounter & dayCounter,const T & interpolator)211 InterpolatedSimpleZeroCurve<T>::InterpolatedSimpleZeroCurve(const std::vector<Date> &dates,
212                                                             const std::vector<Rate> &yields,
213                                                             const DayCounter &dayCounter, const T &interpolator)
214     : YieldTermStructure(dates.at(0), Calendar(), dayCounter), InterpolatedCurve<T>(std::vector<Time>(), yields,
215                                                                                     interpolator),
216       dates_(dates) {
217     initialize();
218 }
219 
220 #endif
221 
initialize()222 template <class T> void InterpolatedSimpleZeroCurve<T>::initialize() {
223     QL_REQUIRE(dates_.size() >= T::requiredPoints, "not enough input dates given");
224     QL_REQUIRE(this->data_.size() == dates_.size(), "dates/data count mismatch");
225 
226     this->times_.resize(dates_.size());
227     this->times_[0] = 0.0;
228     for (Size i = 1; i < dates_.size(); ++i) {
229         QL_REQUIRE(dates_[i] > dates_[i - 1], "invalid date (" << dates_[i] << ", vs " << dates_[i - 1] << ")");
230         this->times_[i] = dayCounter().yearFraction(dates_[0], dates_[i]);
231         QL_REQUIRE(!close(this->times_[i], this->times_[i - 1]), "two dates correspond to the same time "
232                                                                  "under this curve's day count convention");
233     }
234 
235     this->interpolation_ =
236         this->interpolator_.interpolate(this->times_.begin(), this->times_.end(), this->data_.begin());
237     this->interpolation_.update();
238 }
239 
240 } // namespace QuantLib
241 
242 #endif
243