/src/quantlib/ql/termstructures/volatility/swaption/swaptionvolstructure.hpp
Line | Count | Source (jump to first uncovered line) |
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 | | <https://www.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 | | //@} |
65 | 0 | ~SwaptionVolatilityStructure() override = default; |
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 |
189 | 0 | virtual VolatilityType volatilityType() const { |
190 | 0 | return ShiftedLognormal; |
191 | 0 | } |
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 |
225 | | SwaptionVolatilityStructure::volatility(const Period& optionTenor, |
226 | | const Period& swapTenor, |
227 | | Rate strike, |
228 | 0 | bool extrapolate) const { |
229 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
230 | 0 | return volatility(optionDate, swapTenor, strike, extrapolate); |
231 | 0 | } |
232 | | |
233 | | inline Volatility |
234 | | SwaptionVolatilityStructure::volatility(const Period& optionTenor, |
235 | | Time swapLength, |
236 | | Rate strike, |
237 | 0 | bool extrapolate) const { |
238 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
239 | 0 | return volatility(optionDate, swapLength, strike, extrapolate); |
240 | 0 | } |
241 | | |
242 | | inline |
243 | | Real SwaptionVolatilityStructure::blackVariance(const Period& optionTenor, |
244 | | const Period& swapTenor, |
245 | | Rate strike, |
246 | 0 | bool extrapolate) const { |
247 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
248 | 0 | return blackVariance(optionDate, swapTenor, strike, extrapolate); |
249 | 0 | } |
250 | | |
251 | | inline |
252 | | Real SwaptionVolatilityStructure::blackVariance(const Period& optionTenor, |
253 | | Time swapLength, |
254 | | Rate strike, |
255 | 0 | bool extrapolate) const { |
256 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
257 | 0 | return blackVariance(optionDate, swapLength, strike, extrapolate); |
258 | 0 | } |
259 | | |
260 | | inline |
261 | | Real SwaptionVolatilityStructure::shift(const Period& optionTenor, |
262 | | const Period& swapTenor, |
263 | 0 | bool extrapolate) const { |
264 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
265 | 0 | return shift(optionDate, swapTenor, extrapolate); |
266 | 0 | } |
267 | | |
268 | | inline |
269 | | Real SwaptionVolatilityStructure::shift(const Period& optionTenor, |
270 | | Time swapLength, |
271 | 0 | bool extrapolate) const { |
272 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
273 | 0 | return shift(optionDate, swapLength, extrapolate); |
274 | 0 | } |
275 | | |
276 | | inline ext::shared_ptr<SmileSection> |
277 | | SwaptionVolatilityStructure::smileSection(const Period& optionTenor, |
278 | | const Period& swapTenor, |
279 | 0 | bool extrapolate) const { |
280 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
281 | 0 | return smileSection(optionDate, swapTenor, extrapolate); |
282 | 0 | } |
283 | | |
284 | | // 2. blackVariance methods rely on volatility methods |
285 | | inline |
286 | | Real SwaptionVolatilityStructure::blackVariance(const Date& optionDate, |
287 | | const Period& swapTenor, |
288 | | Rate strike, |
289 | 0 | bool extrapolate) const { |
290 | 0 | Volatility v = volatility(optionDate, swapTenor, strike, extrapolate); |
291 | 0 | Time optionTime = timeFromReference(optionDate); |
292 | 0 | return v*v*optionTime; |
293 | 0 | } |
294 | | |
295 | | inline |
296 | | Real SwaptionVolatilityStructure::blackVariance(Time optionTime, |
297 | | const Period& swapTenor, |
298 | | Rate strike, |
299 | 0 | bool extrapolate) const { |
300 | 0 | Volatility v = volatility(optionTime, swapTenor, strike, extrapolate); |
301 | 0 | return v*v*optionTime; |
302 | 0 | } |
303 | | |
304 | | inline |
305 | | Real SwaptionVolatilityStructure::blackVariance(const Date& optionDate, |
306 | | Time swapLength, |
307 | | Rate strike, |
308 | 0 | bool extrapolate) const { |
309 | 0 | Volatility v = volatility(optionDate, swapLength, strike, extrapolate); |
310 | 0 | Time optionTime = timeFromReference(optionDate); |
311 | 0 | return v*v*optionTime; |
312 | 0 | } |
313 | | |
314 | | inline |
315 | | Real SwaptionVolatilityStructure::blackVariance(Time optionTime, |
316 | | Time swapLength, |
317 | | Rate strike, |
318 | 0 | bool extrapolate) const { |
319 | 0 | Volatility v = volatility(optionTime, swapLength, strike, extrapolate); |
320 | 0 | return v*v*optionTime; |
321 | 0 | } |
322 | | |
323 | | // 3. relying on xxxImpl methods |
324 | | inline Volatility |
325 | | SwaptionVolatilityStructure::volatility(const Date& optionDate, |
326 | | const Period& swapTenor, |
327 | | Rate strike, |
328 | 0 | bool extrapolate) const { |
329 | 0 | checkSwapTenor(swapTenor, extrapolate); |
330 | 0 | checkRange(optionDate, extrapolate); |
331 | 0 | checkStrike(strike, extrapolate); |
332 | 0 | return volatilityImpl(optionDate, swapTenor, strike); |
333 | 0 | } |
334 | | |
335 | | inline Volatility |
336 | | SwaptionVolatilityStructure::volatility(const Date& optionDate, |
337 | | Time swapLength, |
338 | | Rate strike, |
339 | 0 | bool extrapolate) const { |
340 | 0 | checkSwapTenor(swapLength, extrapolate); |
341 | 0 | checkRange(optionDate, extrapolate); |
342 | 0 | checkStrike(strike, extrapolate); |
343 | 0 | Time optionTime = timeFromReference(optionDate); |
344 | 0 | return volatilityImpl(optionTime, swapLength, strike); |
345 | 0 | } |
346 | | |
347 | | inline Volatility |
348 | | SwaptionVolatilityStructure::volatility(Time optionTime, |
349 | | const Period& swapTenor, |
350 | | Rate strike, |
351 | 0 | bool extrapolate) const { |
352 | 0 | checkSwapTenor(swapTenor, extrapolate); |
353 | 0 | checkRange(optionTime, extrapolate); |
354 | 0 | checkStrike(strike, extrapolate); |
355 | 0 | Time length = swapLength(swapTenor); |
356 | 0 | return volatilityImpl(optionTime, length, strike); |
357 | 0 | } |
358 | | |
359 | | inline Volatility |
360 | | SwaptionVolatilityStructure::volatility(Time optionTime, |
361 | | Time swapLength, |
362 | | Rate strike, |
363 | 0 | bool extrapolate) const { |
364 | 0 | checkSwapTenor(swapLength, extrapolate); |
365 | 0 | checkRange(optionTime, extrapolate); |
366 | 0 | checkStrike(strike, extrapolate); |
367 | 0 | return volatilityImpl(optionTime, swapLength, strike); |
368 | 0 | } |
369 | | |
370 | | inline Real |
371 | | SwaptionVolatilityStructure::shift(const Date& optionDate, |
372 | | const Period& swapTenor, |
373 | 0 | bool extrapolate) const { |
374 | 0 | checkSwapTenor(swapTenor, extrapolate); |
375 | 0 | checkRange(optionDate, extrapolate); |
376 | 0 | return shiftImpl(optionDate, swapTenor); |
377 | 0 | } |
378 | | |
379 | | inline Real |
380 | | SwaptionVolatilityStructure::shift(const Date& optionDate, |
381 | | Time swapLength, |
382 | 0 | bool extrapolate) const { |
383 | 0 | checkSwapTenor(swapLength, extrapolate); |
384 | 0 | checkRange(optionDate, extrapolate); |
385 | 0 | Time optionTime = timeFromReference(optionDate); |
386 | 0 | return shiftImpl(optionTime, swapLength); |
387 | 0 | } |
388 | | |
389 | | inline Real |
390 | | SwaptionVolatilityStructure::shift(Time optionTime, |
391 | | const Period& swapTenor, |
392 | 0 | bool extrapolate) const { |
393 | 0 | checkSwapTenor(swapTenor, extrapolate); |
394 | 0 | checkRange(optionTime, extrapolate); |
395 | 0 | Time length = swapLength(swapTenor); |
396 | 0 | return shiftImpl(optionTime, length); |
397 | 0 | } |
398 | | |
399 | | inline Real |
400 | | SwaptionVolatilityStructure::shift(Time optionTime, |
401 | | Time swapLength, |
402 | 0 | bool extrapolate) const { |
403 | 0 | checkSwapTenor(swapLength, extrapolate); |
404 | 0 | checkRange(optionTime, extrapolate); |
405 | 0 | return shiftImpl(optionTime, swapLength); |
406 | 0 | } |
407 | | |
408 | | inline ext::shared_ptr<SmileSection> |
409 | | SwaptionVolatilityStructure::smileSection(const Date& optionDate, |
410 | | const Period& swapTenor, |
411 | 0 | bool extrapolate) const { |
412 | 0 | checkSwapTenor(swapTenor, extrapolate); |
413 | 0 | checkRange(optionDate, extrapolate); |
414 | 0 | return smileSectionImpl(optionDate, swapTenor); |
415 | 0 | } |
416 | | |
417 | | inline ext::shared_ptr<SmileSection> |
418 | | SwaptionVolatilityStructure::smileSection(Time optionTime, |
419 | | const Period& swapTenor, |
420 | 0 | bool extrapolate) const { |
421 | 0 | checkSwapTenor(swapTenor, extrapolate); |
422 | 0 | checkRange(optionTime, extrapolate); |
423 | 0 | return smileSection(optionTime, swapLength(swapTenor)); |
424 | 0 | } |
425 | | |
426 | | inline ext::shared_ptr<SmileSection> |
427 | | SwaptionVolatilityStructure::smileSection(const Period& optionTenor, |
428 | | Time swapLength, |
429 | 0 | bool extrapolate) const { |
430 | 0 | checkSwapTenor(swapLength, extrapolate); |
431 | 0 | Date optionDate = optionDateFromTenor(optionTenor); |
432 | 0 | checkRange(optionDate, extrapolate); |
433 | 0 | return smileSection(optionDate, swapLength); |
434 | 0 | } |
435 | | |
436 | | inline ext::shared_ptr<SmileSection> |
437 | | SwaptionVolatilityStructure::smileSection(const Date& optionDate, |
438 | | Time swapLength, |
439 | 0 | bool extrapolate) const { |
440 | 0 | checkSwapTenor(swapLength, extrapolate); |
441 | 0 | checkRange(optionDate, extrapolate); |
442 | 0 | return smileSection(timeFromReference(optionDate), swapLength); |
443 | 0 | } |
444 | | |
445 | | inline ext::shared_ptr<SmileSection> |
446 | | SwaptionVolatilityStructure::smileSection(Time optionTime, |
447 | | Time swapLength, |
448 | 0 | bool extrapolate) const { |
449 | 0 | checkSwapTenor(swapLength, extrapolate); |
450 | 0 | checkRange(optionTime, extrapolate); |
451 | 0 | return smileSectionImpl(optionTime, swapLength); |
452 | 0 | } |
453 | | |
454 | | // 4. default implementation of Date-based xxxImpl methods |
455 | | // relying on the equivalent Time-based methods |
456 | | inline ext::shared_ptr<SmileSection> |
457 | | SwaptionVolatilityStructure::smileSectionImpl(const Date& optionDate, |
458 | 0 | const Period& swapT) const { |
459 | 0 | return smileSectionImpl(timeFromReference(optionDate), |
460 | 0 | swapLength(swapT)); |
461 | 0 | } |
462 | | |
463 | | inline Volatility |
464 | | SwaptionVolatilityStructure::volatilityImpl(const Date& optionDate, |
465 | | const Period& swapTenor, |
466 | 0 | Rate strike) const { |
467 | 0 | return volatilityImpl(timeFromReference(optionDate), |
468 | 0 | swapLength(swapTenor), |
469 | 0 | strike); |
470 | 0 | } |
471 | | |
472 | | inline Real |
473 | | SwaptionVolatilityStructure::shiftImpl(const Date &optionDate, |
474 | 0 | const Period &swapTenor) const { |
475 | 0 | return shiftImpl(timeFromReference(optionDate), swapLength(swapTenor)); |
476 | 0 | } |
477 | | |
478 | 0 | inline Real SwaptionVolatilityStructure::shiftImpl(Time, Time) const { |
479 | 0 | QL_REQUIRE( |
480 | 0 | volatilityType() == ShiftedLognormal, |
481 | 0 | "shift parameter only makes sense for lognormal volatilities"); |
482 | 0 | return 0.0; |
483 | 0 | } |
484 | | |
485 | 0 | inline Time SwaptionVolatilityStructure::maxSwapLength() const { |
486 | 0 | return swapLength(maxSwapTenor()); |
487 | 0 | } |
488 | | |
489 | | } |
490 | | |
491 | | #endif |