1 /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 3 /* 4 Copyright (C) 2002, 2003 RiskMap srl 5 Copyright (C) 2003, 2004, 2005, 2006 StatPro Italia srl 6 Copyright (C) 2006, 2008 Ferdinando Ametrano 7 Copyright (C) 2015 Peter Caspers 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 /*! \file swaptionvolstructure.hpp 24 \brief Swaption volatility structure 25 */ 26 27 #ifndef quantlib_swaption_volatility_structure_hpp 28 #define quantlib_swaption_volatility_structure_hpp 29 30 #include <ql/termstructures/voltermstructure.hpp> 31 #include <ql/termstructures/volatility/volatilitytype.hpp> 32 33 namespace QuantLib { 34 35 class SmileSection; 36 37 //! %Swaption-volatility structure 38 /*! This abstract class defines the interface of concrete swaption 39 volatility structures which will be derived from this one. 40 */ 41 class SwaptionVolatilityStructure : public VolatilityTermStructure { 42 public: 43 /*! \name Constructors 44 See the TermStructure documentation for issues regarding 45 constructors. 46 */ 47 //@{ 48 /*! \warning term structures initialized by means of this 49 constructor must manage their own reference date 50 by overriding the referenceDate() method. 51 */ 52 SwaptionVolatilityStructure(BusinessDayConvention bdc, 53 const DayCounter& dc = DayCounter()); 54 //! initialize with a fixed reference date 55 SwaptionVolatilityStructure(const Date& referenceDate, 56 const Calendar& calendar, 57 BusinessDayConvention bdc, 58 const DayCounter& dc = DayCounter()); 59 //! calculate the reference date based on the global evaluation date 60 SwaptionVolatilityStructure(Natural settlementDays, 61 const Calendar&, 62 BusinessDayConvention bdc, 63 const DayCounter& dc = DayCounter()); 64 //@} ~SwaptionVolatilityStructure()65 virtual ~SwaptionVolatilityStructure() {} 66 //! \name Volatility, variance and smile 67 //@{ 68 //! returns the volatility for a given option tenor and swap tenor 69 Volatility volatility(const Period& optionTenor, 70 const Period& swapTenor, 71 Rate strike, 72 bool extrapolate = false) const; 73 //! returns the volatility for a given option date and swap tenor 74 Volatility volatility(const Date& optionDate, 75 const Period& swapTenor, 76 Rate strike, 77 bool extrapolate = false) const; 78 //! returns the volatility for a given option time and swap tenor 79 Volatility volatility(Time optionTime, 80 const Period& swapTenor, 81 Rate strike, 82 bool extrapolate = false) const; 83 //! returns the volatility for a given option tenor and swap length 84 Volatility volatility(const Period& optionTenor, 85 Time swapLength, 86 Rate strike, 87 bool extrapolate = false) const; 88 //! returns the volatility for a given option date and swap length 89 Volatility volatility(const Date& optionDate, 90 Time swapLength, 91 Rate strike, 92 bool extrapolate = false) const; 93 //! returns the volatility for a given option time and swap length 94 Volatility volatility(Time optionTime, 95 Time swapLength, 96 Rate strike, 97 bool extrapolate = false) const; 98 99 //! returns the Black variance for a given option tenor and swap tenor 100 Real blackVariance(const Period& optionTenor, 101 const Period& swapTenor, 102 Rate strike, 103 bool extrapolate = false) const; 104 //! returns the Black variance for a given option date and swap tenor 105 Real blackVariance(const Date& optionDate, 106 const Period& swapTenor, 107 Rate strike, 108 bool extrapolate = false) const; 109 //! returns the Black variance for a given option time and swap tenor 110 Real blackVariance(Time optionTime, 111 const Period& swapTenor, 112 Rate strike, 113 bool extrapolate = false) const; 114 //! returns the Black variance for a given option tenor and swap length 115 Real blackVariance(const Period& optionTenor, 116 Time swapLength, 117 Rate strike, 118 bool extrapolate = false) const; 119 //! returns the Black variance for a given option date and swap length 120 Real blackVariance(const Date& optionDate, 121 Time swapLength, 122 Rate strike, 123 bool extrapolate = false) const; 124 //! returns the Black variance for a given option time and swap length 125 Real blackVariance(Time optionTime, 126 Time swapLength, 127 Rate strike, 128 bool extrapolate = false) const; 129 130 //! returns the shift for a given option tenor and swap tenor 131 Real shift(const Period& optionTenor, 132 const Period& swapTenor, 133 bool extrapolate = false) const; 134 //! returns the shift for a given option date and swap tenor 135 Real shift(const Date& optionDate, 136 const Period& swapTenor, 137 bool extrapolate = false) const; 138 //! returns the shift for a given option time and swap tenor 139 Real shift(Time optionTime, 140 const Period& swapTenor, 141 bool extrapolate = false) const; 142 //! returns the shift for a given option tenor and swap length 143 Real shift(const Period& optionTenor, 144 Time swapLength, 145 bool extrapolate = false) const; 146 //! returns the shift for a given option date and swap length 147 Real shift(const Date& optionDate, 148 Time swapLength, 149 bool extrapolate = false) const; 150 //! returns the shift for a given option time and swap length 151 Real shift(Time optionTime, 152 Time swapLength, 153 bool extrapolate = false) const; 154 155 //! returns the smile for a given option tenor and swap tenor 156 ext::shared_ptr<SmileSection> smileSection(const Period& optionTenor, 157 const Period& swapTenor, 158 bool extr = false) const; 159 //! returns the smile for a given option date and swap tenor 160 ext::shared_ptr<SmileSection> smileSection(const Date& optionDate, 161 const Period& swapTenor, 162 bool extr = false) const; 163 //! returns the smile for a given option time and swap tenor 164 ext::shared_ptr<SmileSection> smileSection(Time optionTime, 165 const Period& swapTenor, 166 bool extr = false) const; 167 //! returns the smile for a given option tenor and swap length 168 ext::shared_ptr<SmileSection> smileSection(const Period& optionTenor, 169 Time swapLength, 170 bool extr = false) const; 171 //! returns the smile for a given option date and swap length 172 ext::shared_ptr<SmileSection> smileSection(const Date& optionDate, 173 Time swapLength, 174 bool extr = false) const; 175 //! returns the smile for a given option time and swap length 176 ext::shared_ptr<SmileSection> smileSection(Time optionTime, 177 Time swapLength, 178 bool extr = false) const; 179 //@} 180 //! \name Limits 181 //@{ 182 //! the largest length for which the term structure can return vols 183 virtual const Period& maxSwapTenor() const = 0; 184 //! the largest swapLength for which the term structure can return vols 185 Time maxSwapLength() const; 186 //@} 187 //@{ 188 //! volatility type volatilityType() const189 virtual VolatilityType volatilityType() const { 190 return ShiftedLognormal; 191 } 192 //@} 193 //! implements the conversion between swap tenor and swap (time) length 194 Time swapLength(const Period& swapTenor) const; 195 //! implements the conversion between swap dates and swap (time) length 196 Time swapLength(const Date& start, 197 const Date& end) const; 198 protected: 199 virtual ext::shared_ptr<SmileSection> smileSectionImpl( 200 const Date& optionDate, 201 const Period& swapTenor) const; 202 virtual ext::shared_ptr<SmileSection> smileSectionImpl( 203 Time optionTime, 204 Time swapLength) const = 0; 205 virtual Volatility volatilityImpl(const Date& optionDate, 206 const Period& swapTenor, 207 Rate strike) const; 208 virtual Volatility volatilityImpl(Time optionTime, 209 Time swapLength, 210 Rate strike) const = 0; 211 virtual Real shiftImpl(const Date &optionDate, 212 const Period &swapTenor) const; 213 virtual Real shiftImpl(Time optionTime, Time swapLength) const; 214 void checkSwapTenor(const Period& swapTenor, 215 bool extrapolate) const; 216 void checkSwapTenor(Time swapLength, 217 bool extrapolate) const; 218 }; 219 220 // inline definitions 221 222 // 1. methods with Period-denominated exercise convert Period to Date and then 223 // use the equivalent Date-denominated exercise methods 224 inline Volatility volatility(const Period & optionTenor,const Period & swapTenor,Rate strike,bool extrapolate) const225 SwaptionVolatilityStructure::volatility(const Period& optionTenor, 226 const Period& swapTenor, 227 Rate strike, 228 bool extrapolate) const { 229 Date optionDate = optionDateFromTenor(optionTenor); 230 return volatility(optionDate, swapTenor, strike, extrapolate); 231 } 232 233 inline Volatility volatility(const Period & optionTenor,Time swapLength,Rate strike,bool extrapolate) const234 SwaptionVolatilityStructure::volatility(const Period& optionTenor, 235 Time swapLength, 236 Rate strike, 237 bool extrapolate) const { 238 Date optionDate = optionDateFromTenor(optionTenor); 239 return volatility(optionDate, swapLength, strike, extrapolate); 240 } 241 242 inline blackVariance(const Period & optionTenor,const Period & swapTenor,Rate strike,bool extrapolate) const243 Real SwaptionVolatilityStructure::blackVariance(const Period& optionTenor, 244 const Period& swapTenor, 245 Rate strike, 246 bool extrapolate) const { 247 Date optionDate = optionDateFromTenor(optionTenor); 248 return blackVariance(optionDate, swapTenor, strike, extrapolate); 249 } 250 251 inline blackVariance(const Period & optionTenor,Time swapLength,Rate strike,bool extrapolate) const252 Real SwaptionVolatilityStructure::blackVariance(const Period& optionTenor, 253 Time swapLength, 254 Rate strike, 255 bool extrapolate) const { 256 Date optionDate = optionDateFromTenor(optionTenor); 257 return blackVariance(optionDate, swapLength, strike, extrapolate); 258 } 259 260 inline shift(const Period & optionTenor,const Period & swapTenor,bool extrapolate) const261 Real SwaptionVolatilityStructure::shift(const Period& optionTenor, 262 const Period& swapTenor, 263 bool extrapolate) const { 264 Date optionDate = optionDateFromTenor(optionTenor); 265 return shift(optionDate, swapTenor, extrapolate); 266 } 267 268 inline shift(const Period & optionTenor,Time swapLength,bool extrapolate) const269 Real SwaptionVolatilityStructure::shift(const Period& optionTenor, 270 Time swapLength, 271 bool extrapolate) const { 272 Date optionDate = optionDateFromTenor(optionTenor); 273 return shift(optionDate, swapLength, extrapolate); 274 } 275 276 inline ext::shared_ptr<SmileSection> smileSection(const Period & optionTenor,const Period & swapTenor,bool extrapolate) const277 SwaptionVolatilityStructure::smileSection(const Period& optionTenor, 278 const Period& swapTenor, 279 bool extrapolate) const { 280 Date optionDate = optionDateFromTenor(optionTenor); 281 return smileSection(optionDate, swapTenor, extrapolate); 282 } 283 284 // 2. blackVariance methods rely on volatility methods 285 inline blackVariance(const Date & optionDate,const Period & swapTenor,Rate strike,bool extrapolate) const286 Real SwaptionVolatilityStructure::blackVariance(const Date& optionDate, 287 const Period& swapTenor, 288 Rate strike, 289 bool extrapolate) const { 290 Volatility v = volatility(optionDate, swapTenor, strike, extrapolate); 291 Time optionTime = timeFromReference(optionDate); 292 return v*v*optionTime; 293 } 294 295 inline blackVariance(Time optionTime,const Period & swapTenor,Rate strike,bool extrapolate) const296 Real SwaptionVolatilityStructure::blackVariance(Time optionTime, 297 const Period& swapTenor, 298 Rate strike, 299 bool extrapolate) const { 300 Volatility v = volatility(optionTime, swapTenor, strike, extrapolate); 301 return v*v*optionTime; 302 } 303 304 inline blackVariance(const Date & optionDate,Time swapLength,Rate strike,bool extrapolate) const305 Real SwaptionVolatilityStructure::blackVariance(const Date& optionDate, 306 Time swapLength, 307 Rate strike, 308 bool extrapolate) const { 309 Volatility v = volatility(optionDate, swapLength, strike, extrapolate); 310 Time optionTime = timeFromReference(optionDate); 311 return v*v*optionTime; 312 } 313 314 inline blackVariance(Time optionTime,Time swapLength,Rate strike,bool extrapolate) const315 Real SwaptionVolatilityStructure::blackVariance(Time optionTime, 316 Time swapLength, 317 Rate strike, 318 bool extrapolate) const { 319 Volatility v = volatility(optionTime, swapLength, strike, extrapolate); 320 return v*v*optionTime; 321 } 322 323 // 3. relying on xxxImpl methods 324 inline Volatility volatility(const Date & optionDate,const Period & swapTenor,Rate strike,bool extrapolate) const325 SwaptionVolatilityStructure::volatility(const Date& optionDate, 326 const Period& swapTenor, 327 Rate strike, 328 bool extrapolate) const { 329 checkSwapTenor(swapTenor, extrapolate); 330 checkRange(optionDate, extrapolate); 331 checkStrike(strike, extrapolate); 332 return volatilityImpl(optionDate, swapTenor, strike); 333 } 334 335 inline Volatility volatility(const Date & optionDate,Time swapLength,Rate strike,bool extrapolate) const336 SwaptionVolatilityStructure::volatility(const Date& optionDate, 337 Time swapLength, 338 Rate strike, 339 bool extrapolate) const { 340 checkSwapTenor(swapLength, extrapolate); 341 checkRange(optionDate, extrapolate); 342 checkStrike(strike, extrapolate); 343 Time optionTime = timeFromReference(optionDate); 344 return volatilityImpl(optionTime, swapLength, strike); 345 } 346 347 inline Volatility volatility(Time optionTime,const Period & swapTenor,Rate strike,bool extrapolate) const348 SwaptionVolatilityStructure::volatility(Time optionTime, 349 const Period& swapTenor, 350 Rate strike, 351 bool extrapolate) const { 352 checkSwapTenor(swapTenor, extrapolate); 353 checkRange(optionTime, extrapolate); 354 checkStrike(strike, extrapolate); 355 Time length = swapLength(swapTenor); 356 return volatilityImpl(optionTime, length, strike); 357 } 358 359 inline Volatility volatility(Time optionTime,Time swapLength,Rate strike,bool extrapolate) const360 SwaptionVolatilityStructure::volatility(Time optionTime, 361 Time swapLength, 362 Rate strike, 363 bool extrapolate) const { 364 checkSwapTenor(swapLength, extrapolate); 365 checkRange(optionTime, extrapolate); 366 checkStrike(strike, extrapolate); 367 return volatilityImpl(optionTime, swapLength, strike); 368 } 369 370 inline Real shift(const Date & optionDate,const Period & swapTenor,bool extrapolate) const371 SwaptionVolatilityStructure::shift(const Date& optionDate, 372 const Period& swapTenor, 373 bool extrapolate) const { 374 checkSwapTenor(swapTenor, extrapolate); 375 checkRange(optionDate, extrapolate); 376 return shiftImpl(optionDate, swapTenor); 377 } 378 379 inline Real shift(const Date & optionDate,Time swapLength,bool extrapolate) const380 SwaptionVolatilityStructure::shift(const Date& optionDate, 381 Time swapLength, 382 bool extrapolate) const { 383 checkSwapTenor(swapLength, extrapolate); 384 checkRange(optionDate, extrapolate); 385 Time optionTime = timeFromReference(optionDate); 386 return shiftImpl(optionTime, swapLength); 387 } 388 389 inline Real shift(Time optionTime,const Period & swapTenor,bool extrapolate) const390 SwaptionVolatilityStructure::shift(Time optionTime, 391 const Period& swapTenor, 392 bool extrapolate) const { 393 checkSwapTenor(swapTenor, extrapolate); 394 checkRange(optionTime, extrapolate); 395 Time length = swapLength(swapTenor); 396 return shiftImpl(optionTime, length); 397 } 398 399 inline Real shift(Time optionTime,Time swapLength,bool extrapolate) const400 SwaptionVolatilityStructure::shift(Time optionTime, 401 Time swapLength, 402 bool extrapolate) const { 403 checkSwapTenor(swapLength, extrapolate); 404 checkRange(optionTime, extrapolate); 405 return shiftImpl(optionTime, swapLength); 406 } 407 408 inline ext::shared_ptr<SmileSection> smileSection(const Date & optionDate,const Period & swapTenor,bool extrapolate) const409 SwaptionVolatilityStructure::smileSection(const Date& optionDate, 410 const Period& swapTenor, 411 bool extrapolate) const { 412 checkSwapTenor(swapTenor, extrapolate); 413 checkRange(optionDate, extrapolate); 414 return smileSectionImpl(optionDate, swapTenor); 415 } 416 417 inline ext::shared_ptr<SmileSection> smileSection(Time optionTime,const Period & swapTenor,bool extrapolate) const418 SwaptionVolatilityStructure::smileSection(Time optionTime, 419 const Period& swapTenor, 420 bool extrapolate) const { 421 checkSwapTenor(swapTenor, extrapolate); 422 checkRange(optionTime, extrapolate); 423 return smileSection(optionTime, swapLength(swapTenor)); 424 } 425 426 inline ext::shared_ptr<SmileSection> smileSection(const Period & optionTenor,Time swapLength,bool extrapolate) const427 SwaptionVolatilityStructure::smileSection(const Period& optionTenor, 428 Time swapLength, 429 bool extrapolate) const { 430 checkSwapTenor(swapLength, extrapolate); 431 Date optionDate = optionDateFromTenor(optionTenor); 432 checkRange(optionDate, extrapolate); 433 return smileSection(optionDate, swapLength); 434 } 435 436 inline ext::shared_ptr<SmileSection> smileSection(const Date & optionDate,Time swapLength,bool extrapolate) const437 SwaptionVolatilityStructure::smileSection(const Date& optionDate, 438 Time swapLength, 439 bool extrapolate) const { 440 checkSwapTenor(swapLength, extrapolate); 441 checkRange(optionDate, extrapolate); 442 return smileSection(timeFromReference(optionDate), swapLength); 443 } 444 445 inline ext::shared_ptr<SmileSection> smileSection(Time optionTime,Time swapLength,bool extrapolate) const446 SwaptionVolatilityStructure::smileSection(Time optionTime, 447 Time swapLength, 448 bool extrapolate) const { 449 checkSwapTenor(swapLength, extrapolate); 450 checkRange(optionTime, extrapolate); 451 return smileSectionImpl(optionTime, swapLength); 452 } 453 454 // 4. default implementation of Date-based xxxImpl methods 455 // relying on the equivalent Time-based methods 456 inline ext::shared_ptr<SmileSection> smileSectionImpl(const Date & optionDate,const Period & swapT) const457 SwaptionVolatilityStructure::smileSectionImpl(const Date& optionDate, 458 const Period& swapT) const { 459 return smileSectionImpl(timeFromReference(optionDate), 460 swapLength(swapT)); 461 } 462 463 inline Volatility volatilityImpl(const Date & optionDate,const Period & swapTenor,Rate strike) const464 SwaptionVolatilityStructure::volatilityImpl(const Date& optionDate, 465 const Period& swapTenor, 466 Rate strike) const { 467 return volatilityImpl(timeFromReference(optionDate), 468 swapLength(swapTenor), 469 strike); 470 } 471 472 inline Real shiftImpl(const Date & optionDate,const Period & swapTenor) const473 SwaptionVolatilityStructure::shiftImpl(const Date &optionDate, 474 const Period &swapTenor) const { 475 return shiftImpl(timeFromReference(optionDate), swapLength(swapTenor)); 476 } 477 shiftImpl(Time,Time) const478 inline Real SwaptionVolatilityStructure::shiftImpl(Time, Time) const { 479 QL_REQUIRE( 480 volatilityType() == ShiftedLognormal, 481 "shift parameter only makes sense for lognormal volatilities"); 482 return 0.0; 483 } 484 maxSwapLength() const485 inline Time SwaptionVolatilityStructure::maxSwapLength() const { 486 return swapLength(maxSwapTenor()); 487 } 488 489 } 490 491 #endif 492