Coverage Report

Created: 2026-06-08 06:47

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/termstructures/volatility/interpolatedsmilesection.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2006 Ferdinando Ametrano
5
 Copyright (C) 2006 François du Vignaud
6
 Copyright (C) 2015 Peter Caspers
7
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <https://www.quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
/*! \file interpolatedsmilesection.hpp
23
    \brief Interpolated smile section class
24
*/
25
26
#ifndef quantlib_interpolated_smile_section_hpp
27
#define quantlib_interpolated_smile_section_hpp
28
29
#include <ql/math/interpolations/linearinterpolation.hpp>
30
#include <ql/patterns/lazyobject.hpp>
31
#include <ql/quotes/simplequote.hpp>
32
#include <ql/termstructure.hpp>
33
#include <ql/termstructures/volatility/smilesection.hpp>
34
#include <ql/time/daycounters/actual365fixed.hpp>
35
#include <utility>
36
37
namespace QuantLib {
38
39
    template<class Interpolator>
40
    class InterpolatedSmileSection : public SmileSection,
41
                                     public LazyObject {
42
      public:
43
        InterpolatedSmileSection(Time expiryTime,
44
                                 std::vector<Rate> strikes,
45
                                 const std::vector<Handle<Quote> >& stdDevHandles,
46
                                 Handle<Quote> atmLevel,
47
                                 const Interpolator& interpolator = Interpolator(),
48
                                 const DayCounter& dc = Actual365Fixed(),
49
                                 VolatilityType type = ShiftedLognormal,
50
                                 Real shift = 0.0,
51
                                 bool flatStrikeExtrapolation = false);
52
        InterpolatedSmileSection(Time expiryTime,
53
                                 std::vector<Rate> strikes,
54
                                 const std::vector<Real>& stdDevs,
55
                                 Real atmLevel,
56
                                 const Interpolator& interpolator = Interpolator(),
57
                                 const DayCounter& dc = Actual365Fixed(),
58
                                 VolatilityType type = ShiftedLognormal,
59
                                 Real shift = 0.0,
60
                                 bool flatStrikeExtrapolation = false);
61
        InterpolatedSmileSection(const Date& d,
62
                                 std::vector<Rate> strikes,
63
                                 const std::vector<Handle<Quote> >& stdDevHandles,
64
                                 Handle<Quote> atmLevel,
65
                                 const DayCounter& dc = Actual365Fixed(),
66
                                 const Interpolator& interpolator = Interpolator(),
67
                                 const Date& referenceDate = Date(),
68
                                 VolatilityType type = ShiftedLognormal,
69
                                 Real shift = 0.0,
70
                                 bool flatStrikeExtrapolation = false);
71
        InterpolatedSmileSection(const Date& d,
72
                                 std::vector<Rate> strikes,
73
                                 const std::vector<Real>& stdDevs,
74
                                 Real atmLevel,
75
                                 const DayCounter& dc = Actual365Fixed(),
76
                                 const Interpolator& interpolator = Interpolator(),
77
                                 const Date& referenceDate = Date(),
78
                                 VolatilityType type = ShiftedLognormal,
79
                                 Real shift = 0.0,
80
                                 bool flatStrikeExtrapolation = false);
81
82
        void performCalculations() const override;
83
        Real varianceImpl(Rate strike) const override;
84
        Volatility volatilityImpl(Rate strike) const override;
85
0
        Real minStrike() const override { return strikes_.front(); }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::minStrike() const
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::minStrike() const
86
0
        Real maxStrike() const override { return strikes_.back(); }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::maxStrike() const
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::maxStrike() const
87
0
        Real atmLevel() const override { return atmLevel_->value(); }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::atmLevel() const
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::atmLevel() const
88
        void update() override;
89
90
      private:
91
        void checkStrikes();
92
93
        Real exerciseTimeSquareRoot_;
94
        std::vector<Rate> strikes_;
95
        std::vector<Handle<Quote> > stdDevHandles_;
96
        Handle<Quote> atmLevel_;
97
        mutable std::vector<Volatility> vols_;
98
        mutable Interpolation interpolation_;
99
        bool flatStrikeExtrapolation_;
100
    };
101
102
103
    template <class Interpolator>
104
    InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection(
105
        Time timeToExpiry,
106
        std::vector<Rate> strikes,
107
        const std::vector<Handle<Quote> >& stdDevHandles,
108
        Handle<Quote> atmLevel,
109
        const Interpolator& interpolator,
110
        const DayCounter& dc,
111
        const VolatilityType type,
112
        const Real shift,
113
        bool flatStrikeExtrapolation
114
    )
115
    : SmileSection(timeToExpiry, dc, type, shift),
116
      exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(std::move(strikes)),
117
      stdDevHandles_(stdDevHandles), atmLevel_(std::move(atmLevel)), vols_(stdDevHandles.size()),
118
      flatStrikeExtrapolation_(flatStrikeExtrapolation) {
119
        for (auto& stdDevHandle : stdDevHandles_)
120
            LazyObject::registerWith(stdDevHandle);
121
        LazyObject::registerWith(atmLevel_);
122
123
        checkStrikes();
124
        interpolation_ = interpolator.interpolate(strikes_.begin(),
125
                                                  strikes_.end(),
126
                                                  vols_.begin());
127
    }
128
129
    template <class Interpolator>
130
    InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection(
131
        Time timeToExpiry,
132
        std::vector<Rate> strikes,
133
        const std::vector<Real>& stdDevs,
134
        Real atmLevel,
135
        const Interpolator& interpolator,
136
        const DayCounter& dc,
137
        const VolatilityType type,
138
        const Real shift,
139
        bool flatStrikeExtrapolation
140
    )
141
0
    : SmileSection(timeToExpiry, dc, type, shift),
142
0
      exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(std::move(strikes)),
143
0
      stdDevHandles_(stdDevs.size()), vols_(stdDevs.size()),
144
0
      flatStrikeExtrapolation_(flatStrikeExtrapolation) {
145
        // fill dummy handles to allow generic handle-based
146
        // computations later on
147
0
        for (Size i=0; i<stdDevs.size(); ++i)
148
0
            stdDevHandles_[i] = Handle<Quote>(ext::shared_ptr<Quote>(new
149
0
                SimpleQuote(stdDevs[i])));
150
0
        atmLevel_ = Handle<Quote>
151
0
           (ext::shared_ptr<Quote>(new SimpleQuote(atmLevel)));
152
        
153
0
        checkStrikes();
154
0
        interpolation_ = interpolator.interpolate(strikes_.begin(),
155
0
                                                  strikes_.end(),
156
0
                                                  vols_.begin());
157
0
    }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::InterpolatedSmileSection(double, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> > const&, double, QuantLib::Linear const&, QuantLib::DayCounter const&, QuantLib::VolatilityType, double, bool)
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::InterpolatedSmileSection(double, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> > const&, double, QuantLib::Cubic const&, QuantLib::DayCounter const&, QuantLib::VolatilityType, double, bool)
158
159
    template <class Interpolator>
160
    InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection(
161
        const Date& d,
162
        std::vector<Rate> strikes,
163
        const std::vector<Handle<Quote> >& stdDevHandles,
164
        Handle<Quote> atmLevel,
165
        const DayCounter& dc,
166
        const Interpolator& interpolator,
167
        const Date& referenceDate,
168
        const VolatilityType type,
169
        const Real shift,
170
        bool flatStrikeExtrapolation
171
    )
172
    : SmileSection(d, dc, referenceDate, type, shift),
173
      exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(std::move(strikes)),
174
      stdDevHandles_(stdDevHandles), atmLevel_(std::move(atmLevel)), vols_(stdDevHandles.size()),
175
      flatStrikeExtrapolation_(flatStrikeExtrapolation) {
176
        for (auto& stdDevHandle : stdDevHandles_)
177
            LazyObject::registerWith(stdDevHandle);
178
        LazyObject::registerWith(atmLevel_);
179
        
180
        checkStrikes();
181
        interpolation_ = interpolator.interpolate(strikes_.begin(),
182
                                                  strikes_.end(),
183
                                                  vols_.begin());
184
    }
185
186
    template <class Interpolator>
187
    InterpolatedSmileSection<Interpolator>::InterpolatedSmileSection(
188
        const Date& d,
189
        std::vector<Rate> strikes,
190
        const std::vector<Real>& stdDevs,
191
        Real atmLevel,
192
        const DayCounter& dc,
193
        const Interpolator& interpolator,
194
        const Date& referenceDate,
195
        const VolatilityType type,
196
        const Real shift,
197
        bool flatStrikeExtrapolation
198
    )
199
0
    : SmileSection(d, dc, referenceDate, type, shift),
200
0
      exerciseTimeSquareRoot_(std::sqrt(exerciseTime())), strikes_(std::move(strikes)),
201
0
      stdDevHandles_(stdDevs.size()), vols_(stdDevs.size()),
202
0
      flatStrikeExtrapolation_(flatStrikeExtrapolation) {
203
        //fill dummy handles to allow generic handle-based
204
        // computations later on
205
0
        for (Size i=0; i<stdDevs.size(); ++i)
206
0
            stdDevHandles_[i] = Handle<Quote>(ext::shared_ptr<Quote>(new
207
0
                SimpleQuote(stdDevs[i])));
208
0
        atmLevel_ = Handle<Quote>
209
0
           (ext::shared_ptr<Quote>(new SimpleQuote(atmLevel)));
210
        
211
0
        checkStrikes();
212
0
        interpolation_ = interpolator.interpolate(strikes_.begin(),
213
0
                                                  strikes_.end(),
214
0
                                                  vols_.begin());
215
0
    }
216
217
218
    template <class Interpolator>
219
    inline void InterpolatedSmileSection<Interpolator>::performCalculations()
220
0
                                                                      const {
221
0
        for (Size i=0; i<stdDevHandles_.size(); ++i)
222
0
            vols_[i] = stdDevHandles_[i]->value()/exerciseTimeSquareRoot_;
223
0
        interpolation_.update();
224
0
    }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::performCalculations() const
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::performCalculations() const
225
226
    #ifndef __DOXYGEN__
227
    template <class Interpolator>
228
0
    Real InterpolatedSmileSection<Interpolator>::varianceImpl(Real strike) const {
229
0
        calculate();
230
0
        Real v = volatilityImpl(strike);
231
0
        return v * v * exerciseTime();
232
0
    }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::varianceImpl(double) const
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::varianceImpl(double) const
233
234
    template <class Interpolator>
235
0
    Real InterpolatedSmileSection<Interpolator>::volatilityImpl(Real strike) const {
236
0
        calculate();
237
        
238
0
        if (flatStrikeExtrapolation_) {
239
0
            if (strike < minStrike()) {
240
0
                return interpolation_(minStrike(), true);                
241
0
            } else if (strike > maxStrike()) {
242
0
                return interpolation_(maxStrike(), true);
243
0
            }
244
0
        }
245
246
0
        return std::max(interpolation_(strike, true), 0.0);
247
0
    }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::volatilityImpl(double) const
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::volatilityImpl(double) const
248
249
    template <class Interpolator>
250
0
    void InterpolatedSmileSection<Interpolator>::update() {
251
0
        LazyObject::update();
252
0
        SmileSection::update();
253
0
    }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::update()
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::update()
254
    #endif
255
256
    template <class Interpolator>
257
0
    void InterpolatedSmileSection<Interpolator>::checkStrikes() {
258
        QL_REQUIRE(std::is_sorted(strikes_.begin(), strikes_.end()), 
259
0
                    "Strikes have to be sorted in ascending order");
260
0
    }
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Linear>::checkStrikes()
Unexecuted instantiation: QuantLib::InterpolatedSmileSection<QuantLib::Cubic>::checkStrikes()
261
262
}
263
264
#endif