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