27#include <ql/math/interpolations/xabrinterpolation.hpp>
28#include <ql/termstructures/volatility/sabr.hpp>
30#include <boost/assign/list_of.hpp>
31#include <boost/make_shared.hpp>
41 const std::vector<Real>& addParams)
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>())
59 if (params[1] == Null<Real>())
60 params[1] = std::sqrt(0.4);
61 if (params[2] == Null<Real>())
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) {
67 if (!paramIsFixed[0]) {
68 values[0] = (0.01 - 2E-6) * r[j++] + 1E-6;
71 values[1] = 1.5 * r[j++] + 1E-6;
73 values[2] = (2.0 * r[j++] - 1.0) * (1.0 - 1E-6);
75 Real
eps1() {
return .0000001; }
76 Real
eps2() {
return .9999; }
78 Array
inverse(
const Array& y,
const std::vector<bool>&,
const std::vector<Real>&,
const Real) {
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);
85 Array
direct(
const Array& x,
const std::vector<bool>&,
const std::vector<Real>&,
const Real) {
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;
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);
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()) {
102 return QuantLib::ext::make_shared<type>(t, forward, updatedParams, addParams);
111 template <
class I1,
class I2>
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) {
124 !implyAlphaFromAtmVol || atmStrikeIndex != Null<Real>(),
125 "NormalSABRInterpolation: imply alpha from atm vol implies a) that the atm strike index must be given");
127 std::vector<Real> addParams;
128 if (implyAlphaFromAtmVol) {
129 addParams.push_back(*std::next(yBegin, atmStrikeIndex));
132 impl_ = QuantLib::ext::shared_ptr<Interpolation::Impl>(
133 new QuantLib::detail::XABRInterpolationImpl<I1, I2, detail::NormalSABRSpecs>(
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_);
142 Real
nu()
const {
return coeffs_->modelInstance_->params()[1]; }
143 Real
rho()
const {
return coeffs_->modelInstance_->params()[2]; }
150 QuantLib::ext::shared_ptr<QuantLib::detail::XABRCoeffHolder<detail::NormalSABRSpecs>>
coeffs_;
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)
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_,
179 const QuantLib::ext::shared_ptr<OptimizationMethod>
optMethod_;
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.
EndCriteria::Type endCriteria()
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 > ¶ms, const std::vector< Real > &addParams)
Real volatility(const Real x)
const std::vector< Real > params_
const std::vector< Real > & params() const
Real normalSabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real nu, Real rho)
Real normalSabrAlphaFromAtmVol(Rate forward, Time expiryTime, Real atmVol, Real nu, Real rho)
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 > ¶mIsFixed, const Real &forward, const Real expiryTime, const std::vector< Real > &r, const std::vector< Real > &addParams)
void defaultValues(std::vector< Real > ¶ms, 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 > ¶ms, const std::vector< Real > &addParams)