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 <http://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 initialDateQuantLib::SurvivalProbability54 static Date initialDate(const DefaultProbabilityTermStructure* c) { 55 return c->referenceDate(); 56 } 57 // value at reference date initialValueQuantLib::SurvivalProbability58 static Real initialValue(const DefaultProbabilityTermStructure*) { 59 return 1.0; 60 } 61 62 // guesses 63 template <class C> guessQuantLib::SurvivalProbability64 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> minValueAfterQuantLib::SurvivalProbability81 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> maxValueAfterQuantLib::SurvivalProbability93 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 updateGuessQuantLib::SurvivalProbability103 static void updateGuess(std::vector<Real>& data, 104 Probability p, 105 Size i) { 106 data[i] = p; 107 } 108 // upper bound for convergence loop maxIterationsQuantLib::SurvivalProbability109 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 initialDateQuantLib::HazardRate125 static Date initialDate(const DefaultProbabilityTermStructure* c) { 126 return c->referenceDate(); 127 } 128 // dummy value at reference date initialValueQuantLib::HazardRate129 static Real initialValue(const DefaultProbabilityTermStructure*) { 130 return detail::avgHazardRate; 131 } 132 133 // guesses 134 template <class C> guessQuantLib::HazardRate135 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> minValueAfterQuantLib::HazardRate153 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> maxValueAfterQuantLib::HazardRate165 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 updateGuessQuantLib::HazardRate179 static void updateGuess(std::vector<Real>& data, 180 Real rate, 181 Size i) { 182 data[i] = rate; 183 if (i==1) 184 data[0] = rate; // first point is updated as well 185 } 186 // upper bound for convergence loop maxIterationsQuantLib::HazardRate187 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 initialDateQuantLib::DefaultDensity201 static Date initialDate(const DefaultProbabilityTermStructure* c) { 202 return c->referenceDate(); 203 } 204 // value at reference date initialValueQuantLib::DefaultDensity205 static Real initialValue(const DefaultProbabilityTermStructure*) { 206 return detail::avgHazardRate; 207 } 208 209 // guesses 210 template <class C> guessQuantLib::DefaultDensity211 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> minValueAfterQuantLib::DefaultDensity229 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> maxValueAfterQuantLib::DefaultDensity241 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 updateGuessQuantLib::DefaultDensity256 static void updateGuess(std::vector<Real>& data, 257 Real density, 258 Size i) { 259 data[i] = density; 260 if (i==1) 261 data[0] = density; // first point is updated as well 262 } 263 // upper bound for convergence loop maxIterationsQuantLib::DefaultDensity264 static Size maxIterations() { return 30; } 265 }; 266 267 } 268 269 #endif 270