QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
zabrsmilesection.hpp
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2014 Peter Caspers
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
24#ifndef quantlib_zabr_smile_section_hpp
25#define quantlib_zabr_smile_section_hpp
26
27#include <ql/experimental/volatility/zabr.hpp>
28#include <ql/pricingengines/blackformula.hpp>
29#include <ql/termstructures/volatility/smilesection.hpp>
30#include <ql/termstructures/volatility/smilesectionutils.hpp>
31#include <ql/time/daycounters/actual365fixed.hpp>
32#include <utility>
33#include <vector>
34
35using std::exp;
36
37namespace QuantLib {
38
39// Evaluation Tags
40
44struct ZabrFullFd {};
45
46template <typename Evaluation> class ZabrSmileSection : public SmileSection {
47 public:
48 ZabrSmileSection(Time timeToExpiry,
49 Rate forward,
50 std::vector<Real> zabrParameters,
51 const std::vector<Real>& moneyness = std::vector<Real>(),
52 Size fdRefinement = 5);
53 ZabrSmileSection(const Date& d,
54 Rate forward,
55 std::vector<Real> zabrParameters,
56 const DayCounter& dc = Actual365Fixed(),
57 const std::vector<Real>& moneyness = std::vector<Real>(),
58 Size fdRefinement = 5);
59
60 Real minStrike() const override { return 0.0; }
61 Real maxStrike() const override { return QL_MAX_REAL; }
62 Real atmLevel() const override { return model_->forward(); }
63 Real
64 optionPrice(Rate strike, Option::Type type = Option::Call, Real discount = 1.0) const override {
65 return optionPrice(strike, type, discount, Evaluation());
66 }
67
68 ext::shared_ptr<ZabrModel> model() { return model_; }
69
70 protected:
71 Volatility volatilityImpl(Rate strike) const override {
72 return volatilityImpl(strike, Evaluation());
73 }
74
75 private:
76 void init(const std::vector<Real> &moneyness) {
77 init(moneyness, Evaluation());
78 init2(Evaluation());
79 init3(Evaluation());
80 }
81 void init(const std::vector<Real> &moneyness, ZabrShortMaturityLognormal);
82 void init(const std::vector<Real> &moneyness, ZabrShortMaturityNormal);
83 void init(const std::vector<Real> &moneyness, ZabrLocalVolatility);
84 void init(const std::vector<Real> &moneyness, ZabrFullFd);
88 void init2(ZabrFullFd);
92 void init3(ZabrFullFd);
93 Real optionPrice(Rate strike, Option::Type type, Real discount,
95 Real optionPrice(Rate strike, Option::Type type, Real discount,
97 Real optionPrice(Rate strike, Option::Type type, Real discount,
99 Real optionPrice(Rate strike, Option::Type type, Real discount,
100 ZabrFullFd) const;
105 ext::shared_ptr<ZabrModel> model_;
106 Evaluation evaluation_;
108 std::vector<Real> params_;
110 std::vector<Real> strikes_, callPrices_;
111 ext::shared_ptr<Interpolation> callPriceFct_;
113};
114
115template <typename Evaluation>
117 Rate forward,
118 std::vector<Real> zabrParams,
119 const std::vector<Real>& moneyness,
120 const Size fdRefinement)
121: SmileSection(timeToExpiry, DayCounter()), forward_(forward), params_(std::move(zabrParams)),
122 fdRefinement_(fdRefinement) {
123 init(moneyness);
124}
125
126template <typename Evaluation>
128 Rate forward,
129 std::vector<Real> zabrParams,
130 const DayCounter& dc,
131 const std::vector<Real>& moneyness,
132 const Size fdRefinement)
133: SmileSection(d, dc, Date()), forward_(forward), params_(std::move(zabrParams)),
134 fdRefinement_(fdRefinement) {
135 init(moneyness);
136}
137
138template <typename Evaluation>
139void ZabrSmileSection<Evaluation>::init(const std::vector<Real> &,
141
142 model_ = ext::make_shared<ZabrModel>(
143 exerciseTime(), forward_, params_[0], params_[1],
144 params_[2], params_[3], params_[4]);
145}
146
147template <typename Evaluation>
148void ZabrSmileSection<Evaluation>::init(const std::vector<Real> &a,
151}
152
153template <typename Evaluation>
154void ZabrSmileSection<Evaluation>::init(const std::vector<Real> &moneyness,
156
157 QL_REQUIRE(params_.size() >= 5,
158 "zabr expects 5 parameters (alpha,beta,nu,rho,gamma) but ("
159 << params_.size() << ") given");
160
161 model_ = ext::make_shared<ZabrModel>(
162 exerciseTime(), forward_, params_[0], params_[1],
163 params_[2], params_[3], params_[4]);
164
165 // set up strike grid for local vol or full fd flavour of this section
166 // this is shared with SmileSectionUtils - unify later ?
167 static const Real defaultMoney[] = {
168 0.0, 0.01, 0.05, 0.10, 0.25, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90,
169 1.0, 1.25, 1.5, 1.75, 2.0, 5.0, 7.5, 10.0, 15.0, 20.0};
170 std::vector<Real> tmp;
171 if (moneyness.empty())
172 tmp = std::vector<Real>(defaultMoney, defaultMoney + 21);
173 else
174 tmp = std::vector<Real>(moneyness);
175
176 strikes_.clear(); // should not be necessary, anyway
177 Real lastF = 0.0;
178 bool firstStrike = true;
179 for (Real i : tmp) {
180 Real f = i * forward_;
181 if (f > 0.0) {
182 if (!firstStrike) {
183 for (Size j = 1; j <= fdRefinement_; ++j) {
184 strikes_.push_back(lastF +
185 ((double)j) * (f - lastF) /
186 (fdRefinement_ + 1));
187 }
188 }
189 firstStrike = false;
190 lastF = f;
191 strikes_.push_back(f);
192 }
193 }
194}
195
196template <typename Evaluation>
197void ZabrSmileSection<Evaluation>::init(const std::vector<Real> &moneyness,
198 ZabrFullFd) {
199 init(moneyness, ZabrLocalVolatility());
200}
201
202template <typename Evaluation>
204
205template <typename Evaluation>
207
208template <typename Evaluation>
210 callPrices_ = model_->fdPrice(strikes_);
211}
212
213template <typename Evaluation>
215 callPrices_.resize(strikes_.size());
216#pragma omp parallel for
217 for (long i = 0; i < (long)strikes_.size(); i++) {
218 callPrices_[i] = model_->fullFdPrice(strikes_[i]);
219 }
220}
221
222template <typename Evaluation>
224
225template <typename Evaluation>
227
228template <typename Evaluation>
230 strikes_.insert(strikes_.begin(), 0.0);
231 callPrices_.insert(callPrices_.begin(), forward_);
232
233 callPriceFct_ = ext::shared_ptr<Interpolation>(new CubicInterpolation(
234 strikes_.begin(), strikes_.end(), callPrices_.begin(),
237 // callPriceFct_ =
238 // ext::shared_ptr<Interpolation>(new LinearInterpolation(
239 // strikes_.begin(), strikes_.end(), callPrices_.begin()));
240
241 callPriceFct_->enableExtrapolation();
242
243 // on the right side we extrapolate exponetially (because spline
244 // does not make sense)
245 // we precompute the necessary parameters here
246 static const Real eps = 1E-5; // gap for first derivative computation
247
248 Real c0 = (*callPriceFct_)(strikes_.back());
249 Real c0p = ((*callPriceFct_)(strikes_.back() - eps) - c0) / eps;
250
251 a_ = c0p / c0;
252 b_ = std::log(c0) + a_ * strikes_.back();
253}
254
255template <typename Evaluation>
257 init3(ZabrLocalVolatility());
258}
259
260template <typename Evaluation>
261Real
263 Real discount,
265 return SmileSection::optionPrice(strike, type, discount);
266}
267
268template <typename Evaluation>
270 Real discount,
273 type, strike, forward_,
274 model_->normalVolatility(strike) * std::sqrt(exerciseTime()), discount);
275}
276
277template <typename Evaluation>
279 Real discount,
280 ZabrLocalVolatility) const {
281 Real call = strike <= strikes_.back() ? (*callPriceFct_)(strike)
282 : exp(-a_ * strike + b_);
283 if (type == Option::Call)
284 return call * discount;
285 else
286 return (call - (forward_ - strike)) * discount;
287}
288
289template <typename Evaluation>
291 Real discount,
292 ZabrFullFd) const {
293 return optionPrice(strike, type, discount, ZabrLocalVolatility());
294}
295
296template <typename Evaluation>
297Real
300 strike = std::max(1E-6, strike);
301 return model_->lognormalVolatility(strike);
302}
303
304template <typename Evaluation>
305Real
308 Real impliedVol = 0.0;
309 try {
310 Option::Type type;
311 if (strike >= model_->forward())
312 type = Option::Call;
313 else
314 type = Option::Put;
315 impliedVol =
316 blackFormulaImpliedStdDev(type, strike, model_->forward(),
317 optionPrice(strike, type, 1.0), 1.0) /
318 std::sqrt(exerciseTime());
319 } catch (...) {
320 }
321 return impliedVol;
322}
323
324template <typename Evaluation>
326 ZabrLocalVolatility) const {
327 return volatilityImpl(strike, ZabrShortMaturityNormal());
328}
329
330template <typename Evaluation>
332 ZabrFullFd) const {
333 return volatilityImpl(strike, ZabrShortMaturityNormal());
334}
335}
336
337#endif
Actual/365 (Fixed) day count convention.
Cubic interpolation between discrete points.
@ SecondDerivative
Match value of second derivative at end.
Concrete date class.
Definition: date.hpp:125
day counter class
Definition: daycounter.hpp:44
interest rate volatility smile section
virtual Real optionPrice(Rate strike, Option::Type type=Option::Call, Real discount=1.0) const
std::vector< Real > callPrices_
ext::shared_ptr< ZabrModel > model()
void init(const std::vector< Real > &moneyness)
Real atmLevel() const override
std::vector< Real > strikes_
void init3(ZabrShortMaturityLognormal)
void init2(ZabrShortMaturityLognormal)
ext::shared_ptr< ZabrModel > model_
Real minStrike() const override
ext::shared_ptr< Interpolation > callPriceFct_
ZabrSmileSection(Time timeToExpiry, Rate forward, std::vector< Real > zabrParameters, const std::vector< Real > &moneyness=std::vector< Real >(), Size fdRefinement=5)
Volatility volatilityImpl(Rate strike) const override
Real optionPrice(Rate strike, Option::Type type=Option::Call, Real discount=1.0) const override
Real maxStrike() const override
#define QL_MAX_REAL
Definition: qldefines.hpp:176
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real Volatility
volatility
Definition: types.hpp:78
Real Rate
interest rates
Definition: types.hpp:70
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
Real bachelierBlackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount)
Real blackFormulaImpliedStdDev(Option::Type optionType, Real strike, Real forward, Real blackPrice, Real discount, Real displacement, Real guess, Real accuracy, Natural maxIterations)
STL namespace.