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 Mark Joshi 6 7 This file is part of QuantLib, a free-software/open-source library 8 for financial quantitative analysts and developers - http://quantlib.org/ 9 10 QuantLib is free software: you can redistribute it and/or modify it 11 under the terms of the QuantLib license. You should have received a 12 copy of the license along with this program; if not, please email 13 <quantlib-dev@lists.sf.net>. The license is also available online at 14 <http://quantlib.org/license.shtml>. 15 16 This program is distributed in the hope that it will be useful, but WITHOUT 17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 18 FOR A PARTICULAR PURPOSE. See the license for more details. 19 */ 20 21 #include <ql/models/marketmodels/models/ctsmmcapletcalibration.hpp> 22 #include <ql/models/marketmodels/models/piecewiseconstantvariance.hpp> 23 #include <ql/models/marketmodels/models/pseudorootfacade.hpp> 24 #include <ql/models/marketmodels/models/cotswaptofwdadapter.hpp> 25 #include <ql/models/marketmodels/swapforwardmappings.hpp> 26 #include <ql/models/marketmodels/marketmodel.hpp> 27 #include <ql/math/matrixutilities/pseudosqrt.hpp> 28 #include <ql/math/comparison.hpp> 29 #include <ql/utilities/dataformatters.hpp> 30 31 namespace QuantLib { 32 ~CTSMMCapletCalibration()33 CTSMMCapletCalibration::~CTSMMCapletCalibration() {} 34 CTSMMCapletCalibration(const EvolutionDescription & evolution,const ext::shared_ptr<PiecewiseConstantCorrelation> & corr,const std::vector<ext::shared_ptr<PiecewiseConstantVariance>> & displacedSwapVariances,const std::vector<Volatility> & mktCapletVols,const ext::shared_ptr<CurveState> & cs,Spread displacement)35 CTSMMCapletCalibration::CTSMMCapletCalibration( 36 const EvolutionDescription& evolution, 37 const ext::shared_ptr<PiecewiseConstantCorrelation>& corr, 38 const std::vector<ext::shared_ptr< 39 PiecewiseConstantVariance> >& 40 displacedSwapVariances, 41 const std::vector<Volatility>& mktCapletVols, 42 const ext::shared_ptr<CurveState>& cs, 43 Spread displacement) 44 : evolution_(evolution), corr_(corr), 45 displacedSwapVariances_(displacedSwapVariances), 46 mktCapletVols_(mktCapletVols), 47 mdlCapletVols_(evolution_.numberOfRates()), 48 mktSwaptionVols_(evolution_.numberOfRates()), 49 mdlSwaptionVols_(evolution_.numberOfRates()), 50 cs_(cs), displacement_(displacement), 51 numberOfRates_(evolution_.numberOfRates()) 52 { 53 performChecks(evolution_, *corr_, displacedSwapVariances_, 54 mktCapletVols_, *cs_); 55 56 57 58 } 59 60 const std::vector<Volatility>& timeDependentUnCalibratedSwaptionVols(Size i) const61 CTSMMCapletCalibration::timeDependentUnCalibratedSwaptionVols(Size i) const 62 { 63 QL_REQUIRE(i<numberOfRates_, 64 "index (" << i << ") must less than number of rates (" << 65 numberOfRates_ << ")"); 66 return displacedSwapVariances_[i]->volatilities(); 67 } 68 69 const std::vector<Volatility>& timeDependentCalibratedSwaptionVols(Size i) const70 CTSMMCapletCalibration::timeDependentCalibratedSwaptionVols(Size i) const 71 { 72 QL_REQUIRE(i<numberOfRates_, 73 "index (" << i << ") must less than number of rates (" << 74 numberOfRates_ << ")"); 75 return timeDependentCalibratedSwaptionVols_[i]; 76 } 77 performChecks(const EvolutionDescription & evolution,const PiecewiseConstantCorrelation & corr,const std::vector<ext::shared_ptr<PiecewiseConstantVariance>> & displacedSwapVariances,const std::vector<Volatility> & mktCapletVols,const CurveState & cs)78 void CTSMMCapletCalibration::performChecks( 79 const EvolutionDescription& evolution, 80 const PiecewiseConstantCorrelation& corr, 81 const std::vector<ext::shared_ptr< 82 PiecewiseConstantVariance> >& 83 displacedSwapVariances, 84 const std::vector<Volatility>& mktCapletVols, 85 const CurveState& cs) 86 { 87 const std::vector<Time>& evolutionTimes = evolution.evolutionTimes(); 88 QL_REQUIRE(evolutionTimes==corr.times(), 89 "evolutionTimes " 90 << io::sequence(evolutionTimes) 91 << " not equal to correlation times " 92 << io::sequence(corr.times())); 93 94 const std::vector<Time>& rateTimes = evolution.rateTimes(); 95 QL_REQUIRE(rateTimes==cs.rateTimes(), 96 "mismatch between EvolutionDescription and " 97 "CurveState rate times"); 98 99 Size numberOfRates = evolution.numberOfRates(); 100 QL_REQUIRE(numberOfRates==displacedSwapVariances.size(), 101 "mismatch between EvolutionDescription number of rates (" 102 << numberOfRates << ") and displacedSwapVariances size (" 103 << displacedSwapVariances.size() << ")"); 104 QL_REQUIRE(numberOfRates==corr.numberOfRates(), 105 "mismatch between EvolutionDescription number of rates (" 106 << numberOfRates << ") and corr number of rates (" 107 << corr.numberOfRates() << ")"); 108 QL_REQUIRE(numberOfRates==mktCapletVols.size(), 109 "mismatch between EvolutionDescription number of rates (" 110 << numberOfRates << ") and mktCapletVols size (" 111 << mktCapletVols.size() << ")"); 112 QL_REQUIRE(numberOfRates==cs.numberOfRates(), 113 "mismatch between EvolutionDescription number of rates (" 114 << numberOfRates << ") and CurveState number of rates (" 115 << cs.numberOfRates() << ")"); 116 117 std::vector<Time> temp(rateTimes.begin(), rateTimes.end()-1); 118 QL_REQUIRE(temp==evolutionTimes, 119 "mismatch between evolutionTimes and rateTimes"); 120 121 Volatility lastSwaptionVol = 122 displacedSwapVariances.back()->totalVolatility(numberOfRates-1); 123 QL_REQUIRE(close(lastSwaptionVol, mktCapletVols[numberOfRates-1]), 124 "last caplet vol (" << std::setprecision(16) << 125 mktCapletVols[numberOfRates-1] << 126 ") must be equal to last swaption vol (" << 127 lastSwaptionVol << "); discrepancy is " << 128 lastSwaptionVol-mktCapletVols[numberOfRates-1]); 129 } 130 calibrate(Natural numberOfFactors,Natural maxIterations,Real capletVolTolerance,Natural innerSolvingMaxIterations,Real innerSolvingTolerance)131 bool CTSMMCapletCalibration::calibrate(Natural numberOfFactors, 132 133 Natural maxIterations, 134 Real capletVolTolerance, 135 136 Natural innerSolvingMaxIterations, 137 Real innerSolvingTolerance) { 138 // initialize results 139 calibrated_ = false; 140 failures_ = 987654321; // a positive large number 141 deformationSize_ = 987654321; 142 capletRmsError_ = swaptionRmsError_ = 987654321; 143 capletMaxError_ = swaptionMaxError_ = 987654321; 144 145 // initialize working variables 146 usedCapletVols_ = mktCapletVols_; 147 148 for (Size i=0; i<numberOfRates_; ++i) 149 mktSwaptionVols_[i]=displacedSwapVariances_[i]->totalVolatility(i); 150 151 std::vector<Spread> displacements(numberOfRates_, 152 displacement_); 153 const std::vector<Time>& rateTimes = evolution_.rateTimes(); 154 Natural iterations = 0; 155 156 // calibration loop 157 do { 158 failures_ = calibrationImpl_(numberOfFactors, 159 innerSolvingMaxIterations, 160 innerSolvingTolerance); 161 162 ext::shared_ptr<MarketModel> ctsmm(new 163 PseudoRootFacade(swapCovariancePseudoRoots_, 164 rateTimes, 165 cs_->coterminalSwapRates(), 166 displacements)); 167 const Matrix& swaptionTotCovariance = 168 ctsmm->totalCovariance(numberOfRates_-1); 169 170 CotSwapToFwdAdapter flmm(ctsmm); 171 const Matrix& capletTotCovariance = 172 flmm.totalCovariance(numberOfRates_-1); 173 174 // check fit 175 capletRmsError_ = swaptionRmsError_ = 0.0; 176 capletMaxError_ = swaptionMaxError_ = -1.0; 177 178 for (Size i=0; i<numberOfRates_; ++i) { 179 mdlSwaptionVols_[i] = std::sqrt(swaptionTotCovariance[i][i]/rateTimes[i]); 180 Real swaptionError = std::fabs(mktSwaptionVols_[i]-mdlSwaptionVols_[i]); 181 swaptionRmsError_ += swaptionError*swaptionError; 182 swaptionMaxError_ = std::max(swaptionMaxError_, swaptionError); 183 184 mdlCapletVols_[i] = std::sqrt(capletTotCovariance[i][i]/rateTimes[i]); 185 Real capletError = std::fabs(mktCapletVols_[i]-mdlCapletVols_[i]); 186 capletRmsError_ += capletError*capletError; 187 capletMaxError_ = std::max(capletMaxError_, capletError); 188 189 if (i < numberOfRates_-1) 190 usedCapletVols_[i] *= mktCapletVols_[i]/mdlCapletVols_[i]; 191 } 192 swaptionRmsError_ = std::sqrt(swaptionRmsError_/numberOfRates_); 193 capletRmsError_ = std::sqrt(capletRmsError_/numberOfRates_); 194 ++iterations; 195 } while (iterations<maxIterations && 196 capletRmsError_>capletVolTolerance); 197 198 ext::shared_ptr<MarketModel> ctsmm(new 199 PseudoRootFacade(swapCovariancePseudoRoots_, 200 rateTimes, 201 cs_->coterminalSwapRates(), 202 displacements)); 203 204 timeDependentCalibratedSwaptionVols_.clear(); 205 for (Size i=0; i<numberOfRates_; ++i) 206 timeDependentCalibratedSwaptionVols_.push_back( 207 ctsmm->timeDependentVolatility(i)); 208 209 // calculate deformationSize_ ?? 210 calibrated_ = true; 211 return failures_==0; 212 } 213 214 } 215