QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
zabrsmilesection.hpp
Go to the documentation of this file.
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
20/*! \file zabrsmilesection.hpp
21 \brief zabr smile section
22*/
23
24#ifndef quantlib_zabr_smile_section_hpp
25#define quantlib_zabr_smile_section_hpp
26
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 counter.
Black formula.
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
Real a_
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
Date d
#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
const VF_R b_
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.
Smile section base class.
Additional utilities for smile sections.
ZABR functions Reference: Andreasen, Huge: ZABR - Expansions for the masses, Preliminary Version,...