QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
sviinterpolation.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_svi_interpolation_hpp
25#define quantlib_svi_interpolation_hpp
26
27#include <ql/experimental/volatility/svismilesection.hpp>
28#include <ql/math/interpolations/xabrinterpolation.hpp>
29#include <utility>
30
31namespace QuantLib {
32
33namespace detail {
34
35inline void checkSviParameters(const Real a, const Real b, const Real sigma,
36 const Real rho, const Real m, const Time tte) {
37 QL_REQUIRE(b >= 0.0, "b (" << b << ") must be non negative");
38 QL_REQUIRE(std::fabs(rho) < 1.0, "rho (" << rho << ") must be in (-1,1)");
39 QL_REQUIRE(sigma > 0.0, "sigma (" << sigma << ") must be positive");
40 QL_REQUIRE(a + b * sigma * std::sqrt(1.0 - rho * rho) >= 0.0,
41 "a + b sigma sqrt(1-rho^2) (a=" << a << ", b=" << b << ", sigma="
42 << sigma << ", rho=" << rho
43 << ") must be non negative");
44 QL_REQUIRE(b * (1.0 + std::fabs(rho)) <= 4.0,
45 "b(1+|rho|) must be less than or equal to 4, (b=" << b << ", rho=" << rho << ")");
46
47}
48
49inline Real sviTotalVariance(const Real a, const Real b, const Real sigma,
50 const Real rho, const Real m, const Real k) {
51 return a +
52 b * (rho * (k - m) + std::sqrt((k - m) * (k - m) + sigma * sigma));
53}
54
56
57struct SviSpecs {
58 Size dimension() { return 5; }
59 void defaultValues(std::vector<Real> &params,
60 std::vector<bool> &paramIsFixed, const Real &forward,
61 const Real expiryTime,
62 const std::vector<Real> &addParams) {
63 if (params[2] == Null<Real>())
64 params[2] = 0.1;
65 if (params[3] == Null<Real>())
66 params[3] = -0.4;
67 if (params[4] == Null<Real>())
68 params[4] = 0.0;
69 if (params[1] == Null<Real>())
70 params[1] = 2.0 / (1.0 + std::fabs(params[3]));
71 if (params[0] == Null<Real>()) {
72 params[0] = std::max(
73 0.20 * 0.20 * expiryTime -
74 params[1] * (params[3] * (-params[4]) +
75 std::sqrt((-params[4]) * (-params[4]) +
76 params[2] * params[2])),
77 -params[1] * params[2] *
78 std::sqrt(1.0 - params[3] * params[3]) + eps1());
79 }
80 }
81 void guess(Array &values, const std::vector<bool> &paramIsFixed,
82 const Real &forward, const Real expiryTime,
83 const std::vector<Real> &r, const std::vector<Real> &addParams) {
84 Size j = 0;
85 if (!paramIsFixed[2])
86 values[2] = r[j++] + eps1();
87 if (!paramIsFixed[3])
88 values[3] = (2.0 * r[j++] - 1.0) * eps2();
89 if (!paramIsFixed[4])
90 values[4] = (2.0 * r[j++] - 1.0);
91 if (!paramIsFixed[1])
92 values[1] = r[j++] * 4.0 / (1.0 + std::fabs(values[3])) * eps2();
93 if (!paramIsFixed[0])
94 values[0] = r[j++] * expiryTime -
95 eps2() * (values[1] * values[2] *
96 std::sqrt(1.0 - values[3] * values[3]));
97 }
98 Array inverse(const Array &y, const std::vector<bool> &,
99 const std::vector<Real> &, const Real) {
100 Array x(5);
101 x[2] = std::sqrt(y[2] - eps1());
102 x[3] = std::asin(y[3] / eps2());
103 x[4] = y[4];
104 x[1] = std::tan(y[1] / 4.0 * (1.0 + std::fabs(y[3])) / eps2() * M_PI -
105 M_PI / 2.0);
106 x[0] = std::sqrt(y[0] - eps1() +
107 y[1] * y[2] * std::sqrt(1.0 - y[3] * y[3]));
108 return x;
109 }
110 Real eps1() { return 0.000001; }
111 Real eps2() { return 0.999999; }
112 Array direct(const Array &x, const std::vector<bool> &paramIsFixed,
113 const std::vector<Real> &params, const Real forward) {
114 Array y(5);
115 y[2] = x[2] * x[2] + eps1();
116 y[3] = std::sin(x[3]) * eps2();
117 y[4] = x[4];
118 if (paramIsFixed[1])
119 y[1] = params[1];
120 else
121 y[1] = (std::atan(x[1]) + M_PI / 2.0) / M_PI * eps2() * 4.0 /
122 (1.0 + std::fabs(y[3]));
123 if (paramIsFixed[0])
124 y[0] = params[0];
125 else
126 y[0] = eps1() + x[0] * x[0] -
127 y[1] * y[2] * std::sqrt(1.0 - y[3] * y[3]);
128 return y;
129 }
130 Real weight(const Real strike, const Real forward, const Real stdDev,
131 const std::vector<Real> &addParams) {
132 return blackFormulaStdDevDerivative(strike, forward, stdDev, 1.0);
133 }
135 ext::shared_ptr<type> instance(const Time t, const Real &forward,
136 const std::vector<Real> &params,
137 const std::vector<Real> &addParams) {
138 return ext::make_shared<type>(t, forward, params);
139 }
140};
141}
142
145 public:
146 template <class I1, class I2>
147 SviInterpolation(const I1 &xBegin, // x = strikes
148 const I1 &xEnd,
149 const I2 &yBegin, // y = volatilities
150 Time t, // option expiry
151 const Real &forward, Real a, Real b, Real sigma, Real rho,
152 Real m, bool aIsFixed, bool bIsFixed, bool sigmaIsFixed,
153 bool rhoIsFixed, bool mIsFixed, bool vegaWeighted = true,
154 const ext::shared_ptr<EndCriteria> &endCriteria =
155 ext::shared_ptr<EndCriteria>(),
156 const ext::shared_ptr<OptimizationMethod> &optMethod =
157 ext::shared_ptr<OptimizationMethod>(),
158 const Real errorAccept = 0.0020,
159 const bool useMaxError = false,
160 const Size maxGuesses = 50) {
161
162 impl_ = ext::shared_ptr<Interpolation::Impl>(
164 xBegin, xEnd, yBegin, t, forward,
165 {a, b, sigma, rho, m},
166 {aIsFixed, bIsFixed, sigmaIsFixed, rhoIsFixed, mIsFixed},
167 vegaWeighted, endCriteria, optMethod, errorAccept, useMaxError,
168 maxGuesses));
169 }
170 Real expiry() const { return coeffs().t_; }
171 Real forward() const { return coeffs().forward_; }
172 Real a() const { return coeffs().params_[0]; }
173 Real b() const { return coeffs().params_[1]; }
174 Real sigma() const { return coeffs().params_[2]; }
175 Real rho() const { return coeffs().params_[3]; }
176 Real m() const { return coeffs().params_[4]; }
177 Real rmsError() const { return coeffs().error_; }
178 Real maxError() const { return coeffs().maxError_; }
179 const std::vector<Real> &interpolationWeights() const {
180 return coeffs().weights_;
181 }
182 EndCriteria::Type endCriteria() { return coeffs().XABREndCriteria_; }
183
184 private:
186 return *dynamic_cast<detail::XABRCoeffHolder<detail::SviSpecs>*>(impl_.get());
187 }
188};
189
191class Svi {
192 public:
194 Real forward,
195 Real a,
196 Real b,
197 Real sigma,
198 Real rho,
199 Real m,
200 bool aIsFixed,
201 bool bIsFixed,
202 bool sigmaIsFixed,
203 bool rhoIsFixed,
204 bool mIsFixed,
205 bool vegaWeighted = false,
206 ext::shared_ptr<EndCriteria> endCriteria = ext::shared_ptr<EndCriteria>(),
207 ext::shared_ptr<OptimizationMethod> optMethod = ext::shared_ptr<OptimizationMethod>(),
208 const Real errorAccept = 0.0020,
209 const bool useMaxError = false,
210 const Size maxGuesses = 50)
211 : t_(t), forward_(forward), a_(a), b_(b), sigma_(sigma), rho_(rho), m_(m), aIsFixed_(aIsFixed),
212 bIsFixed_(bIsFixed), sigmaIsFixed_(sigmaIsFixed), rhoIsFixed_(rhoIsFixed),
213 mIsFixed_(mIsFixed), vegaWeighted_(vegaWeighted), endCriteria_(std::move(endCriteria)),
214 optMethod_(std::move(optMethod)), errorAccept_(errorAccept), useMaxError_(useMaxError),
215 maxGuesses_(maxGuesses) {}
216 template <class I1, class I2>
217 Interpolation interpolate(const I1 &xBegin, const I1 &xEnd,
218 const I2 &yBegin) const {
219 return SviInterpolation(xBegin, xEnd, yBegin, t_, forward_, a_, b_,
224 }
225 static const bool global = true;
226
227 private:
233 const ext::shared_ptr<EndCriteria> endCriteria_;
234 const ext::shared_ptr<OptimizationMethod> optMethod_;
236 const bool useMaxError_;
238};
239}
240
241#endif
1-D array used in linear algebra.
Definition: array.hpp:52
base class for 1-D interpolations.
ext::shared_ptr< Impl > impl_
template class providing a null value for a given type.
Definition: null.hpp:76
Svi interpolation factory and traits
const Real errorAccept_
static const bool global
const ext::shared_ptr< OptimizationMethod > optMethod_
const ext::shared_ptr< EndCriteria > endCriteria_
const bool useMaxError_
const Size maxGuesses_
Svi(Time t, Real forward, Real a, Real b, Real sigma, Real rho, Real m, bool aIsFixed, bool bIsFixed, bool sigmaIsFixed, bool rhoIsFixed, bool mIsFixed, bool vegaWeighted=false, ext::shared_ptr< EndCriteria > endCriteria=ext::shared_ptr< EndCriteria >(), ext::shared_ptr< OptimizationMethod > optMethod=ext::shared_ptr< OptimizationMethod >(), const Real errorAccept=0.0020, const bool useMaxError=false, const Size maxGuesses=50)
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
Svi smile interpolation between discrete volatility points.
EndCriteria::Type endCriteria()
const detail::XABRCoeffHolder< detail::SviSpecs > & coeffs() const
const std::vector< Real > & interpolationWeights() const
SviInterpolation(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Time t, const Real &forward, Real a, Real b, Real sigma, Real rho, Real m, bool aIsFixed, bool bIsFixed, bool sigmaIsFixed, bool rhoIsFixed, bool mIsFixed, bool vegaWeighted=true, const ext::shared_ptr< EndCriteria > &endCriteria=ext::shared_ptr< EndCriteria >(), const ext::shared_ptr< OptimizationMethod > &optMethod=ext::shared_ptr< OptimizationMethod >(), const Real errorAccept=0.0020, const bool useMaxError=false, const Size maxGuesses=50)
Stochastic Volatility Inspired Smile Section.
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
SviSmileSection SviWrapper
void checkSviParameters(const Real a, const Real b, const Real sigma, const Real rho, const Real m, const Time tte)
Real sviTotalVariance(const Real a, const Real b, const Real sigma, const Real rho, const Real m, const Real k)
Definition: any.hpp:35
Real blackFormulaStdDevDerivative(Rate strike, Rate forward, Real stdDev, Real discount, Real displacement)
STL namespace.
Array inverse(const Array &y, const std::vector< bool > &, const std::vector< Real > &, const Real)
Real weight(const Real strike, const Real forward, const Real stdDev, const std::vector< Real > &addParams)
void guess(Array &values, const std::vector< bool > &paramIsFixed, const Real &forward, const Real expiryTime, const std::vector< Real > &r, const std::vector< Real > &addParams)
ext::shared_ptr< type > instance(const Time t, const Real &forward, const std::vector< Real > &params, const std::vector< Real > &addParams)
Array direct(const Array &x, const std::vector< bool > &paramIsFixed, const std::vector< Real > &params, const Real forward)
void defaultValues(std::vector< Real > &params, std::vector< bool > &paramIsFixed, const Real &forward, const Real expiryTime, const std::vector< Real > &addParams)