QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
sabrinterpolation.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) 2006 Ferdinando Ametrano
5 Copyright (C) 2007 Marco Bianchetti
6 Copyright (C) 2007 François du Vignaud
7 Copyright (C) 2007 Giorgio Facchinetti
8 Copyright (C) 2006 Mario Pucci
9 Copyright (C) 2006 StatPro Italia srl
10 Copyright (C) 2014 Peter Caspers
11
12 This file is part of QuantLib, a free-software/open-source library
13 for financial quantitative analysts and developers - http://quantlib.org/
14
15 QuantLib is free software: you can redistribute it and/or modify it
16 under the terms of the QuantLib license. You should have received a
17 copy of the license along with this program; if not, please email
18 <quantlib-dev@lists.sf.net>. The license is also available online at
19 <http://quantlib.org/license.shtml>.
20
21 This program is distributed in the hope that it will be useful, but WITHOUT
22 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
23 FOR A PARTICULAR PURPOSE. See the license for more details.
24*/
25
26/*! \file sabrinterpolation.hpp
27 \brief SABR interpolation interpolation between discrete points
28*/
29
30#ifndef quantlib_sabr_interpolation_hpp
31#define quantlib_sabr_interpolation_hpp
32
35#include <utility>
36
37namespace QuantLib {
38
39namespace detail {
40
42 public:
44 const Real& forward,
45 const std::vector<Real>& params,
46 const std::vector<Real>& addParams)
47 : t_(t), forward_(forward), params_(params), shift_(addParams.empty() ? 0.0 : addParams[0]) {
48 QL_REQUIRE(forward_ + shift_ > 0.0, "forward+shift must be positive: "
49 << forward_ << " with shift "
50 << shift_ << " not allowed");
51 validateSabrParameters(params[0], params[1], params[2], params[3]);
52 }
53 Real volatility(const Real x, const VolatilityType volatilityType) {
55 params_[2], params_[3], shift_, volatilityType);
56 }
57
58 private:
59 const Real t_, &forward_;
60 const std::vector<Real> &params_;
61 const Real shift_;
62};
63
64struct SABRSpecs {
65 Size dimension() { return 4; }
66 void defaultValues(std::vector<Real> &params, std::vector<bool> &,
67 const Real &forward, const Real expiryTime,
68 const std::vector<Real> &addParams) {
69 if (params[1] == Null<Real>())
70 params[1] = 0.5;
71 if (params[0] == Null<Real>())
72 // adapt alpha to beta level
73 params[0] = 0.2 * (params[1] < 0.9999 ?
74 Real(std::pow(forward + (addParams.empty() ? 0.0 : addParams[0]),
75 1.0 - params[1])) :
76 1.0);
77 if (params[2] == Null<Real>())
78 params[2] = std::sqrt(0.4);
79 if (params[3] == Null<Real>())
80 params[3] = 0.0;
81 }
82 void guess(Array &values, const std::vector<bool> &paramIsFixed,
83 const Real &forward, const Real expiryTime,
84 const std::vector<Real> &r, const std::vector<Real> &addParams) {
85 Size j = 0;
86 if (!paramIsFixed[1])
87 values[1] = (1.0 - 2E-6) * r[j++] + 1E-6;
88 if (!paramIsFixed[0]) {
89 values[0] = (1.0 - 2E-6) * r[j++] + 1E-6; // lognormal vol guess
90 // adapt this to beta level
91 if (values[1] < 0.999)
92 values[0] *=
93 std::pow(forward + (addParams.empty() ? 0.0 : addParams[0]), 1.0 - values[1]);
94 }
95 if (!paramIsFixed[2])
96 values[2] = 1.5 * r[j++] + 1E-6;
97 if (!paramIsFixed[3])
98 values[3] = (2.0 * r[j++] - 1.0) * (1.0 - 1E-6);
99 }
100 Real eps1() { return .0000001; }
101 Real eps2() { return .9999; }
102 Real dilationFactor() { return 0.001; }
103 Array inverse(const Array &y, const std::vector<bool> &,
104 const std::vector<Real> &, const Real) {
105 Array x(4);
106 x[0] = y[0] < 25.0 + eps1() ? Real(std::sqrt(y[0] - eps1()))
107 : Real((y[0] - eps1() + 25.0) / 10.0);
108 // y_[1] = std::tan(M_PI*(x[1] - 0.5))/dilationFactor();
109 x[1] = std::sqrt(-std::log(y[1]));
110 x[2] = y[2] < 25.0 + eps1() ? Real(std::sqrt(y[2] - eps1()))
111 : Real((y[2] - eps1() + 25.0) / 10.0);
112 x[3] = std::asin(y[3] / eps2());
113 return x;
114 }
115 Array direct(const Array &x, const std::vector<bool> &,
116 const std::vector<Real> &, const Real) {
117 Array y(4);
118 y[0] = std::fabs(x[0]) < 5.0 ? Real(x[0] * x[0] + eps1())
119 : Real((10.0 * std::fabs(x[0]) - 25.0) + eps1());
120 // y_[1] = std::atan(dilationFactor_*x[1])/M_PI + 0.5;
121 y[1] = std::fabs(x[1]) < std::sqrt(-std::log(eps1()))
122 ? std::exp(-(x[1] * x[1]))
123 : eps1();
124 y[2] = std::fabs(x[2]) < 5.0 ? Real(x[2] * x[2] + eps1())
125 : Real((10.0 * std::fabs(x[2]) - 25.0) + eps1());
126 y[3] = std::fabs(x[3]) < 2.5 * M_PI
127 ? Real(eps2() * std::sin(x[3]))
128 : Real(eps2() * (x[3] > 0.0 ? 1.0 : (-1.0)));
129 return y;
130 }
131 Real weight(const Real strike, const Real forward, const Real stdDev,
132 const std::vector<Real> &addParams) {
133 return blackFormulaStdDevDerivative(strike, forward, stdDev, 1.0,
134 addParams[0]);
135 }
137 ext::shared_ptr<type> instance(const Time t, const Real &forward,
138 const std::vector<Real> &params,
139 const std::vector<Real> &addParams) {
140 return ext::make_shared<type>(t, forward, params, addParams);
141 }
142};
143}
144
145//! %SABR smile interpolation between discrete volatility points.
146/*! \ingroup interpolations
147 \warning See the Interpolation class for information about the
148 required lifetime of the underlying data.
149*/
151 public:
152 template <class I1, class I2>
153 SABRInterpolation(const I1 &xBegin, // x = strikes
154 const I1 &xEnd,
155 const I2 &yBegin, // y = volatilities
156 Time t, // option expiry
157 const Real &forward, Real alpha, Real beta, Real nu,
158 Real rho, bool alphaIsFixed, bool betaIsFixed,
159 bool nuIsFixed, bool rhoIsFixed, bool vegaWeighted = true,
160 const ext::shared_ptr<EndCriteria> &endCriteria =
161 ext::shared_ptr<EndCriteria>(),
162 const ext::shared_ptr<OptimizationMethod> &optMethod =
163 ext::shared_ptr<OptimizationMethod>(),
164 const Real errorAccept = 0.0020,
165 const bool useMaxError = false,
166 const Size maxGuesses = 50, const Real shift = 0.0,
167 const VolatilityType volatilityType = VolatilityType::ShiftedLognormal) {
168
169 impl_ = ext::shared_ptr<Interpolation::Impl>(
171 xBegin, xEnd, yBegin, t, forward,
172 {alpha, beta, nu, rho},
173 {alphaIsFixed, betaIsFixed, nuIsFixed, rhoIsFixed},
174 vegaWeighted, endCriteria, optMethod, errorAccept, useMaxError,
175 maxGuesses, {shift}, volatilityType));
176 }
177 Real expiry() const { return coeffs().t_; }
178 Real forward() const { return coeffs().forward_; }
179 Real alpha() const { return coeffs().params_[0]; }
180 Real beta() const { return coeffs().params_[1]; }
181 Real nu() const { return coeffs().params_[2]; }
182 Real rho() const { return coeffs().params_[3]; }
183 Real rmsError() const { return coeffs().error_; }
184 Real maxError() const { return coeffs().maxError_; }
185 const std::vector<Real> &interpolationWeights() const {
186 return coeffs().weights_;
187 }
188 EndCriteria::Type endCriteria() { return coeffs().XABREndCriteria_; }
189
190 private:
192 return *dynamic_cast<detail::XABRCoeffHolder<detail::SABRSpecs>*>(impl_.get());
193 }
194};
195
196//! %SABR interpolation factory and traits
197/*! \ingroup interpolations */
198class SABR {
199 public:
201 Real forward,
202 Real alpha,
203 Real beta,
204 Real nu,
205 Real rho,
206 bool alphaIsFixed,
207 bool betaIsFixed,
208 bool nuIsFixed,
209 bool rhoIsFixed,
210 bool vegaWeighted = false,
211 ext::shared_ptr<EndCriteria> endCriteria = ext::shared_ptr<EndCriteria>(),
212 ext::shared_ptr<OptimizationMethod> optMethod = ext::shared_ptr<OptimizationMethod>(),
213 const Real errorAccept = 0.0020,
214 const bool useMaxError = false,
215 const Size maxGuesses = 50,
216 const Real shift = 0.0)
217 : t_(t), forward_(forward), alpha_(alpha), beta_(beta), nu_(nu), rho_(rho),
218 alphaIsFixed_(alphaIsFixed), betaIsFixed_(betaIsFixed), nuIsFixed_(nuIsFixed),
219 rhoIsFixed_(rhoIsFixed), vegaWeighted_(vegaWeighted), endCriteria_(std::move(endCriteria)),
220 optMethod_(std::move(optMethod)), errorAccept_(errorAccept), useMaxError_(useMaxError),
221 maxGuesses_(maxGuesses), shift_(shift) {}
222 template <class I1, class I2>
223 Interpolation interpolate(const I1 &xBegin, const I1 &xEnd,
224 const I2 &yBegin) const {
225 return SABRInterpolation(xBegin, xEnd, yBegin, t_, forward_, alpha_,
230 }
231 static const bool global = true;
232
233 private:
239 const ext::shared_ptr<EndCriteria> endCriteria_;
240 const ext::shared_ptr<OptimizationMethod> optMethod_;
242 const bool useMaxError_;
245};
246}
247
248#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
SABR interpolation factory and traits
static const bool global
const ext::shared_ptr< OptimizationMethod > optMethod_
const ext::shared_ptr< EndCriteria > endCriteria_
SABR(Time t, Real forward, Real alpha, Real beta, Real nu, Real rho, bool alphaIsFixed, bool betaIsFixed, bool nuIsFixed, bool rhoIsFixed, 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, const Real shift=0.0)
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
SABR smile interpolation between discrete volatility points.
const detail::XABRCoeffHolder< detail::SABRSpecs > & coeffs() const
SABRInterpolation(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Time t, const Real &forward, Real alpha, Real beta, Real nu, Real rho, bool alphaIsFixed, bool betaIsFixed, bool nuIsFixed, bool rhoIsFixed, 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, const Real shift=0.0, const VolatilityType volatilityType=VolatilityType::ShiftedLognormal)
const std::vector< Real > & interpolationWeights() const
const std::vector< Real > & params_
SABRWrapper(const Time t, const Real &forward, const std::vector< Real > &params, const std::vector< Real > &addParams)
Real volatility(const Real x, const VolatilityType volatilityType)
const DefaultType & t
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
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
Real rho
#define M_PI
Definition: any.hpp:35
void validateSabrParameters(Real alpha, Real beta, Real nu, Real rho)
Definition: sabr.cpp:145
Real blackFormulaStdDevDerivative(Rate strike, Rate forward, Real stdDev, Real discount, Real displacement)
Real shiftedSabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho, Real shift, VolatilityType volatilityType)
Definition: sabr.cpp:178
STL namespace.
ext::shared_ptr< YieldTermStructure > r
Real beta
Definition: sabr.cpp:200
Real nu
Definition: sabr.cpp:200
Real alpha
Definition: sabr.cpp:200
SABR functions.
Array inverse(const Array &y, const std::vector< bool > &, const std::vector< Real > &, const Real)
Array direct(const Array &x, 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)
void defaultValues(std::vector< Real > &params, std::vector< bool > &, const Real &forward, const Real expiryTime, const std::vector< Real > &addParams)
generic interpolation class for sabr style underlying models like the Hagan 2002 expansion,...