/usr/include/ql/experimental/volatility/noarbsabr.hpp is in libquantlib0-dev 1.7.1-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
Copyright (C) 2014 Peter Caspers
This file is part of QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
QuantLib is free software: you can redistribute it and/or modify it
under the terms of the QuantLib license. You should have received a
copy of the license along with this program; if not, please email
<quantlib-dev@lists.sf.net>. The license is also available online at
<http://quantlib.org/license.shtml>.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
/*! \file noarbsabr.hpp
\brief No-arbitrage SABR
Reference: Paul Doust, No-arbitrage SABR,
The Journal of Computational Finance (3–31)
Volume 15/Number 3, Spring 2012
The parameters are bounded as follows (see also below)
beta [0.01, 0.99]
expiryTime (0.0, 30.0]
sigmaI = alpha*forward^(beta-1) [0.05, 1.0]
nu [0.0001, 0.8]
rho [-0.99, 0.99]
As suggested in the paper, d0 is interpolated (linearly)
in phi space. For beta > 0.9 phi is extrapolated to a
value corresponding to d0 = tiny_prob = 1E-5 at beta = 1.
For tau < 0.25 phi is extrapolated flat.
For rho outside [-0.75, 0.75] phi is extrapolated linearly.
There are some parameter sets that are admissable, yet do
not allow for the adjustment procedure as suggested in the
paper to force the model implied forward to the correct
value. In this case, no adjustment is done, leading to a
model implied forward different from the desired one.
This situation can be identified by comparing forward()
and numericalForward().
*/
#ifndef quantlib_noarb_sabr
#define quantlib_noarb_sabr
#include <ql/qldefines.hpp>
#include <ql/types.hpp>
#include <ql/math/integrals/gausslobattointegral.hpp>
#include <vector>
namespace QuantLib {
namespace detail {
namespace NoArbSabrModel {
// parameter bounds
const Real beta_min = 0.01;
const Real beta_max = 0.99;
const Real expiryTime_max = 30.0;
const Real sigmaI_min = 0.05;
const Real sigmaI_max = 1.00;
const Real nu_min = 0.01;
const Real nu_max = 0.80;
const Real rho_min = -0.99;
const Real rho_max = 0.99;
// cutoff for phi(d0) / tau
// if beta = 0.99, d0 is below 1E-14 for
// bigger values than this
const Real phiByTau_cutoff = 124.587;
// number of mc simulations in tabulated
// absorption probabilities
const Real nsim = 2500000.0;
// small probability used for extrapolation
// of beta towards 1
const Real tiny_prob = 1E-5;
// minimum strike used for normal case integration
const Real strike_min = 1E-6;
// accuracy and max iterations for
// numerical integration
const Real i_accuracy = 1E-7;
const Size i_max_iterations = 10000;
// accuracy when adjusting the model forward
// to match the given forward
const Real forward_accuracy = 1E-6;
// step for searching the model forward
// in newton algorithm
const Real forward_search_step = 0.0010;
// lower bound for density evaluation
const Real density_lower_bound = 1E-50;
// threshold to identify a zero density
const Real density_threshold = 1E-100;
}
}
class NoArbSabrModel {
public:
NoArbSabrModel(const Real expiryTime, const Real forward, const Real alpha,
const Real beta, const Real nu, const Real rho);
Real optionPrice(const Real strike) const;
Real digitalOptionPrice(const Real strike) const;
Real density(const Real strike) const {
return p(strike) * (1 - absProb_) / numericalIntegralOverP_;
}
Real forward() const { return externalForward_; }
Real numericalForward() const { return numericalForward_; }
Real expiryTime() const { return expiryTime_; }
Real alpha() const { return alpha_; }
Real beta() const { return beta_; }
Real nu() const { return nu_; }
Real rho() const { return rho_; }
Real absorptionProbability() const { return absProb_; }
static void checkAbsorptionMatrix();
private:
Real p(const Real f) const;
Real forwardError(const Real forward) const;
const Real expiryTime_, externalForward_;
const Real alpha_, beta_, nu_, rho_;
Real absProb_, fmin_, fmax_;
mutable Real forward_, numericalIntegralOverP_;
mutable Real numericalForward_;
boost::shared_ptr<GaussLobattoIntegral> integrator_;
class integrand;
friend class integrand;
};
namespace detail {
extern "C" const unsigned long sabrabsprob[1209600];
class D0Interpolator {
public:
D0Interpolator(const Real forward, const Real expiryTime, const Real alpha,
const Real beta, const Real nu, const Real rho);
Real operator()() const;
private:
Real phi(const Real d0) const;
Real d0(const Real phi) const;
const Real forward_, expiryTime_, alpha_, beta_, nu_, rho_, gamma_;
Real sigmaI_;
std::vector<Real> tauG_, sigmaIG_, rhoG_, nuG_, betaG_;
};
} // namespace detail
} // namespace QuantLib
#endif
|