Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/termstructures/yield/discountcurve.hpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2002, 2003 Decillion Pty(Ltd)
5
 Copyright (C) 2005, 2006, 2008, 2009 StatPro Italia srl
6
 Copyright (C) 2009, 2015 Ferdinando Ametrano
7
 Copyright (C) 2015 Paolo Mazzocchi
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 discountcurve.hpp
24
    \brief interpolated discount factor structure
25
*/
26
27
#ifndef quantlib_discount_curve_hpp
28
#define quantlib_discount_curve_hpp
29
30
#include <ql/termstructures/yieldtermstructure.hpp>
31
#include <ql/termstructures/interpolatedcurve.hpp>
32
#include <ql/math/interpolations/loginterpolation.hpp>
33
#include <utility>
34
35
namespace QuantLib {
36
37
    //! YieldTermStructure based on interpolation of discount factors
38
    /*! \ingroup yieldtermstructures */
39
    template <class Interpolator>
40
    class InterpolatedDiscountCurve
41
        : public YieldTermStructure,
42
          protected InterpolatedCurve<Interpolator> {
43
      public:
44
        InterpolatedDiscountCurve(
45
            const std::vector<Date>& dates,
46
            const std::vector<DiscountFactor>& dfs,
47
            const DayCounter& dayCounter,
48
            const Calendar& cal = Calendar(),
49
            const std::vector<Handle<Quote> >& jumps = {},
50
            const std::vector<Date>& jumpDates = {},
51
            const Interpolator& interpolator = {});
52
        InterpolatedDiscountCurve(
53
            const std::vector<Date>& dates,
54
            const std::vector<DiscountFactor>& dfs,
55
            const DayCounter& dayCounter,
56
            const Calendar& calendar,
57
            const Interpolator& interpolator);
58
        InterpolatedDiscountCurve(
59
            const std::vector<Date>& dates,
60
            const std::vector<DiscountFactor>& dfs,
61
            const DayCounter& dayCounter,
62
            const Interpolator& interpolator);
63
        //! \name TermStructure interface
64
        //@{
65
        Date maxDate() const override;
66
        //@}
67
        //! \name other inspectors
68
        //@{
69
        const std::vector<Time>& times() const;
70
        const std::vector<Date>& dates() const;
71
        const std::vector<Real>& data() const;
72
        const std::vector<DiscountFactor>& discounts() const;
73
        std::vector<std::pair<Date, Real> > nodes() const;
74
        //@}
75
76
      protected:
77
        explicit InterpolatedDiscountCurve(
78
            const DayCounter&,
79
            const Interpolator& interpolator = {});
80
        InterpolatedDiscountCurve(
81
            const Date& referenceDate,
82
            const DayCounter&,
83
            const std::vector<Handle<Quote> >& jumps = {},
84
            const std::vector<Date>& jumpDates = {},
85
            const Interpolator& interpolator = {});
86
        InterpolatedDiscountCurve(
87
            Natural settlementDays,
88
            const Calendar&,
89
            const DayCounter&,
90
            const std::vector<Handle<Quote> >& jumps = {},
91
            const std::vector<Date>& jumpDates = {},
92
            const Interpolator& interpolator = {});
93
94
        //! \name YieldTermStructure implementation
95
        //@{
96
        DiscountFactor discountImpl(Time) const override;
97
        //@}
98
        mutable std::vector<Date> dates_;
99
      private:
100
        void initialize();
101
    };
102
103
    //! Term structure based on log-linear interpolation of discount factors
104
    /*! Log-linear interpolation guarantees piecewise-constant forward
105
        rates.
106
107
        \ingroup yieldtermstructures
108
    */
109
    typedef InterpolatedDiscountCurve<LogLinear> DiscountCurve;
110
111
112
    // inline definitions
113
114
    template <class T>
115
    inline Date InterpolatedDiscountCurve<T>::maxDate() const {
116
        if (this->maxDate_ != Date())
117
            return this->maxDate_;
118
        return dates_.back();
119
    }
120
121
    template <class T>
122
    inline const std::vector<Time>&
123
    InterpolatedDiscountCurve<T>::times() const {
124
        return this->times_;
125
    }
126
127
    template <class T>
128
    inline const std::vector<Date>&
129
0
    InterpolatedDiscountCurve<T>::dates() const {
130
0
        return dates_;
131
0
    }
132
133
    template <class T>
134
    inline const std::vector<Real>&
135
    InterpolatedDiscountCurve<T>::data() const {
136
        return this->data_;
137
    }
138
139
    template <class T>
140
    inline const std::vector<DiscountFactor>&
141
    InterpolatedDiscountCurve<T>::discounts() const {
142
        return this->data_;
143
    }
144
145
    template <class T>
146
    inline std::vector<std::pair<Date, Real> >
147
    InterpolatedDiscountCurve<T>::nodes() const {
148
        std::vector<std::pair<Date, Real> > results(dates_.size());
149
        for (Size i=0; i<dates_.size(); ++i)
150
            results[i] = std::make_pair(dates_[i], this->data_[i]);
151
        return results;
152
    }
153
154
    #ifndef __DOXYGEN__
155
156
    // template definitions
157
    
158
    template <class T>
159
    DiscountFactor InterpolatedDiscountCurve<T>::discountImpl(Time t) const {
160
        if (t <= this->times_.back())
161
            return this->interpolation_(t, true);
162
163
        // flat fwd extrapolation
164
        Time tMax = this->times_.back();
165
        DiscountFactor dMax = this->data_.back();
166
        Rate instFwdMax = - this->interpolation_.derivative(tMax) / dMax;
167
        return dMax * std::exp(- instFwdMax * (t-tMax));
168
    }
169
170
    template <class T>
171
    InterpolatedDiscountCurve<T>::InterpolatedDiscountCurve(
172
                                    const DayCounter& dayCounter,
173
                                    const T& interpolator)
174
    : YieldTermStructure(dayCounter),
175
      InterpolatedCurve<T>(interpolator) {}
176
177
    template <class T>
178
    InterpolatedDiscountCurve<T>::InterpolatedDiscountCurve(
179
                                    const Date& referenceDate,
180
                                    const DayCounter& dayCounter,
181
                                    const std::vector<Handle<Quote> >& jumps,
182
                                    const std::vector<Date>& jumpDates,
183
                                    const T& interpolator)
184
    : YieldTermStructure(referenceDate, Calendar(), dayCounter, jumps, jumpDates),
185
      InterpolatedCurve<T>(interpolator) {}
186
187
    template <class T>
188
    InterpolatedDiscountCurve<T>::InterpolatedDiscountCurve(
189
                                    Natural settlementDays,
190
                                    const Calendar& calendar,
191
                                    const DayCounter& dayCounter,
192
                                    const std::vector<Handle<Quote> >& jumps,
193
                                    const std::vector<Date>& jumpDates,
194
                                    const T& interpolator)
195
    : YieldTermStructure(settlementDays, calendar, dayCounter, jumps, jumpDates),
196
      InterpolatedCurve<T>(interpolator) {}
197
198
    template <class T>
199
    InterpolatedDiscountCurve<T>::InterpolatedDiscountCurve(
200
                                 const std::vector<Date>& dates,
201
                                 const std::vector<DiscountFactor>& discounts,
202
                                 const DayCounter& dayCounter,
203
                                 const Calendar& calendar,
204
                                 const std::vector<Handle<Quote> >& jumps,
205
                                 const std::vector<Date>& jumpDates,
206
                                 const T& interpolator)
207
    : YieldTermStructure(dates.at(0), calendar, dayCounter, jumps, jumpDates),
208
      InterpolatedCurve<T>(std::vector<Time>(), discounts, interpolator),
209
      dates_(dates)
210
    {
211
        initialize();
212
    }
213
214
    template <class T>
215
    InterpolatedDiscountCurve<T>::InterpolatedDiscountCurve(
216
                                 const std::vector<Date>& dates,
217
                                 const std::vector<DiscountFactor>& discounts,
218
                                 const DayCounter& dayCounter,
219
                                 const Calendar& calendar,
220
                                 const T& interpolator)
221
    : YieldTermStructure(dates.at(0), calendar, dayCounter),
222
      InterpolatedCurve<T>(std::vector<Time>(), discounts, interpolator),
223
      dates_(dates)
224
    {
225
        initialize();
226
    }
227
228
    template <class T>
229
    InterpolatedDiscountCurve<T>::InterpolatedDiscountCurve(
230
                                 const std::vector<Date>& dates,
231
                                 const std::vector<DiscountFactor>& discounts,
232
                                 const DayCounter& dayCounter,
233
                                 const T& interpolator)
234
    : YieldTermStructure(dates.at(0), Calendar(), dayCounter),
235
      InterpolatedCurve<T>(std::vector<Time>(), discounts, interpolator),
236
      dates_(dates)
237
    {
238
        initialize();
239
    }
240
241
    #endif
242
243
    template <class T>
244
    void InterpolatedDiscountCurve<T>::initialize()
245
    {
246
        QL_REQUIRE(dates_.size() >= T::requiredPoints,
247
                   "not enough input dates given");
248
        QL_REQUIRE(this->data_.size() == dates_.size(),
249
                   "dates/data count mismatch");
250
        QL_REQUIRE(this->data_[0] == 1.0,
251
                   "the first discount must be == 1.0 "
252
                   "to flag the corresponding date as reference date");
253
        for (Size i=1; i<dates_.size(); ++i) {
254
            QL_REQUIRE(this->data_[i] > 0.0, "negative discount");
255
        }
256
257
        this->setupTimes(dates_, dates_[0], dayCounter());
258
        this->setupInterpolation();
259
        this->interpolation_.update();
260
    }
261
262
}
263
264
#endif