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