1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2006, 2008 Ferdinando Ametrano 5 Copyright (C) 2006 François du Vignaud 6 Copyright (C) 2006 Katiuscia Manzoni 7 Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl 8 Copyright (C) 2015 Peter Caspers 9 10 This file is part of QuantLib, a free-software/open-source library 11 for financial quantitative analysts and developers - http://quantlib.org/ 12 13 QuantLib is free software: you can redistribute it and/or modify it 14 under the terms of the QuantLib license. You should have received a 15 copy of the license along with this program; if not, please email 16 <quantlib-dev@lists.sf.net>. The license is also available online at 17 <http://quantlib.org/license.shtml>. 18 19 This program is distributed in the hope that it will be useful, but WITHOUT 20 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 21 FOR A PARTICULAR PURPOSE. See the license for more details. 22 */ 23 24 #include <ql/termstructures/volatility/swaption/swaptionvolmatrix.hpp> 25 #include <ql/termstructures/volatility/flatsmilesection.hpp> 26 #include <ql/time/calendars/nullcalendar.hpp> 27 #include <ql/utilities/dataformatters.hpp> 28 #include <ql/quotes/simplequote.hpp> 29 #include <ql/math/interpolations/bilinearinterpolation.hpp> 30 #include <ql/math/interpolations/flatextrapolation2d.hpp> 31 32 33 namespace QuantLib { 34 35 // floating reference date, floating market data SwaptionVolatilityMatrix(const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const std::vector<std::vector<Handle<Quote>>> & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const std::vector<std::vector<Real>> & shifts)36 SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( 37 const Calendar& cal, 38 BusinessDayConvention bdc, 39 const std::vector<Period>& optionT, 40 const std::vector<Period>& swapT, 41 const std::vector<std::vector<Handle<Quote> > >& vols, 42 const DayCounter& dc, 43 const bool flatExtrapolation, 44 const VolatilityType type, 45 const std::vector<std::vector<Real> >& shifts) 46 : SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc), 47 volHandles_(vols), shiftValues_(shifts), 48 volatilities_(vols.size(), vols.front().size()), 49 shifts_(vols.size(), vols.front().size(), 0.0), volatilityType_(type) { 50 checkInputs(volatilities_.rows(), volatilities_.columns(), shifts.size(), 51 shifts.empty() ? 0 : shifts.front().size()); 52 registerWithMarketData(); 53 if (flatExtrapolation) { 54 interpolation_ = 55 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 56 swapLengths_.begin(), swapLengths_.end(), 57 optionTimes_.begin(), optionTimes_.end(), volatilities_)); 58 interpolationShifts_ = 59 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 60 swapLengths_.begin(), swapLengths_.end(), 61 optionTimes_.begin(), optionTimes_.end(), shifts_)); 62 } else { 63 interpolation_ = BilinearInterpolation( 64 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 65 optionTimes_.end(), volatilities_); 66 interpolationShifts_ = BilinearInterpolation( 67 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 68 optionTimes_.end(), shifts_); 69 } 70 } 71 72 // fixed reference date, floating market data SwaptionVolatilityMatrix(const Date & refDate,const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const std::vector<std::vector<Handle<Quote>>> & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const std::vector<std::vector<Real>> & shifts)73 SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( 74 const Date& refDate, 75 const Calendar& cal, 76 BusinessDayConvention bdc, 77 const std::vector<Period>& optionT, 78 const std::vector<Period>& swapT, 79 const std::vector<std::vector<Handle<Quote> > >& vols, 80 const DayCounter& dc, 81 const bool flatExtrapolation, 82 const VolatilityType type, 83 const std::vector<std::vector<Real> >& shifts) 84 : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc), 85 volHandles_(vols), shiftValues_(shifts), 86 volatilities_(vols.size(), vols.front().size()), 87 shifts_(vols.size(), vols.front().size(), 0.0), volatilityType_(type) { 88 checkInputs(volatilities_.rows(), volatilities_.columns(), shifts.size(), 89 shifts.empty() ? 0 : shifts.front().size()); 90 registerWithMarketData(); 91 if (flatExtrapolation) { 92 interpolation_ = 93 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 94 swapLengths_.begin(), swapLengths_.end(), 95 optionTimes_.begin(), optionTimes_.end(), volatilities_)); 96 interpolationShifts_ = 97 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 98 swapLengths_.begin(), swapLengths_.end(), 99 optionTimes_.begin(), optionTimes_.end(), shifts_)); 100 } else { 101 interpolation_ = BilinearInterpolation( 102 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 103 optionTimes_.end(), volatilities_); 104 interpolationShifts_ = BilinearInterpolation( 105 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 106 optionTimes_.end(), shifts_); 107 } 108 } 109 110 // floating reference date, fixed market data SwaptionVolatilityMatrix(const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const Matrix & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const Matrix & shifts)111 SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( 112 const Calendar& cal, 113 BusinessDayConvention bdc, 114 const std::vector<Period>& optionT, 115 const std::vector<Period>& swapT, 116 const Matrix& vols, 117 const DayCounter& dc, 118 const bool flatExtrapolation, 119 const VolatilityType type, 120 const Matrix& shifts) 121 : SwaptionVolatilityDiscrete(optionT, swapT, 0, cal, bdc, dc), 122 volHandles_(vols.rows()), shiftValues_(vols.rows()), 123 volatilities_(vols.rows(), vols.columns()), 124 shifts_(vols.rows(), vols.columns(), 0.0), volatilityType_(type) { 125 126 checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns()); 127 128 // fill dummy handles to allow generic handle-based 129 // computations later on 130 for (Size i=0; i<vols.rows(); ++i) { 131 volHandles_[i].resize(vols.columns()); 132 shiftValues_[i].resize(vols.columns()); 133 for (Size j=0; j<vols.columns(); ++j) { 134 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new 135 SimpleQuote(vols[i][j]))); 136 shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0; 137 } 138 } 139 if (flatExtrapolation) { 140 interpolation_ = 141 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 142 swapLengths_.begin(), swapLengths_.end(), 143 optionTimes_.begin(), optionTimes_.end(), volatilities_)); 144 interpolationShifts_ = 145 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 146 swapLengths_.begin(), swapLengths_.end(), 147 optionTimes_.begin(), optionTimes_.end(), shifts_)); 148 } else { 149 interpolation_ = BilinearInterpolation( 150 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 151 optionTimes_.end(), volatilities_); 152 interpolationShifts_ = BilinearInterpolation( 153 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 154 optionTimes_.end(), shifts_); 155 } 156 } 157 158 // fixed reference date, fixed market data SwaptionVolatilityMatrix(const Date & refDate,const Calendar & cal,BusinessDayConvention bdc,const std::vector<Period> & optionT,const std::vector<Period> & swapT,const Matrix & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const Matrix & shifts)159 SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( 160 const Date& refDate, 161 const Calendar& cal, 162 BusinessDayConvention bdc, 163 const std::vector<Period>& optionT, 164 const std::vector<Period>& swapT, 165 const Matrix& vols, 166 const DayCounter& dc, 167 const bool flatExtrapolation, 168 const VolatilityType type, 169 const Matrix& shifts) 170 : SwaptionVolatilityDiscrete(optionT, swapT, refDate, cal, bdc, dc), 171 volHandles_(vols.rows()), shiftValues_(vols.rows()), 172 volatilities_(vols.rows(), vols.columns()), 173 shifts_(shifts.rows(), shifts.columns(), 0.0), volatilityType_(type) { 174 175 checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns()); 176 177 // fill dummy handles to allow generic handle-based 178 // computations later on 179 for (Size i=0; i<vols.rows(); ++i) { 180 volHandles_[i].resize(vols.columns()); 181 shiftValues_[i].resize(vols.columns()); 182 for (Size j=0; j<vols.columns(); ++j) { 183 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new 184 SimpleQuote(vols[i][j]))); 185 shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0; 186 } 187 } 188 if (flatExtrapolation) { 189 interpolation_ = 190 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 191 swapLengths_.begin(), swapLengths_.end(), 192 optionTimes_.begin(), optionTimes_.end(), volatilities_)); 193 interpolationShifts_ = 194 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 195 swapLengths_.begin(), swapLengths_.end(), 196 optionTimes_.begin(), optionTimes_.end(), shifts_)); 197 } else { 198 interpolation_ = BilinearInterpolation( 199 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 200 optionTimes_.end(), volatilities_); 201 interpolationShifts_ = BilinearInterpolation( 202 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 203 optionTimes_.end(), shifts_); 204 } 205 } 206 207 // fixed reference date and fixed market data, option dates SwaptionVolatilityMatrix(const Date & today,const Calendar & calendar,BusinessDayConvention bdc,const std::vector<Date> & optionDates,const std::vector<Period> & swapT,const Matrix & vols,const DayCounter & dc,const bool flatExtrapolation,const VolatilityType type,const Matrix & shifts)208 SwaptionVolatilityMatrix::SwaptionVolatilityMatrix( 209 const Date& today, 210 const Calendar& calendar, 211 BusinessDayConvention bdc, 212 const std::vector<Date>& optionDates, 213 const std::vector<Period>& swapT, 214 const Matrix& vols, 215 const DayCounter& dc, 216 const bool flatExtrapolation, 217 const VolatilityType type, 218 const Matrix& shifts) 219 : SwaptionVolatilityDiscrete(optionDates, swapT, today, calendar, bdc, dc), 220 volHandles_(vols.rows()), shiftValues_(vols.rows()), 221 volatilities_(vols.rows(), vols.columns()), 222 shifts_(shifts.rows(),shifts.columns(),0.0), volatilityType_(type) { 223 224 checkInputs(vols.rows(), vols.columns(), shifts.rows(), shifts.columns()); 225 226 // fill dummy handles to allow generic handle-based 227 // computations later on 228 for (Size i=0; i<vols.rows(); ++i) { 229 volHandles_[i].resize(vols.columns()); 230 shiftValues_[i].resize(vols.columns()); 231 for (Size j=0; j<vols.columns(); ++j) { 232 volHandles_[i][j] = Handle<Quote>(ext::shared_ptr<Quote>(new 233 SimpleQuote(vols[i][j]))); 234 shiftValues_[i][j] = shifts.rows() > 0 ? shifts[i][j] : 0.0; 235 } 236 } 237 if (flatExtrapolation) { 238 interpolation_ = 239 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 240 swapLengths_.begin(), swapLengths_.end(), 241 optionTimes_.begin(), optionTimes_.end(), volatilities_)); 242 interpolationShifts_ = 243 FlatExtrapolator2D(ext::make_shared<BilinearInterpolation>( 244 swapLengths_.begin(), swapLengths_.end(), 245 optionTimes_.begin(), optionTimes_.end(), shifts_)); 246 } else { 247 interpolation_ = BilinearInterpolation( 248 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 249 optionTimes_.end(), volatilities_); 250 interpolationShifts_ = BilinearInterpolation( 251 swapLengths_.begin(), swapLengths_.end(), optionTimes_.begin(), 252 optionTimes_.end(), shifts_); 253 } 254 } 255 256 checkInputs(Size volRows,Size volsColumns,Size shiftRows,Size shiftsColumns) const257 void SwaptionVolatilityMatrix::checkInputs(Size volRows, 258 Size volsColumns, 259 Size shiftRows, 260 Size shiftsColumns) const { 261 QL_REQUIRE(nOptionTenors_==volRows, 262 "mismatch between number of option dates (" << 263 nOptionTenors_ << ") and number of rows (" << volRows << 264 ") in the vol matrix"); 265 QL_REQUIRE(nSwapTenors_==volsColumns, 266 "mismatch between number of swap tenors (" << 267 nSwapTenors_ << ") and number of columns (" << volsColumns << 268 ") in the vol matrix"); 269 270 if(shiftRows==0 && shiftsColumns==0) { 271 shifts_ = Matrix(volRows, volsColumns, 0.0); 272 shiftRows = volRows; 273 shiftsColumns = volsColumns; 274 } 275 276 QL_REQUIRE(nOptionTenors_==shiftRows, 277 "mismatch between number of option dates (" << 278 nOptionTenors_ << ") and number of rows (" << shiftRows << 279 ") in the shift matrix"); 280 QL_REQUIRE(nSwapTenors_==shiftsColumns, 281 "mismatch between number of swap tenors (" << 282 nSwapTenors_ << ") and number of columns (" << shiftsColumns << 283 ") in the shift matrix"); 284 285 } 286 registerWithMarketData()287 void SwaptionVolatilityMatrix::registerWithMarketData() 288 { 289 for (Size i=0; i<volHandles_.size(); ++i) 290 for (Size j=0; j<volHandles_.front().size(); ++j) 291 registerWith(volHandles_[i][j]); 292 } 293 performCalculations() const294 void SwaptionVolatilityMatrix::performCalculations() const { 295 296 SwaptionVolatilityDiscrete::performCalculations(); 297 298 // we might use iterators here... 299 for (Size i=0; i<volatilities_.rows(); ++i) { 300 for (Size j=0; j<volatilities_.columns(); ++j) { 301 volatilities_[i][j] = volHandles_[i][j]->value(); 302 if (!shiftValues_.empty()) 303 shifts_[i][j] = shiftValues_[i][j]; 304 } 305 } 306 } 307 308 //ext::shared_ptr<SmileSection> 309 //SwaptionVolatilityMatrix::smileSectionImpl(const Date& d, 310 // const Period& swapTenor) const { 311 // Time optionTime = timeFromReference(d); 312 // Time swapLength = convertSwapTenor(swapTenor); 313 // // dummy strike 314 // Volatility atmVol = volatilityImpl(optionTime, swapLength, 0.05); 315 // return ext::shared_ptr<SmileSection>(new 316 // FlatSmileSection(d, atmVol, dayCounter(), referenceDate())); 317 //} 318 319 ext::shared_ptr<SmileSection> smileSectionImpl(Time optionTime,Time swapLength) const320 SwaptionVolatilityMatrix::smileSectionImpl(Time optionTime, 321 Time swapLength) const { 322 // dummy strike 323 Volatility atmVol = volatilityImpl(optionTime, swapLength, 0.05); 324 return ext::shared_ptr<SmileSection>(new FlatSmileSection( 325 optionTime, atmVol, dayCounter(), Null<Real>(), volatilityType(), 326 shift(optionTime, swapLength, true))); 327 } 328 329 } 330