Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
normalsabrinterpolation.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file normalsabrinterpolation.hpp
20 \brief normal SABR interpolation interpolation between discrete points
21*/
22
23#pragma once
24
26
27#include <ql/math/interpolations/xabrinterpolation.hpp>
28#include <ql/termstructures/volatility/sabr.hpp>
29
30#include <boost/assign/list_of.hpp>
31#include <boost/make_shared.hpp>
32
33namespace QuantExt {
34using namespace QuantLib;
35
36namespace detail {
37
39public:
40 NormalSABRWrapper(const Time t, const Real& forward, const std::vector<Real>& params,
41 const std::vector<Real>& addParams)
42 : t_(t), forward_(forward), params_(params) {
43 // validateSabrParameters(params[0], 0.0, params[1], params[2]);
44 }
45 const std::vector<Real>& params() const { return params_; }
46 Real volatility(const Real x) { return normalSabrVolatility(x, forward_, t_, params_[0], params_[1], params_[2]); }
47
48private:
49 const Real t_, &forward_;
50 const std::vector<Real> params_;
51};
52
54 Size dimension() { return 3; }
55 void defaultValues(std::vector<Real>& params, std::vector<bool>&, const Real& forward, const Real expiryTime,
56 const std::vector<Real>& addParams) {
57 if (params[0] == Null<Real>())
58 params[0] = 0.0040;
59 if (params[1] == Null<Real>())
60 params[1] = std::sqrt(0.4);
61 if (params[2] == Null<Real>())
62 params[2] = 0.0;
63 }
64 void guess(Array& values, const std::vector<bool>& paramIsFixed, const Real& forward, const Real expiryTime,
65 const std::vector<Real>& r, const std::vector<Real>& addParams) {
66 Size j = 0;
67 if (!paramIsFixed[0]) {
68 values[0] = (0.01 - 2E-6) * r[j++] + 1E-6; // normal vol guess
69 }
70 if (!paramIsFixed[1])
71 values[1] = 1.5 * r[j++] + 1E-6;
72 if (!paramIsFixed[2])
73 values[2] = (2.0 * r[j++] - 1.0) * (1.0 - 1E-6);
74 }
75 Real eps1() { return .0000001; }
76 Real eps2() { return .9999; }
77 Real dilationFactor() { return 0.001; }
78 Array inverse(const Array& y, const std::vector<bool>&, const std::vector<Real>&, const Real) {
79 Array x(3);
80 x[0] = std::tan(y[0] * M_PI / 0.02 - M_PI_2);
81 x[1] = std::tan(y[1] * M_PI / 5.00 - M_PI_2);
82 x[2] = std::tan((y[2] + 1.0) * M_PI / 2.0 - M_PI_2);
83 return x;
84 }
85 Array direct(const Array& x, const std::vector<bool>&, const std::vector<Real>&, const Real) {
86 Array y(3);
87 y[0] = 0.02 * (std::atan(x[0]) + M_PI_2) / M_PI;
88 y[1] = 5.00 * (std::atan(x[1]) + M_PI_2) / M_PI;
89 y[2] = 2.0 * (std::atan(x[2]) + M_PI_2) / M_PI - 1.0;
90 return y;
91 }
92 Real weight(const Real strike, const Real forward, const Real stdDev, const std::vector<Real>& addParams) {
93 return bachelierBlackFormulaStdDevDerivative(strike, forward, stdDev, 1.0);
94 }
96 QuantLib::ext::shared_ptr<type> instance(const Time t, const Real& forward, const std::vector<Real>& params,
97 const std::vector<Real>& addParams) {
98 std::vector<Real> updatedParams(params);
99 if (!addParams.empty()) {
100 updatedParams[0] = normalSabrAlphaFromAtmVol(forward, t, addParams.front(), params[1], params[2]);
101 }
102 return QuantLib::ext::make_shared<type>(t, forward, updatedParams, addParams);
103 }
104};
105} // namespace detail
106
107//! %SABR smile interpolation between discrete volatility points.
108/*! \ingroup interpolations */
109class NormalSABRInterpolation : public Interpolation {
110public:
111 template <class I1, class I2>
113 const I1& xBegin, // x = strikes
114 const I1& xEnd,
115 const I2& yBegin, // y = volatilities
116 Time t, // option expiry
117 const Real& forward, Real alpha, Real nu, Real rho, bool alphaIsFixed, bool nuIsFixed, bool rhoIsFixed,
118 bool vegaWeighted = true, const Size atmStrikeIndex = Null<Size>(), const bool implyAlphaFromAtmVol = false,
119 const QuantLib::ext::shared_ptr<EndCriteria>& endCriteria = QuantLib::ext::shared_ptr<EndCriteria>(),
120 const QuantLib::ext::shared_ptr<OptimizationMethod>& optMethod = QuantLib::ext::shared_ptr<OptimizationMethod>(),
121 const Real errorAccept = 0.0002, const bool useMaxError = false, const Size maxGuesses = 50) {
122
123 QL_REQUIRE(
124 !implyAlphaFromAtmVol || atmStrikeIndex != Null<Real>(),
125 "NormalSABRInterpolation: imply alpha from atm vol implies a) that the atm strike index must be given");
126
127 std::vector<Real> addParams;
128 if (implyAlphaFromAtmVol) {
129 addParams.push_back(*std::next(yBegin, atmStrikeIndex));
130 }
131
132 impl_ = QuantLib::ext::shared_ptr<Interpolation::Impl>(
133 new QuantLib::detail::XABRInterpolationImpl<I1, I2, detail::NormalSABRSpecs>(
134 xBegin, xEnd, yBegin, t, forward, boost::assign::list_of(alpha)(nu)(rho),
135 boost::assign::list_of(alphaIsFixed)(nuIsFixed)(rhoIsFixed), vegaWeighted, endCriteria, optMethod,
136 errorAccept, useMaxError, maxGuesses, addParams));
137 coeffs_ = QuantLib::ext::dynamic_pointer_cast<QuantLib::detail::XABRCoeffHolder<detail::NormalSABRSpecs>>(impl_);
138 }
139 Real expiry() const { return coeffs_->t_; }
140 Real forward() const { return coeffs_->forward_; }
141 Real alpha() const { return coeffs_->modelInstance_->params()[0]; }
142 Real nu() const { return coeffs_->modelInstance_->params()[1]; }
143 Real rho() const { return coeffs_->modelInstance_->params()[2]; }
144 Real rmsError() const { return coeffs_->error_; }
145 Real maxError() const { return coeffs_->maxError_; }
146 const std::vector<Real>& interpolationWeights() const { return coeffs_->weights_; }
147 EndCriteria::Type endCriteria() { return coeffs_->XABREndCriteria_; }
148
149private:
150 QuantLib::ext::shared_ptr<QuantLib::detail::XABRCoeffHolder<detail::NormalSABRSpecs>> coeffs_;
151};
152
153//! %SABR interpolation factory and traits
154/*! \ingroup interpolations */
156public:
157 NormalSABR(Time t, Real forward, Real alpha, Real nu, Real rho, bool alphaIsFixed, bool nuIsFixed, bool rhoIsFixed,
158 bool vegaWeighted = false,
159 const QuantLib::ext::shared_ptr<EndCriteria> endCriteria = QuantLib::ext::shared_ptr<EndCriteria>(),
160 const QuantLib::ext::shared_ptr<OptimizationMethod> optMethod = QuantLib::ext::shared_ptr<OptimizationMethod>(),
161 const Real errorAccept = 0.0002, const bool useMaxError = false, const Size maxGuesses = 50)
162 : t_(t), forward_(forward), alpha_(alpha), nu_(nu), rho_(rho), alphaIsFixed_(alphaIsFixed),
163 nuIsFixed_(nuIsFixed), rhoIsFixed_(rhoIsFixed), vegaWeighted_(vegaWeighted), endCriteria_(endCriteria),
164 optMethod_(optMethod), errorAccept_(errorAccept), useMaxError_(useMaxError), maxGuesses_(maxGuesses) {}
165 template <class I1, class I2> Interpolation interpolate(const I1& xBegin, const I1& xEnd, const I2& yBegin) const {
166 return SABRInterpolation(xBegin, xEnd, yBegin, t_, forward_, alpha_, nu_, rho_, alphaIsFixed_, nuIsFixed_,
169 }
170 static const bool global = true;
171
172private:
173 Time t_;
178 const QuantLib::ext::shared_ptr<EndCriteria> endCriteria_;
179 const QuantLib::ext::shared_ptr<OptimizationMethod> optMethod_;
180 const Real errorAccept_;
181 const bool useMaxError_;
182 const Size maxGuesses_;
183};
184} // namespace QuantExt
SABR interpolation factory and traits
const QuantLib::ext::shared_ptr< OptimizationMethod > optMethod_
NormalSABR(Time t, Real forward, Real alpha, Real nu, Real rho, bool alphaIsFixed, bool nuIsFixed, bool rhoIsFixed, bool vegaWeighted=false, const QuantLib::ext::shared_ptr< EndCriteria > endCriteria=QuantLib::ext::shared_ptr< EndCriteria >(), const QuantLib::ext::shared_ptr< OptimizationMethod > optMethod=QuantLib::ext::shared_ptr< OptimizationMethod >(), const Real errorAccept=0.0002, const bool useMaxError=false, const Size maxGuesses=50)
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
const QuantLib::ext::shared_ptr< EndCriteria > endCriteria_
SABR smile interpolation between discrete volatility points.
QuantLib::ext::shared_ptr< QuantLib::detail::XABRCoeffHolder< detail::NormalSABRSpecs > > coeffs_
const std::vector< Real > & interpolationWeights() const
NormalSABRInterpolation(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin, Time t, const Real &forward, Real alpha, Real nu, Real rho, bool alphaIsFixed, bool nuIsFixed, bool rhoIsFixed, bool vegaWeighted=true, const Size atmStrikeIndex=Null< Size >(), const bool implyAlphaFromAtmVol=false, const QuantLib::ext::shared_ptr< EndCriteria > &endCriteria=QuantLib::ext::shared_ptr< EndCriteria >(), const QuantLib::ext::shared_ptr< OptimizationMethod > &optMethod=QuantLib::ext::shared_ptr< OptimizationMethod >(), const Real errorAccept=0.0002, const bool useMaxError=false, const Size maxGuesses=50)
NormalSABRWrapper(const Time t, const Real &forward, const std::vector< Real > &params, const std::vector< Real > &addParams)
const std::vector< Real > & params() const
Real normalSabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real nu, Real rho)
Definition: normalsabr.cpp:28
Real normalSabrAlphaFromAtmVol(Rate forward, Time expiryTime, Real atmVol, Real nu, Real rho)
Definition: normalsabr.cpp:50
normal SABR model implied volatility approximation
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)
void defaultValues(std::vector< Real > &params, std::vector< bool > &, const Real &forward, const Real expiryTime, const std::vector< Real > &addParams)
QuantLib::ext::shared_ptr< type > instance(const Time t, const Real &forward, const std::vector< Real > &params, const std::vector< Real > &addParams)