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> ×() 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