22#include <ql/exercise.hpp>
23#include <ql/math/distributions/normaldistribution.hpp>
24#include <ql/pricingengines/blackcalculator.hpp>
25#include <ql/pricingengines/blackformula.hpp>
26#include <ql/pricingengines/vanilla/baroneadesiwhaleyengine.hpp>
27#include <ql/pricingengines/vanilla/juquadraticengine.hpp>
39 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
40 : process_(
std::move(process)) {
47 "not an American Option");
49 ext::shared_ptr<AmericanExercise> ex =
50 ext::dynamic_pointer_cast<AmericanExercise>(arguments_.exercise);
51 QL_REQUIRE(ex,
"non-American exercise given");
52 QL_REQUIRE(!ex->payoffAtExpiry(),
53 "payoff at expiry not handled");
55 ext::shared_ptr<StrikedTypePayoff> payoff =
56 ext::dynamic_pointer_cast<StrikedTypePayoff>(arguments_.payoff);
57 QL_REQUIRE(payoff,
"non-striked payoff given");
59 Real variance =
process_->blackVolatility()->blackVariance(
60 ex->lastDate(), payoff->strike());
66 QL_REQUIRE(spot > 0.0,
"negative or null underlying given");
67 Real forwardPrice = spot * dividendDiscount / riskFreeDiscount;
69 std::sqrt(variance), riskFreeDiscount);
71 if (dividendDiscount>=1.0 && payoff->optionType()==
Option::Call) {
73 results_.value = black.
value();
74 results_.delta = black.
delta(spot);
77 results_.gamma = black.
gamma(spot);
84 arguments_.exercise->lastDate());
85 results_.rho = black.
rho(t);
88 arguments_.exercise->lastDate());
92 arguments_.exercise->lastDate());
93 results_.vega = black.
vega(t);
94 results_.theta = black.
theta(spot, t);
104 Real tolerance = 1e-6;
106 payoff, riskFreeDiscount, dividendDiscount, variance,
109 Real forwardSk = Sk * dividendDiscount / riskFreeDiscount;
111 Real alpha = -2.0*std::log(riskFreeDiscount)/(variance);
112 Real beta = 2.0*std::log(dividendDiscount/riskFreeDiscount)/
114 Real h = 1 - riskFreeDiscount;
116 switch (payoff->optionType()) {
124 QL_FAIL(
"unknown option type");
127 Real temp_root = std::sqrt ((beta-1)*(beta-1) + (4*alpha)/h);
128 Real lambda = (-(beta-1) + phi * temp_root) / 2;
129 Real lambda_prime = - phi * alpha / (h*h * temp_root);
132 forwardSk, std::sqrt(variance)) * riskFreeDiscount;
133 Real hA = phi * (Sk - payoff->strike()) - black_Sk;
135 Real d1_Sk = (std::log(forwardSk/payoff->strike()) + 0.5*variance)
136 /std::sqrt(variance);
137 Real d2_Sk = d1_Sk - std::sqrt(variance);
138 Real part1 = forwardSk * normalDist(d1_Sk) /
139 (alpha * std::sqrt(variance));
140 Real part2 = - phi * forwardSk * cumNormalDist(phi * d1_Sk) *
141 std::log(dividendDiscount) / std::log(riskFreeDiscount);
142 Real part3 = + phi * payoff->strike() * cumNormalDist(phi * d2_Sk);
143 Real V_E_h = part1 + part2 + part3;
145 Real b = (1-h) * alpha * lambda_prime / (2*(2*lambda + beta - 1));
146 Real c = - ((1 - h) * alpha / (2 * lambda + beta - 1)) *
147 (V_E_h / (hA) + 1 / h + lambda_prime / (2*lambda + beta - 1));
148 Real temp_spot_ratio = std::log(spot / Sk);
149 Real chi = temp_spot_ratio * (b * temp_spot_ratio + c);
151 if (phi*(Sk-spot) > 0) {
152 results_.value = black.
value() +
153 hA * std::pow((spot/Sk), lambda) / (1 - chi);
154 Real temp_chi_prime = (2 * b / spot) * std::log(spot/Sk);
155 Real chi_prime = temp_chi_prime + c / spot;
156 Real chi_double_prime = 2*b/(spot*spot)
157 - temp_chi_prime / spot - c / (spot*spot);
158 Real d1_S = (std::log(forwardPrice/payoff->strike()) + 0.5*variance)
159 / std::sqrt(variance);
162 results_.delta = phi * dividendDiscount * cumNormalDist (phi * d1_S)
163 + (lambda / (spot * (1 - chi)) + chi_prime / ((1 - chi)*(1 - chi))) *
164 (phi * (Sk - payoff->strike()) - black_Sk) * std::pow((spot/Sk), lambda);
166 results_.gamma = dividendDiscount * normalDist (phi*d1_S)
167 / (spot * std::sqrt(variance))
168 + (2 * lambda * chi_prime / (spot * (1 - chi) * (1 - chi))
169 + 2 * chi_prime * chi_prime / ((1 - chi) * (1 - chi) * (1 - chi))
170 + chi_double_prime / ((1 - chi) * (1 - chi))
171 + lambda * (lambda - 1) / (spot * spot * (1 - chi)))
172 * (phi * (Sk - payoff->strike()) - black_Sk)
173 * std::pow((spot/Sk), lambda);
175 results_.value = phi * (spot - payoff->strike());
176 results_.delta = phi;
static Real criticalPrice(const ext::shared_ptr< StrikedTypePayoff > &payoff, DiscountFactor riskFreeDiscount, DiscountFactor dividendDiscount, Real variance, Real tolerance=1e-6)
Black 1976 calculator class.
Real dividendRho(Time maturity) const
virtual Real delta(Real spot) const
Real vega(Time maturity) const
Real itmCashProbability() const
Real strikeSensitivity() const
virtual Real gamma(Real spot) const
virtual Real elasticity(Real spot) const
virtual Real thetaPerDay(Real spot, Time maturity) const
Real deltaForward() const
virtual Real theta(Real spot, Time maturity) const
Real rho(Time maturity) const
Cumulative normal distribution function.
Time yearFraction(const Date &, const Date &, const Date &refPeriodStart=Date(), const Date &refPeriodEnd=Date()) const
Returns the period between two dates as a fraction of year.
void calculate() const override
JuQuadraticApproximationEngine(ext::shared_ptr< GeneralizedBlackScholesProcess >)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Normal distribution function.
Real Time
continuous quantity with 1-year units
Real DiscountFactor
discount factor between dates
Real blackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)