21#include <ql/math/comparison.hpp>
23#include <boost/math/distributions/normal.hpp>
31static boost::math::normal_distribution<double> normal_dist;
32Real phi(
const Real x) {
return boost::math::pdf(normal_dist, x); }
33Real Phi(
const Real x) {
return boost::math::cdf(normal_dist, x); }
35Real PhiTilde(
const Real x) {
return Phi(x) + phi(x) / x; }
37Real inversePhiTilde(
const Real PhiTildeStar) {
38 QL_REQUIRE(PhiTildeStar < 0.0,
"inversePhiTilde(" << PhiTildeStar <<
"): negative argument required");
40 if (PhiTildeStar < -0.001882039271) {
41 Real g = 1.0 / (PhiTildeStar - 0.5);
42 Real xibar = (0.032114372355 - g * g * (0.016969777977 - g * g * (2.6207332461E-3 - 9.6066952861E-5 * g * g))) /
43 (1.0 - g * g * (0.6635646938 - g * g * (0.14528712196 - 0.010472855461 * g * g)));
44 xbar = g * (0.3989422804014326 + xibar * g * g);
46 Real h = std::sqrt(-std::log(-PhiTildeStar));
47 xbar = (9.4883409779 - h * (9.6320903635 - h * (0.58556997323 + 2.1464093351 * h))) /
48 (1.0 - h * (0.65174820867 + h * (1.5120247828 + 6.6437847132E-5 * h)));
50 Real q = (PhiTilde(xbar) - PhiTildeStar) / phi(xbar);
52 xbar + 3.0 * q * xbar * xbar * (2.0 - q * xbar * (2.0 + xbar * xbar)) /
53 (6.0 + q * xbar * (-12.0 + xbar * (6.0 * q + xbar * (-6.0 + q * xbar * (3.0 + xbar * xbar)))));
62 Real theta = optionType == Option::Call ? 1.0 : -1.0;
66 bachelierPrice /= discount;
70 if (std::abs(strike - forward) < 1E-15) {
71 return bachelierPrice / (std::sqrt(tte) * phi(0.0));
76 Real timeValue = bachelierPrice - std::max(theta * (forward - strike), 0.0);
78 if (std::abs(timeValue) < 1E-15)
81 QL_REQUIRE(timeValue > 0.0,
"exactBachelierImpliedVolatility(theta="
82 << theta <<
",strike=" << strike <<
",forward=" << forward <<
",tte=" << tte
83 <<
",price=" << bachelierPrice <<
"): option price implies negative time value ("
86 Real PhiTildeStar = -std::abs(timeValue / (strike - forward));
87 Real xstar = inversePhiTilde(PhiTildeStar);
88 Real impliedVol = std::abs((strike - forward) / (xstar * std::sqrt(tte)));
implied bachelier volatility based on Jaeckel, Implied Normal Volatility, 2017
Real exactBachelierImpliedVolatility(Option::Type optionType, Real strike, Real forward, Real tte, Real bachelierPrice, Real discount)