Coverage Report

Created: 2025-09-04 07:11

/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