Coverage Report

Created: 2026-01-25 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/termstructures/credit/probabilitytraits.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2008, 2016 Jose Aparicio
5
 Copyright (C) 2008 Chris Kenyon
6
 Copyright (C) 2008 Roland Lichters
7
 Copyright (C) 2008 StatPro Italia srl
8
 Copyright (C) 2009, 2011 Ferdinando Ametrano
9
10
 This file is part of QuantLib, a free-software/open-source library
11
 for financial quantitative analysts and developers - http://quantlib.org/
12
13
 QuantLib is free software: you can redistribute it and/or modify it
14
 under the terms of the QuantLib license.  You should have received a
15
 copy of the license along with this program; if not, please email
16
 <quantlib-dev@lists.sf.net>. The license is also available online at
17
 <https://www.quantlib.org/license.shtml>.
18
19
 This program is distributed in the hope that it will be useful, but WITHOUT
20
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
21
 FOR A PARTICULAR PURPOSE.  See the license for more details.
22
*/
23
24
/*! \file probabilitytraits.hpp
25
    \brief default-probability bootstrap traits
26
*/
27
28
#ifndef ql_probability_traits_hpp
29
#define ql_probability_traits_hpp
30
31
#include <ql/termstructures/credit/interpolatedsurvivalprobabilitycurve.hpp>
32
#include <ql/termstructures/credit/interpolatedhazardratecurve.hpp>
33
#include <ql/termstructures/credit/interpolateddefaultdensitycurve.hpp>
34
#include <ql/termstructures/bootstraphelper.hpp>
35
36
namespace QuantLib {
37
38
    namespace detail {
39
        const Real avgHazardRate = 0.01;
40
        const Real maxHazardRate = 1.0;
41
    }
42
43
    //! Survival-Probability-curve traits
44
    struct SurvivalProbability {
45
        // interpolated curve type
46
        template <class Interpolator>
47
        struct curve {
48
            typedef InterpolatedSurvivalProbabilityCurve<Interpolator> type;
49
        };
50
        // helper class
51
        typedef BootstrapHelper<DefaultProbabilityTermStructure> helper;
52
53
        // start of curve data
54
0
        static Date initialDate(const DefaultProbabilityTermStructure* c) {
55
0
            return c->referenceDate();
56
0
        }
57
        // value at reference date
58
0
        static Real initialValue(const DefaultProbabilityTermStructure*) {
59
0
            return 1.0;
60
0
        }
61
62
        // guesses
63
        template <class C>
64
        static Real guess(Size i,
65
                          const C* c,
66
                          bool validData,
67
                          Size) // firstAliveHelper
68
        {
69
            if (validData) // previous iteration value
70
                return c->data()[i];
71
72
            if (i==1) // first pillar
73
                return 1.0/(1.0+detail::avgHazardRate*0.25);
74
75
            // extrapolate
76
            Date d = c->dates()[i];
77
            return c->survivalProbability(d,true);
78
        }
79
        // constraints
80
        template <class C>
81
        static Real minValueAfter(Size i,
82
                                  const C* c,
83
                                  bool validData,
84
                                  Size) // firstAliveHelper
85
        {
86
            if (validData) {
87
                return c->data().back()/2.0;
88
            }
89
            Time dt = c->times()[i] - c->times()[i-1];
90
            return c->data()[i-1] * std::exp(- detail::maxHazardRate * dt);
91
        }
92
        template <class C>
93
        static Real maxValueAfter(Size i,
94
                                  const C* c,
95
                                  bool validData,
96
                                  Size) // firstAliveHelper
97
        {
98
            // survival probability cannot increase
99
            return c->data()[i-1];
100
        }
101
102
        // root-finding update
103
        static void updateGuess(std::vector<Real>& data,
104
                                Probability p,
105
0
                                Size i) {
106
0
            data[i] = p;
107
0
        }
108
        // upper bound for convergence loop
109
0
        static Size maxIterations() { return 50; }
110
    };
111
112
113
114
    //! Hazard-rate-curve traits
115
    struct HazardRate {
116
        // interpolated curve type
117
        template <class Interpolator>
118
        struct curve {
119
            typedef InterpolatedHazardRateCurve<Interpolator> type;
120
        };
121
        // helper class
122
        typedef BootstrapHelper<DefaultProbabilityTermStructure> helper;
123
124
        // start of curve data
125
0
        static Date initialDate(const DefaultProbabilityTermStructure* c) {
126
0
            return c->referenceDate();
127
0
        }
128
        // dummy value at reference date
129
0
        static Real initialValue(const DefaultProbabilityTermStructure*) {
130
0
            return detail::avgHazardRate;
131
0
        }
132
133
        // guesses
134
        template <class C>
135
        static Real guess(Size i,
136
                          const C* c,
137
                          bool validData,
138
                          Size) // firstAliveHelper
139
        {
140
            if (validData) // previous iteration value
141
                return c->data()[i];
142
143
            if (i==1) // first pillar
144
                return detail::avgHazardRate;
145
146
            // extrapolate
147
            Date d = c->dates()[i];
148
            return c->hazardRate(d, true);
149
        }
150
151
        // constraints
152
        template <class C>
153
        static Real minValueAfter(Size i,
154
                                  const C* c,
155
                                  bool validData,
156
                                  Size) // firstAliveHelper
157
        {
158
            if (validData) {
159
                Real r = *(std::min_element(c->data().begin(), c->data().end()));
160
                return r/2.0;
161
            }
162
            return QL_EPSILON;
163
        }
164
        template <class C>
165
        static Real maxValueAfter(Size i,
166
                                  const C* c,
167
                                  bool validData,
168
                                  Size) // firstAliveHelper
169
        {
170
            if (validData) {
171
                Real r = *(std::max_element(c->data().begin(), c->data().end()));
172
                return r*2.0;
173
            }
174
            // no constraints.
175
            // We choose as max a value very unlikely to be exceeded.
176
            return detail::maxHazardRate;
177
        }
178
        // update with new guess
179
        static void updateGuess(std::vector<Real>& data,
180
                                Real rate,
181
0
                                Size i) {
182
0
            data[i] = rate;
183
0
            if (i==1)
184
0
                data[0] = rate; // first point is updated as well
185
0
        }
186
        // upper bound for convergence loop
187
0
        static Size maxIterations() { return 30; }
188
    };
189
190
191
    //! Default-density-curve traits
192
    struct DefaultDensity {
193
        // interpolated curve type
194
        template <class Interpolator>
195
        struct curve {
196
            typedef InterpolatedDefaultDensityCurve<Interpolator> type;
197
        };
198
        // helper class
199
        typedef BootstrapHelper<DefaultProbabilityTermStructure> helper;
200
        // start of curve data
201
0
        static Date initialDate(const DefaultProbabilityTermStructure* c) {
202
0
            return c->referenceDate();
203
0
        }
204
        // value at reference date
205
0
        static Real initialValue(const DefaultProbabilityTermStructure*) {
206
0
            return detail::avgHazardRate;
207
0
        }
208
209
        // guesses
210
        template <class C>
211
        static Real guess(Size i,
212
                          const C* c,
213
                          bool validData,
214
                          Size) // firstAliveHelper
215
        {
216
            if (validData) // previous iteration value
217
                return c->data()[i];
218
219
            if (i==1) // first pillar
220
                return detail::avgHazardRate;
221
222
            // extrapolate
223
            Date d = c->dates()[i];
224
            return c->defaultDensity(d, true);
225
        }
226
227
        // constraints
228
        template <class C>
229
        static Real minValueAfter(Size i,
230
                                  const C* c,
231
                                  bool validData,
232
                                  Size) // firstAliveHelper
233
        {
234
            if (validData) {
235
                Real r = *(std::min_element(c->data().begin(), c->data().end()));
236
                return r/2.0;
237
            }
238
            return QL_EPSILON;
239
        }
240
        template <class C>
241
        static Real maxValueAfter(Size i,
242
                                  const C* c,
243
                                  bool validData,
244
                                  Size) // firstAliveHelper
245
        {
246
            if (validData) {
247
                Real r = *(std::max_element(c->data().begin(), c->data().end()));
248
                return r*2.0;
249
            }
250
            // no constraints.
251
            // We choose as max a value very unlikely to be exceeded.
252
            return detail::maxHazardRate;
253
        }
254
255
        // update with new guess
256
        static void updateGuess(std::vector<Real>& data,
257
                                Real density,
258
0
                                Size i) {
259
0
            data[i] = density;
260
0
            if (i==1)
261
0
                data[0] = density; // first point is updated as well
262
0
        }
263
        // upper bound for convergence loop
264
0
        static Size maxIterations() { return 30; }
265
    };
266
267
}
268
269
#endif