/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 |