QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
interpolatedaffinehazardratecurve.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2015 Jose Aparicio
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#ifndef quantlib_interpolated_affine_hazard_rate_curve_hpp
21#define quantlib_interpolated_affine_hazard_rate_curve_hpp
22
23#include <ql/stochasticprocess.hpp>
24#include <ql/experimental/credit/onefactoraffinesurvival.hpp>
25#include <ql/termstructures/credit/probabilitytraits.hpp>
26#include <ql/termstructures/interpolatedcurve.hpp>
27#include <ql/termstructures/bootstraphelper.hpp>
28#include <utility>
29
30namespace QuantLib {
31
36 /*
37 The hazard rate structure here refers to the deterministic term
38 structure added on top of the affine model intensity. It is typically
39 employed to match the current market implied probabilities. The total
40 probabilities keep their meaning and are those of the affine model. An
41 example of this is the CIR++ model as employed in credit.
42
43 (Although this is not usually the preferred way one can instead match the
44 model to price the market.)
45
46 Notice that here, hazardRateImpl(Time) returns the deterministic part of
47 the hazard rate and not E[\lambda] This is what the bootstrapping
48 requires but it might be confusing.
49
50 \todo Redesign?:
51 The Affine model type is meant to model short rates; most methods
52 if not all still have sense here, though discounts mean probabilities.
53 This is not satisfactory, the affine models might need more structure
54 or reusing these classes should be reconsidered.
55 \todo Implement forward default methods.
56 \todo Implement statistics methods (expected values etc)
57
58 */
60 template <class Interpolator>
63 protected InterpolatedCurve<Interpolator> {
64 public:
66 const std::vector<Date>& dates,
67 const std::vector<Rate>& hazardRates,
69 const ext::shared_ptr<OneFactorAffineModel>& model,
70 const Calendar& cal = Calendar(),
71 const std::vector<Handle<Quote> >& jumps = std::vector<Handle<Quote> >(),
72 const std::vector<Date>& jumpDates = std::vector<Date>(),
73 const Interpolator& interpolator = Interpolator());
74 InterpolatedAffineHazardRateCurve(const std::vector<Date>& dates,
75 const std::vector<Rate>& hazardRates,
77 const ext::shared_ptr<OneFactorAffineModel>& model,
78 const Calendar& calendar,
79 const Interpolator& interpolator);
80 InterpolatedAffineHazardRateCurve(const std::vector<Date>& dates,
81 const std::vector<Rate>& hazardRates,
83 const ext::shared_ptr<OneFactorAffineModel>& model,
84 const Interpolator& interpolator);
86
87 Date maxDate() const override;
89
91 const std::vector<Time>& times() const;
92 const std::vector<Date>& dates() const;
93 const std::vector<Real>& data() const;
94 const std::vector<Rate>& hazardRates() const;
95 std::vector<std::pair<Date, Real> > nodes() const;
97 protected:
99 const DayCounter&,
100 const ext::shared_ptr<OneFactorAffineModel>& model,
101 const std::vector<Handle<Quote> >& jumps = std::vector<Handle<Quote> >(),
102 const std::vector<Date>& jumpDates = std::vector<Date>(),
103 const Interpolator& interpolator = Interpolator());
105 const Date& referenceDate,
106 const DayCounter&,
107 const ext::shared_ptr<OneFactorAffineModel>& model,
108 const std::vector<Handle<Quote> >& jumps = std::vector<Handle<Quote> >(),
109 const std::vector<Date>& jumpDates = std::vector<Date>(),
110 const Interpolator& interpolator = Interpolator());
113 const Calendar&,
114 const DayCounter&,
115 const ext::shared_ptr<OneFactorAffineModel>& model,
116 const std::vector<Handle<Quote> >& jumps = std::vector<Handle<Quote> >(),
117 const std::vector<Date>& jumpDates = std::vector<Date>(),
118 const Interpolator& interpolator = Interpolator());
120
121
122 Real hazardRateImpl(Time) const override;
124
125 public:
127 protected:
134 conditionalSurvivalProbabilityImpl(Time tFwd, Time tTarget, Real yVal) const override;
136
137 mutable std::vector<Date> dates_;
138
139 private:
141 };
142
143
144 namespace detail {
145 // hazard rate compensation TS for affine models
147 }
148
153 // interpolated curve type
154 template <class Interpolator>
155 struct curve {
157 };
158 // helper class
160
161 // start of curve data
163 return c->referenceDate();
164 }
165 // dummy value at reference date
168 }
169
170 // guesses
171 template <class C>
172 static Real guess(Size i,
173 const C* c,
174 bool validData,
175 Size) // firstAliveHelper
176 {
177 if (validData) // previous iteration value
178 return c->data()[i];
179
180 if (i==1) // first pillar
181 return 0.0001;
182 // return detail::avgHazardRate;
183
184 // extrapolate
185 Date d = c->dates()[i];
186 /* Uneasy about the naming: Here we are bootstrapping only the
187 deterministic part of the intensity it might be a better idea to
188 have a different naming when having these two components.
189 What is meant here is the deterministic part of a ++model type
190 */
191 return c->hazardRate(d, true);
192 }
193
194 // constraints
195 template <class C>
197 const C* c,
198 bool validData,
199 Size) // firstAliveHelper
200 {
201 if (validData) {
202 Real r = *(std::min_element(c->data().begin(),
203 c->data().end()));
204 return r/2.0;
205 }
208 }
209 template <class C>
211 const C* c,
212 bool validData,
213 Size) // firstAliveHelper
214 {
215 if (validData) {
216 Real r = *(std::max_element(c->data().begin(),
217 c->data().end()));
218 return r*2.0;
219 }
220 // no constraints.
221 // We choose as max a value very unlikely to be exceeded.
223 }
224 // update with new guess
225 static void updateGuess(std::vector<Real>& data,
226 Real rate,
227 Size i) {
228 data[i] = rate;
229 if (i==1)
230 data[0] = rate; // first point is updated as well
231 }
232 // upper bound for convergence loop
233 static Size maxIterations() { return 30; }
234 };
235
236
237 // inline definitions
238
239 template <class T>
241 return dates_.back();
242 }
243
244 template <class T>
245 inline const std::vector<Time>&
247 return this->times_;
248 }
249
250 template <class T>
251 inline const std::vector<Date>&
253 return dates_;
254 }
255
256 template <class T>
257 inline const std::vector<Real>&
259 return this->data_;
260 }
261
262 template <class T>
263 inline const std::vector<Rate>&
265 return this->data_;
266 }
267
268 template <class T>
269 inline std::vector<std::pair<Date, Real> >
271 std::vector<std::pair<Date, Real> > results(dates_.size());
272 for (Size i=0; i<dates_.size(); ++i)
273 results[i] = std::make_pair(dates_[i], this->data_[i]);
274 return results;
275 }
276
277 #ifndef __DOXYGEN__
278
279 // template definitions
280
281 template <class T>
283 if (t <= this->times_.back())
284 return this->interpolation_(t, true);
285
286 // deterministic flat hazard rate extrapolation
287 return this->data_.back();
288 }
289
290 // notice it is rewritten and no call is made to hazardRateImpl
291 template <class T>
294 Time t) const
295 {
296 // the way x0 is defined:
297 Real initValHR = std::pow(model_->dynamics()->process()->x0(), 2);
298
299 if (t == 0.0)
300 return model_->discountBond(0., t, initValHR);
301
302 Real integral;
303 if (t <= this->times_.back()) {
304 integral = this->interpolation_.primitive(t, true);
305 } else {
306 // flat hazard rate extrapolation
307 integral =
308 this->interpolation_.primitive(this->times_.back(), true)
309 + this->data_.back()*(t - this->times_.back());
310 }
311 return std::exp(-integral) * model_->discountBond(0., t, initValHR);
312 }
313
314 template <class T>
317 Time tFwd, Time tTarget, Real yVal) const
318 {
319 QL_REQUIRE(tFwd <= tTarget, "Probability time in the past.");
320 // Still leaves the possibility of sending tFwd=0 and an yVal different
321 // to the initial conditions. In an abstract sense thats all right as
322 // long as it is seen as a zero probability scenario.
323 #if defined(QL_EXTRA_SAFETY_CHECKS)
324 QL_REQUIRE(tFwd > 0. || yVal ==
325 model_->dynamics()->process()->x0(),
326 "Initial value different to process'.");
327 #endif
328 if (tFwd == 0.) return survivalProbabilityImpl(tTarget);
329 if (tFwd - tTarget == 0.0)
330 return 1.;
331
332 Real integralTFwd, integralTP;
333 if (tFwd <= this->times_.back()) {
334 integralTFwd = this->interpolation_.primitive(tFwd, true);
335 } else {
336 // flat hazard rate extrapolation
337 integralTFwd =
338 this->interpolation_.primitive(this->times_.back(), true)
339 + this->data_.back()*(tFwd - this->times_.back());
340 }
341 if (tTarget <= this->times_.back()) {
342 integralTP = this->interpolation_.primitive(tTarget, true);
343 } else {
344 // flat hazard rate extrapolation
345 integralTP =
346 this->interpolation_.primitive(this->times_.back(), true)
347 + this->data_.back()*(tTarget - this->times_.back());
348 }
349
350 return std::exp(-(integralTP-integralTFwd)) *
351 model_->discountBond(tFwd, tTarget, yVal );
352 }
353
354 template <class T>
356 const DayCounter& dayCounter,
357 const ext::shared_ptr<OneFactorAffineModel>& model,
358 const std::vector<Handle<Quote> >& jumps,
359 const std::vector<Date>& jumpDates,
360 const T& interpolator)
361 : OneFactorAffineSurvivalStructure(model, dayCounter, jumps, jumpDates), InterpolatedCurve<T>(
362 interpolator) {}
363
364 template <class T>
366 const Date& referenceDate,
367 const DayCounter& dayCounter,
368 const ext::shared_ptr<OneFactorAffineModel>& model,
369 const std::vector<Handle<Quote> >& jumps,
370 const std::vector<Date>& jumpDates,
371 const T& interpolator)
372 : OneFactorAffineSurvivalStructure(
373 model, referenceDate, Calendar(), dayCounter, jumps, jumpDates),
374 InterpolatedCurve<T>(interpolator) {}
375
376 template <class T>
378 Natural settlementDays,
379 const Calendar& calendar,
380 const DayCounter& dayCounter,
381 const ext::shared_ptr<OneFactorAffineModel>& model,
382 const std::vector<Handle<Quote> >& jumps,
383 const std::vector<Date>& jumpDates,
384 const T& interpolator)
385 : OneFactorAffineSurvivalStructure(
386 model, settlementDays, calendar, dayCounter, jumps, jumpDates),
387 InterpolatedCurve<T>(interpolator) {}
388
389 template <class T>
391 const std::vector<Date>& dates,
392 const std::vector<Rate>& hazardRates,
393 const DayCounter& dayCounter,
394 const ext::shared_ptr<OneFactorAffineModel>& model,
395 const Calendar& calendar,
396 const std::vector<Handle<Quote> >& jumps,
397 const std::vector<Date>& jumpDates,
398 const T& interpolator)
399 : OneFactorAffineSurvivalStructure(model, dates.at(0), calendar, dayCounter, jumps, jumpDates),
400 InterpolatedCurve<T>(std::vector<Time>(), hazardRates, interpolator), dates_(dates) {
401 initialize();
402 }
403
404 template <class T>
406 const std::vector<Date>& dates,
407 const std::vector<Rate>& hazardRates,
408 const DayCounter& dayCounter,
409 const ext::shared_ptr<OneFactorAffineModel>& model,
410 const Calendar& calendar,
411 const T& interpolator)
412 : OneFactorAffineSurvivalStructure(model, dates.at(0), calendar, dayCounter),
413 InterpolatedCurve<T>(std::vector<Time>(), hazardRates, interpolator), dates_(dates) {
414 initialize();
415 }
416
417 template <class T>
419 const std::vector<Date>& dates,
420 const std::vector<Rate>& hazardRates,
421 const DayCounter& dayCounter,
422 const ext::shared_ptr<OneFactorAffineModel>& model,
423 const T& interpolator)
424 : OneFactorAffineSurvivalStructure(model, dates.at(0), Calendar(), dayCounter),
425 InterpolatedCurve<T>(std::vector<Time>(), hazardRates, interpolator), dates_(dates) {
426 initialize();
427 }
428
429 template <class T>
431 {
432 QL_REQUIRE(dates_.size() >= T::requiredPoints,
433 "not enough input dates given");
434 QL_REQUIRE(this->data_.size() == dates_.size(),
435 "dates/data count mismatch");
436
437 this->setupTimes(dates_, dates_[0], dayCounter());
438 this->setupInterpolation();
439 this->interpolation_.update();
440 }
441
442 #endif
443
444}
445
446#endif
Base helper class for bootstrapping.
calendar class
Definition: calendar.hpp:61
Concrete date class.
Definition: date.hpp:125
day counter class
Definition: daycounter.hpp:44
Default probability term structure.
Rate hazardRate(const Date &d, bool extrapolate=false) const
const std::vector< Date > & jumpDates() const
Shared handle to an observable.
Definition: handle.hpp:41
InterpolatedAffineHazardRateCurve(const DayCounter &, const ext::shared_ptr< OneFactorAffineModel > &model, const std::vector< Handle< Quote > > &jumps=std::vector< Handle< Quote > >(), const std::vector< Date > &jumpDates=std::vector< Date >(), const Interpolator &interpolator=Interpolator())
InterpolatedAffineHazardRateCurve(Natural settlementDays, const Calendar &, const DayCounter &, const ext::shared_ptr< OneFactorAffineModel > &model, const std::vector< Handle< Quote > > &jumps=std::vector< Handle< Quote > >(), const std::vector< Date > &jumpDates=std::vector< Date >(), const Interpolator &interpolator=Interpolator())
InterpolatedAffineHazardRateCurve(const std::vector< Date > &dates, const std::vector< Rate > &hazardRates, const DayCounter &dayCounter, const ext::shared_ptr< OneFactorAffineModel > &model, const Calendar &calendar, const Interpolator &interpolator)
Real hazardRateImpl(Time) const override
Returns the deterministic hazard rate component.
std::vector< std::pair< Date, Real > > nodes() const
InterpolatedAffineHazardRateCurve(const std::vector< Date > &dates, const std::vector< Rate > &hazardRates, const DayCounter &dayCounter, const ext::shared_ptr< OneFactorAffineModel > &model, const Calendar &cal=Calendar(), const std::vector< Handle< Quote > > &jumps=std::vector< Handle< Quote > >(), const std::vector< Date > &jumpDates=std::vector< Date >(), const Interpolator &interpolator=Interpolator())
Probability survivalProbabilityImpl(Time) const override
survival probability calculation
InterpolatedAffineHazardRateCurve(const std::vector< Date > &dates, const std::vector< Rate > &hazardRates, const DayCounter &dayCounter, const ext::shared_ptr< OneFactorAffineModel > &model, const Interpolator &interpolator)
Date maxDate() const override
the latest date for which the curve can return values
Probability conditionalSurvivalProbabilityImpl(Time tFwd, Time tTarget, Real yVal) const override
InterpolatedAffineHazardRateCurve(const Date &referenceDate, const DayCounter &, const ext::shared_ptr< OneFactorAffineModel > &model, const std::vector< Handle< Quote > > &jumps=std::vector< Handle< Quote > >(), const std::vector< Date > &jumpDates=std::vector< Date >(), const Interpolator &interpolator=Interpolator())
Helper class to build interpolated term structures.
virtual Natural settlementDays() const
the settlementDays used for reference date calculation
virtual const Date & referenceDate() const
the date at which discount = 1.0 and/or variance = 0.0
virtual Calendar calendar() const
the calendar used for reference and/or option date calculation
virtual DayCounter dayCounter() const
the day counter used for date/time conversion
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
unsigned QL_INTEGER Natural
positive integer
Definition: types.hpp:43
Real Probability
probability
Definition: types.hpp:82
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
STL namespace.
InterpolatedAffineHazardRateCurve< Interpolator > type
static void updateGuess(std::vector< Real > &data, Real rate, Size i)
BootstrapHelper< DefaultProbabilityTermStructure > helper
static Real maxValueAfter(Size i, const C *c, bool validData, Size)
static Real guess(Size i, const C *c, bool validData, Size)
static Real initialValue(const DefaultProbabilityTermStructure *)
static Real minValueAfter(Size i, const C *c, bool validData, Size)
static Date initialDate(const DefaultProbabilityTermStructure *c)