1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 
3 /*
4  Copyright (C) 2007 Ferdinando Ametrano
5  Copyright (C) 2007 Marco Bianchetti
6  Copyright (C) 2007 Giorgio Facchinetti
7  Copyright (C) 2007 François du Vignaud
8 
9  This file is part of QuantLib, a free-software/open-source library
10  for financial quantitative analysts and developers - http://quantlib.org/
11 
12  QuantLib is free software: you can redistribute it and/or modify it
13  under the terms of the QuantLib license.  You should have received a
14  copy of the license along with this program; if not, please email
15  <quantlib-dev@lists.sf.net>. The license is also available online at
16  <http://quantlib.org/license.shtml>.
17 
18  This program is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
20  FOR A PARTICULAR PURPOSE.  See the license for more details.
21 */
22 
23 #include <ql/models/marketmodels/correlations/expcorrelations.hpp>
24 #include <ql/models/marketmodels/correlations/timehomogeneousforwardcorrelation.hpp>
25 #include <ql/models/marketmodels/utilities.hpp>
26 #include <ql/math/comparison.hpp>
27 #include <ql/utilities/dataformatters.hpp>
28 
29 namespace QuantLib {
30 
exponentialCorrelations(const std::vector<Time> & rateTimes,Real longTermCorr,Real beta,Real gamma,Time time)31     Disposable<Matrix> exponentialCorrelations(
32                                         const std::vector<Time>& rateTimes,
33                                         Real longTermCorr,
34                                         Real beta,
35                                         Real gamma,
36                                         Time time) {
37         // preliminary checks
38         checkIncreasingTimes(rateTimes);
39         QL_REQUIRE(longTermCorr<=1.0 && longTermCorr>=0.0,
40                    "Long term correlation (" << longTermCorr <<
41                    ") outside [0;1] interval");
42         QL_REQUIRE(beta>=0.0,
43                    "beta (" << beta <<
44                    ") must be greater than zero");
45         QL_REQUIRE(gamma<=1.0 && gamma>=0.0,
46                    "gamma (" << gamma <<
47                    ") outside [0;1] interval");
48 
49         // Calculate correlation matrix
50         Size nbRows = rateTimes.size()-1;
51         Matrix correlations(nbRows, nbRows, 0.0);
52         for (Size i=0; i<nbRows; ++i) {
53             // correlation is defined only between
54             // (alive) stochastic rates...
55             if (time<=rateTimes[i]) {
56                 correlations[i][i] = 1.0;
57                 for (Size j=0; j<i; ++j) {
58                     if (time<=rateTimes[j]) {
59                         correlations[i][j] = correlations[j][i] =
60                             longTermCorr + (1.0-longTermCorr) *
61                             std::exp(-beta*std::fabs(
62                                 std::pow(rateTimes[i]-time, gamma) -
63                                 std::pow(rateTimes[j]-time, gamma)
64                                 )
65                             );
66                     }
67                 }
68             }
69         }
70         return correlations;
71     }
72 
73 
ExponentialForwardCorrelation(const std::vector<Time> & rateTimes,Real longTermCorr,Real beta,Real gamma,const std::vector<Time> & times)74     ExponentialForwardCorrelation::ExponentialForwardCorrelation(
75                                     const std::vector<Time>& rateTimes,
76                                     Real longTermCorr,
77                                     Real beta,
78                                     Real gamma,
79                                     const std::vector<Time>& times)
80     : numberOfRates_(rateTimes.empty() ? 0 : rateTimes.size()-1),
81       longTermCorr_(longTermCorr), beta_(beta), gamma_(gamma),
82       rateTimes_(rateTimes),
83       times_(times) {
84 
85         QL_REQUIRE(numberOfRates_>1,
86                    "Rate times must contain at least two values");
87 
88         checkIncreasingTimes(rateTimes_);
89 
90         // corrTimes must include all rateTimes but the last
91         if (times_.empty())
92             times_ = std::vector<Time>(rateTimes_.begin(),
93                                        rateTimes_.end()-1);
94         else
95             checkIncreasingTimes(times_);
96 
97         if (close(gamma,1.0)) {
98             std::vector<Time> temp(rateTimes_.begin(), rateTimes_.end()-1);
99             QL_REQUIRE(times_==temp,
100                        "corr times " << io::sequence(times_)
101                        << " must be equal to (all) rate times (but the last) "
102                        << io::sequence(temp));
103             Matrix c = exponentialCorrelations(
104                 rateTimes_, longTermCorr_, beta_, 1.0, 0.0);
105             correlations_ =
106                 TimeHomogeneousForwardCorrelation::evolvedMatrices(c);
107         } else {
108             // FIXME should check here that all rateTimes but the last
109             // are included in rateTimes
110             QL_REQUIRE(times_.back()<=rateTimes_[numberOfRates_],
111                        "last corr time " << times_.back() <<
112                        "is after next-to-last rate time " <<
113                        rateTimes_[numberOfRates_]);
114             correlations_.resize(times_.size());
115             Time time = times_[0]/2.0;
116             correlations_[0] = exponentialCorrelations(
117                 rateTimes_, longTermCorr_, beta_, gamma_, time);
118             for (Size k=1; k<times_.size(); ++k) {
119                 time = (times_[k]+times_[k-1])/2.0;
120                 correlations_[k] = exponentialCorrelations(
121                     rateTimes_, longTermCorr_, beta_, gamma_, time);
122             }
123         }
124     }
125 
126     const std::vector<Time>&
times() const127     ExponentialForwardCorrelation::times() const {
128         return times_;
129     }
130 
131     const std::vector<Time>&
rateTimes() const132     ExponentialForwardCorrelation::rateTimes() const {
133         return rateTimes_;
134     }
135 
136     const std::vector<Matrix>&
correlations() const137     ExponentialForwardCorrelation::correlations() const {
138         return correlations_;
139     }
140 
numberOfRates() const141     Size ExponentialForwardCorrelation::numberOfRates() const {
142         return numberOfRates_;
143     }
144 
145 }
146