27 class BlackCalculator::Calculator :
public AcyclicVisitor,
28 public Visitor<Payoff>,
29 public Visitor<PlainVanillaPayoff>,
30 public Visitor<CashOrNothingPayoff>,
31 public Visitor<AssetOrNothingPayoff>,
32 public Visitor<GapPayoff> {
34 BlackCalculator& black_;
36 explicit Calculator(BlackCalculator& black) : black_(black) {}
37 void visit(Payoff&)
override;
38 void visit(PlainVanillaPayoff&)
override;
39 void visit(CashOrNothingPayoff&)
override;
40 void visit(AssetOrNothingPayoff&)
override;
41 void visit(GapPayoff&)
override;
49 :
strike_(p->strike()), forward_(forward), stdDev_(stdDev),
50 discount_(discount),
variance_(stdDev*stdDev) {
59 :
strike_(strike), forward_(forward), stdDev_(stdDev),
60 discount_(discount),
variance_(stdDev*stdDev) {
61 initialize(ext::shared_ptr<StrikedTypePayoff>(
new
67 "strike (" <<
strike_ <<
") must be non-negative");
69 "forward (" <<
forward_ <<
") must be positive");
73 "stdDev (" <<
stdDev_ <<
") must be non-negative");
75 "discount (" <<
discount_ <<
") must be positive");
129 switch (p->optionType()) {
143 QL_FAIL(
"invalid option type");
148 Calculator calc(*
this);
152 void BlackCalculator::Calculator::visit(Payoff& p) {
153 QL_FAIL(
"unsupported payoff type: " << p.name());
156 void BlackCalculator::Calculator::visit(PlainVanillaPayoff&) {}
158 void BlackCalculator::Calculator::visit(CashOrNothingPayoff&
payoff) {
159 black_.alpha_ = black_.DalphaDd1_ = 0.0;
160 black_.x_ =
payoff.cashPayoff();
161 black_.DxDstrike_ = 0.0;
162 switch (
payoff.optionType()) {
164 black_.beta_ = black_.cum_d2_;
165 black_.DbetaDd2_ = black_.n_d2_;
168 black_.beta_ = 1.0-black_.cum_d2_;
169 black_.DbetaDd2_ = -black_.n_d2_;
172 QL_FAIL(
"invalid option type");
176 void BlackCalculator::Calculator::visit(AssetOrNothingPayoff&
payoff) {
177 black_.beta_ = black_.DbetaDd2_ = 0.0;
178 switch (
payoff.optionType()) {
180 black_.alpha_ = black_.cum_d1_;
181 black_.DalphaDd1_ = black_.n_d1_;
184 black_.alpha_ = 1.0-black_.cum_d1_;
185 black_.DalphaDd1_ = -black_.n_d1_;
188 QL_FAIL(
"invalid option type");
192 void BlackCalculator::Calculator::visit(GapPayoff&
payoff) {
193 black_.x_ =
payoff.secondStrike();
194 black_.DxDstrike_ = 0.0;
204 QL_REQUIRE(spot > 0.0,
"positive spot value required: " <<
205 spot <<
" not allowed");
257 QL_REQUIRE(spot > 0.0,
"positive spot value required: " <<
258 spot <<
" not allowed");
269 Real temp2 = D2alphaDs2 *
forward_ + 2.0 * DalphaDs * DforwardDs
270 +D2betaDs2 *
x_ + 2.0 * DbetaDs *
DxDs_;
284 Real temp2 = D2alphaDforward2 *
forward_ + 2.0 * DalphaDforward
285 +D2betaDforward2 *
x_;
291 Time maturity)
const {
294 "maturity (" << maturity <<
") must be non-negative");
295 if (
close(maturity, 0.0))
return 0.0;
303 "negative maturity not allowed");
312 return discount_ * std::sqrt(maturity) * temp2;
318 "negative maturity not allowed");
330 "negative maturity not allowed");
364 D2alphaD2strike *
forward_ + D2betaD2strike *
x_
Black-formula calculator class.
Real dividendRho(Time maturity) const
virtual Real delta(Real spot) const
Real vega(Time maturity) const
void initialize(const ext::shared_ptr< StrikedTypePayoff > &p)
BlackCalculator(const ext::shared_ptr< StrikedTypePayoff > &payoff, Real forward, Real stdDev, Real discount=1.0)
Real strikeSensitivity() const
virtual Real gamma(Real spot) const
Real gammaForward() const
Real elasticityForward() const
virtual Real elasticity(Real spot) const
Real deltaForward() const
virtual Real theta(Real spot, Time maturity) const
Real rho(Time maturity) const
Cumulative normal distribution function.
floating-point comparisons
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Real Time
continuous quantity with 1-year units
ext::shared_ptr< QuantLib::Payoff > payoff
bool close(const Quantity &m1, const Quantity &m2, Size n)
normal, cumulative and inverse cumulative distributions