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