Coverage Report

Created: 2025-08-11 06:28

/src/quantlib/ql/termstructures/credit/interpolatedsurvivalprobabilitycurve.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) 2009 Ferdinando Ametrano
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <http://quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
/*! \file interpolatedsurvivalprobabilitycurve.hpp
21
    \brief interpolated survival-probability term structure
22
*/
23
24
#ifndef quantlib_interpolated_survival_probability_curve_hpp
25
#define quantlib_interpolated_survival_probability_curve_hpp
26
27
#include <ql/termstructures/credit/survivalprobabilitystructure.hpp>
28
#include <ql/termstructures/interpolatedcurve.hpp>
29
#include <utility>
30
31
namespace QuantLib {
32
33
    //! DefaultProbabilityTermStructure based on interpolation of survival probabilities
34
    /*! \ingroup defaultprobabilitytermstructures */
35
    template <class Interpolator>
36
    class InterpolatedSurvivalProbabilityCurve
37
        : public SurvivalProbabilityStructure,
38
          protected InterpolatedCurve<Interpolator> {
39
      public:
40
        InterpolatedSurvivalProbabilityCurve(
41
            const std::vector<Date>& dates,
42
            const std::vector<Probability>& probabilities,
43
            const DayCounter& dayCounter,
44
            const Calendar& calendar = Calendar(),
45
            const std::vector<Handle<Quote> >& jumps = {},
46
            const std::vector<Date>& jumpDates = {},
47
            const Interpolator& interpolator = {});
48
        InterpolatedSurvivalProbabilityCurve(
49
            const std::vector<Date>& dates,
50
            const std::vector<Probability>& probabilities,
51
            const DayCounter& dayCounter,
52
            const Calendar& calendar,
53
            const Interpolator& interpolator);
54
        InterpolatedSurvivalProbabilityCurve(
55
            const std::vector<Date>& dates,
56
            const std::vector<Probability>& probabilities,
57
            const DayCounter& dayCounter,
58
            const Interpolator& interpolator);
59
        //! \name TermStructure interface
60
        //@{
61
        Date maxDate() const override;
62
        //@}
63
        //! \name other inspectors
64
        //@{
65
        const std::vector<Time>& times() const;
66
        const std::vector<Date>& dates() const;
67
        const std::vector<Real>& data() const;
68
        const std::vector<Probability>& survivalProbabilities() const;
69
        std::vector<std::pair<Date, Real> > nodes() const;
70
        //@}
71
      protected:
72
        InterpolatedSurvivalProbabilityCurve(
73
            const DayCounter&,
74
            const std::vector<Handle<Quote> >& jumps = {},
75
            const std::vector<Date>& jumpDates = {},
76
            const Interpolator& interpolator = {});
77
        InterpolatedSurvivalProbabilityCurve(
78
            const Date& referenceDate,
79
            const DayCounter&,
80
            const std::vector<Handle<Quote> >& jumps = {},
81
            const std::vector<Date>& jumpDates = {},
82
            const Interpolator& interpolator = {});
83
        InterpolatedSurvivalProbabilityCurve(
84
            Natural settlementDays,
85
            const Calendar&,
86
            const DayCounter&,
87
            const std::vector<Handle<Quote> >& jumps = {},
88
            const std::vector<Date>& jumpDates = {},
89
            const Interpolator& interpolator = {});
90
        //! \name DefaultProbabilityTermStructure implementation
91
        //@{
92
        Probability survivalProbabilityImpl(Time) const override;
93
        Real defaultDensityImpl(Time) const override;
94
        //@}
95
        mutable std::vector<Date> dates_;
96
    private:
97
        void initialize();
98
    };
99
100
    // inline definitions
101
102
    template <class T>
103
    inline Date InterpolatedSurvivalProbabilityCurve<T>::maxDate() const {
104
        return dates_.back();
105
    }
106
107
    template <class T>
108
    inline const std::vector<Time>&
109
    InterpolatedSurvivalProbabilityCurve<T>::times() const {
110
        return this->times_;
111
    }
112
113
    template <class T>
114
    inline const std::vector<Date>&
115
0
    InterpolatedSurvivalProbabilityCurve<T>::dates() const {
116
0
        return dates_;
117
0
    }
118
119
    template <class T>
120
    inline const std::vector<Real>&
121
    InterpolatedSurvivalProbabilityCurve<T>::data() const {
122
        return this->data_;
123
    }
124
125
    template <class T>
126
    inline const std::vector<Probability>&
127
    InterpolatedSurvivalProbabilityCurve<T>::survivalProbabilities() const {
128
        return this->data_;
129
    }
130
131
    template <class T>
132
    inline std::vector<std::pair<Date,Real> >
133
    InterpolatedSurvivalProbabilityCurve<T>::nodes() const {
134
        std::vector<std::pair<Date,Real> > results(dates_.size());
135
        for (Size i=0; i<dates_.size(); ++i)
136
            results[i] = std::make_pair(dates_[i],this->data_[i]);
137
        return results;
138
    }
139
140
    #ifndef __DOXYGEN__
141
142
    // template definitions
143
144
    template <class T>
145
    Probability
146
    InterpolatedSurvivalProbabilityCurve<T>::survivalProbabilityImpl(Time t)
147
                                                                        const {
148
        if (t <= this->times_.back())
149
            return this->interpolation_(t, true);
150
151
        // flat hazard rate extrapolation
152
        Time tMax = this->times_.back();
153
        Probability sMax = this->data_.back();
154
        Rate hazardMax = - this->interpolation_.derivative(tMax) / sMax;
155
        return sMax * std::exp(- hazardMax * (t-tMax));
156
    }
157
158
    template <class T>
159
    Real
160
    InterpolatedSurvivalProbabilityCurve<T>::defaultDensityImpl(Time t) const {
161
        if (t <= this->times_.back())
162
            return -this->interpolation_.derivative(t, true);
163
164
        // flat hazard rate extrapolation
165
        Time tMax = this->times_.back();
166
        Probability sMax = this->data_.back();
167
        Rate hazardMax = - this->interpolation_.derivative(tMax) / sMax;
168
        return sMax * hazardMax * std::exp(- hazardMax * (t-tMax));
169
    }
170
171
    template <class T>
172
    InterpolatedSurvivalProbabilityCurve<T>::InterpolatedSurvivalProbabilityCurve(
173
                                    const DayCounter& dayCounter,
174
                                    const std::vector<Handle<Quote> >& jumps,
175
                                    const std::vector<Date>& jumpDates,
176
                                    const T& interpolator)
177
    : SurvivalProbabilityStructure(dayCounter, jumps, jumpDates),
178
      InterpolatedCurve<T>(interpolator) {}
179
180
    template <class T>
181
    InterpolatedSurvivalProbabilityCurve<T>::InterpolatedSurvivalProbabilityCurve(
182
                                    const Date& referenceDate,
183
                                    const DayCounter& dayCounter,
184
                                    const std::vector<Handle<Quote> >& jumps,
185
                                    const std::vector<Date>& jumpDates,
186
                                    const T& interpolator)
187
    : SurvivalProbabilityStructure(referenceDate, Calendar(), dayCounter, jumps, jumpDates),
188
      InterpolatedCurve<T>(interpolator) {}
189
190
    template <class T>
191
    InterpolatedSurvivalProbabilityCurve<T>::InterpolatedSurvivalProbabilityCurve(
192
                                    Natural settlementDays,
193
                                    const Calendar& calendar,
194
                                    const DayCounter& dayCounter,
195
                                    const std::vector<Handle<Quote> >& jumps,
196
                                    const std::vector<Date>& jumpDates,
197
                                    const T& interpolator)
198
    : SurvivalProbabilityStructure(settlementDays, calendar, dayCounter, jumps, jumpDates),
199
      InterpolatedCurve<T>(interpolator) {}
200
201
    template <class T>
202
    InterpolatedSurvivalProbabilityCurve<T>::InterpolatedSurvivalProbabilityCurve(
203
                                    const std::vector<Date>& dates,
204
                                    const std::vector<Probability>& probabilities,
205
                                    const DayCounter& dayCounter,
206
                                    const Calendar& calendar,
207
                                    const std::vector<Handle<Quote> >& jumps,
208
                                    const std::vector<Date>& jumpDates,
209
                                    const T& interpolator)
210
    : SurvivalProbabilityStructure(dates.at(0), calendar, dayCounter, jumps, jumpDates),
211
      InterpolatedCurve<T>(std::vector<Time>(), probabilities, interpolator),
212
      dates_(dates)
213
    {
214
        initialize();
215
    }
216
217
    template <class T>
218
    InterpolatedSurvivalProbabilityCurve<T>::InterpolatedSurvivalProbabilityCurve(
219
                                    const std::vector<Date>& dates,
220
                                    const std::vector<Probability>& probabilities,
221
                                    const DayCounter& dayCounter,
222
                                    const Calendar& calendar,
223
                                    const T& interpolator)
224
    : SurvivalProbabilityStructure(dates.at(0), calendar, dayCounter),
225
      InterpolatedCurve<T>(std::vector<Time>(), probabilities, interpolator),
226
      dates_(dates)
227
    {
228
        initialize();
229
    }
230
231
    template <class T>
232
    InterpolatedSurvivalProbabilityCurve<T>::InterpolatedSurvivalProbabilityCurve(
233
                                    const std::vector<Date>& dates,
234
                                    const std::vector<Probability>& probabilities,
235
                                    const DayCounter& dayCounter,
236
                                    const T& interpolator)
237
    : SurvivalProbabilityStructure(dates.at(0), Calendar(), dayCounter),
238
      InterpolatedCurve<T>(std::vector<Time>(), probabilities, interpolator),
239
      dates_(dates)
240
    {
241
        initialize();
242
    }
243
244
245
    #endif
246
247
248
    template <class T>
249
    void InterpolatedSurvivalProbabilityCurve<T>::initialize()
250
    {
251
        QL_REQUIRE(dates_.size() >= T::requiredPoints,
252
                   "not enough input dates given");
253
        QL_REQUIRE(this->data_.size() == dates_.size(),
254
                   "dates/data count mismatch");
255
        QL_REQUIRE(this->data_[0] == 1.0,
256
                   "the first probability must be == 1.0 "
257
                   "to flag the corresponding date as reference date");
258
259
        this->setupTimes(dates_, dates_[0], dayCounter());
260
261
        for (Size i=1; i<dates_.size(); ++i) {
262
            QL_REQUIRE(this->data_[i] > 0.0, "negative probability");
263
            QL_REQUIRE(this->data_[i] <= this->data_[i-1],
264
                       "negative hazard rate implied by the survival "
265
                       "probability " <<
266
                       this->data_[i] << " at " << dates_[i] <<
267
                       " (t=" << this->times_[i] << ") after the survival "
268
                       "probability " <<
269
                       this->data_[i-1] << " at " << dates_[i-1] <<
270
                       " (t=" << this->times_[i-1] << ")");
271
        }
272
273
        this->setupInterpolation();
274
        this->interpolation_.update();
275
    }
276
277
}
278
279
#endif