24#include <ql/termstructures/volatility/sabr.hpp>
25#include <ql/utilities/dataformatters.hpp>
26#include <ql/math/comparison.hpp>
27#include <ql/math/functional.hpp>
28#include <ql/errors.hpp>
29#include <ql/termstructures/volatility/volatilitytype.hpp>
41 const Real oneMinusBeta = 1.0-beta;
42 const Real A = std::pow(forward*strike, oneMinusBeta);
43 const Real sqrtA= std::sqrt(A);
45 if (!
close(forward, strike))
46 logM = std::log(forward/strike);
48 const Real epsilon = (forward-strike)/strike;
49 logM = epsilon - .5 * epsilon * epsilon ;
51 const Real z = (nu/alpha)*sqrtA*logM;
52 const Real B = 1.0-2.0*rho*z+z*z;
53 const Real C = oneMinusBeta*oneMinusBeta*logM*logM;
54 const Real tmp = (std::sqrt(B)+z-rho)/(1.0-rho);
55 const Real xx = std::log(tmp);
56 const Real D = sqrtA*(1.0+C/24.0+C*C/1920.0);
57 const Real d = 1.0 + expiryTime *
58 (oneMinusBeta*oneMinusBeta*alpha*alpha/(24.0*A)
59 + 0.25*rho*beta*nu*alpha/sqrtA
60 +(2.0-3.0*rho*rho)*(nu*nu/24.0));
65 static const Real m = 10;
69 multiplier = 1.0 - 0.5*rho*z - (3.0*rho*rho-2.0)*z*z/12.0;
71 return (alpha/D)*multiplier*d;
92 const Real oneMinusBeta = 1.0 - beta;
93 const Real minusBeta = -1.0 * beta;
94 const Real A = std::pow(forward * strike, oneMinusBeta);
95 const Real sqrtA = std::sqrt(A);
97 if (!
close(forward, strike))
98 logM = std::log(forward / strike);
100 const Real epsilon = (forward - strike) / strike;
101 logM = epsilon - .5 * epsilon * epsilon;
103 const Real z = (nu / alpha) * sqrtA * logM;
104 const Real B = 1.0 - 2.0 * rho * z + z * z;
105 const Real C = oneMinusBeta * oneMinusBeta * logM * logM;
106 const Real D = logM * logM;
107 const Real tmp = (std::sqrt(B) + z - rho) / (1.0 - rho);
108 const Real xx = std::log(tmp);
109 const Real E_1 = (1.0 + D / 24.0 + D * D / 1920.0);
110 const Real E_2 = (1.0 + C / 24.0 + C * C / 1920.0);
111 const Real E = E_1 / E_2;
112 const Real d = 1.0 + expiryTime * (minusBeta * (2 - beta) * alpha * alpha / (24.0 * A) +
113 0.25 * rho * beta * nu * alpha / sqrtA +
114 (2.0 - 3.0 * rho * rho) * (nu * nu / 24.0));
119 static const Real m = 10;
123 multiplier = 1.0 - 0.5 * rho * z - (3.0 * rho * rho - 2.0) * z * z / 12.0;
125 const Real F = alpha * std::pow(forward * strike, beta / 2.0);
127 return F * E * multiplier * d;
149 QL_REQUIRE(alpha>0.0,
"alpha must be positive: "
150 << alpha <<
" not allowed");
151 QL_REQUIRE(beta>=0.0 && beta<=1.0,
"beta must be in (0.0, 1.0): "
152 << beta <<
" not allowed");
153 QL_REQUIRE(nu>=0.0,
"nu must be non negative: "
154 << nu <<
" not allowed");
155 QL_REQUIRE(rho*rho<1.0,
"rho square must be less than one: "
156 << rho <<
" not allowed");
167 QL_REQUIRE(strike>0.0,
"strike must be positive: "
168 <<
io::rate(strike) <<
" not allowed");
169 QL_REQUIRE(forward>0.0,
"at the money forward rate must be "
170 "positive: " <<
io::rate(forward) <<
" not allowed");
171 QL_REQUIRE(expiryTime>=0.0,
"expiry time must be non-negative: "
172 << expiryTime <<
" not allowed");
187 QL_REQUIRE(strike + shift > 0.0,
"strike+shift must be positive: "
189 QL_REQUIRE(forward + shift > 0.0,
"at the money forward rate + shift must be "
190 "positive: " <<
io::rate(forward) <<
" " <<
io::rate(shift) <<
" not allowed");
191 QL_REQUIRE(expiryTime>=0.0,
"expiry time must be non-negative: "
192 << expiryTime <<
" not allowed");
195 alpha, beta, nu, rho,shift, volatilityType);
199 struct SabrFlochKennedyVolatility {
200 Real F, alpha, beta, nu, rho, t;
203 return -1.0/(1.0-beta)*(std::pow(F,1-beta)-std::pow(k,1-beta));
207 return 1/nu*std::log( ( std::sqrt(1+2*rho*nu/alpha*y(k)
209 - rho - nu/alpha*y(k) ) / (1-rho) );
213 return std::sqrt(alpha*alpha+2*alpha*rho*nu*y(k)
214 +
squared(nu*y(k)))*std::pow(k,beta);
218 return std::log(F/k)/Dint(k);
223 if (m > 1.0025 || m < 0.9975) {
224 return omega0(k)*(1+0.25*rho*nu*alpha*
225 (std::pow(k,beta)-std::pow(F,beta))/(k-F)*t)
226 -omega0(k)/
squared(Dint(k))*(std::log(
227 omega0(k)) + 0.5*std::log((F*k/(D(F)*D(k))) ))*t;
230 return taylorExpansion(k);
234 Real taylorExpansion(
Real k)
const {
236 const Real alpha2 = alpha*alpha;
237 const Real rho2 = rho*rho;
239 (alpha*std::pow(F,-3 + beta)*(alpha2*
squared(-1 + beta)*std::pow(F,2*beta)*t + 6*alpha*beta*nu*std::pow(F,1 + beta)*rho*t +
240 F2*(24 + nu*nu*(2 - 3*rho2)*t)))/24.0 +
241 (3*alpha2*alpha*std::pow(-1 + beta,3)*std::pow(F,3*beta)*t +
242 3*alpha2*(-1 + beta)*(-1 + 5*beta)*nu*std::pow(F,1 + 2*beta)*rho*t + nu*F2*F*rho*(24 + nu*nu*(-4 + 3*rho2)*t) +
243 alpha*std::pow(F,2 + beta)*(24*(-1 + beta) + nu*nu*(2*(-1 + beta) + 3*(1 + beta)*rho2)*t))/(48.*F2*F2) * (k-F) +
244 (std::pow(F,-5 - beta)*(alpha2*alpha2*std::pow(-1 + beta,3)*(-209 + 119*beta)*std::pow(F,4*beta)*t + 30*alpha2*alpha*(-1 + beta)*(9 + beta*(-37 + 18*beta))*nu*std::pow(F,1 + 3*beta)*rho*t -
245 30*alpha*nu*std::pow(F,3 + beta)*rho*(24 + nu*nu*(-4*(1 + beta) + 3*(1 + 2*beta)*rho2)*t) +
246 10*alpha2*std::pow(F,2 + 2*beta)*(24*(-4 + beta)*(-1 + beta) + nu*nu*(2*(-1 + beta)*(-7 + 4*beta) + 3*(-4 + beta*(-7 + 5*beta))*rho2)*t) +
247 nu*nu*F2*F2*(480 - 720*rho2 + nu*nu*(-64 + 75*rho2*(4 - 3*rho2))*t)))/(2880*alpha) * (k-F)*(k-F);
259 const SabrFlochKennedyVolatility v =
260 {forward, alpha, beta, nu, rho, expiryTime};
detail::percent_holder rate(Rate)
output rates and spreads as percentages
Real Time
continuous quantity with 1-year units
Real sabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho, VolatilityType volatilityType)
Real unsafeShiftedSabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho, Real shift, VolatilityType volatilityType)
Real unsafeSabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho, VolatilityType volatilityType)
Real sabrFlochKennedyVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho)
Real unsafeSabrNormalVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho)
Real unsafeSabrLogNormalVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho)
bool close(const Quantity &m1, const Quantity &m2, Size n)
void validateSabrParameters(Real alpha, Real beta, Real nu, Real rho)
Real shiftedSabrVolatility(Rate strike, Rate forward, Time expiryTime, Real alpha, Real beta, Real nu, Real rho, Real shift, VolatilityType volatilityType)