22#include <ql/exercise.hpp>
23#include <ql/math/distributions/bivariatenormaldistribution.hpp>
24#include <ql/math/distributions/normaldistribution.hpp>
25#include <ql/pricingengines/basket/stulzengine.hpp>
26#include <ql/pricingengines/blackcalculator.hpp>
27#include <ql/pricingengines/blackformula.hpp>
35 Real euroTwoAssetMinBasketCall(
Real forward1,
Real forward2,
41 Real stdDev1 = std::sqrt(variance1);
42 Real stdDev2 = std::sqrt(variance2);
44 Real variance = variance1 + variance2 - 2*rho*stdDev1*stdDev2;
45 Real stdDev = std::sqrt(variance);
47 Real modRho1 = (rho * stdDev2 - stdDev1) / stdDev;
48 Real modRho2 = (rho * stdDev1 - stdDev2) / stdDev;
50 Real D1 = (std::log(forward1/forward2) + 0.5*variance) / stdDev;
52 Real alfa, beta, gamma;
62 (std::log(forward1/strike) + 0.5*variance1) / stdDev1;
64 (std::log(forward2/strike) + 0.5*variance2) / stdDev2;
65 alfa = bivCNormMod1(D1_1, -D1);
66 beta = bivCNormMod2(D1_2, D1 - stdDev);
67 gamma = bivCNorm(D1_1 - stdDev1, D1_2 - stdDev2);
69 CumulativeNormalDistribution cum;
71 beta = cum(D1 - stdDev);
75 return riskFreeDiscount *
76 (forward1*alfa + forward2*beta - strike*gamma);
81 Real euroTwoAssetMaxBasketCall(
Real forward1,
Real forward2,
87 ext::shared_ptr<StrikedTypePayoff> payoff(
new
91 forward1, std::sqrt(variance1)) * riskFreeDiscount;
94 forward2, std::sqrt(variance2)) * riskFreeDiscount;
96 return black1 + black2 -
97 euroTwoAssetMinBasketCall(forward1, forward2, strike,
99 variance1, variance2, rho);
104 ext::shared_ptr<GeneralizedBlackScholesProcess> process2,
106 : process1_(
std::move(process1)), process2_(
std::move(process2)), rho_(correlation) {
114 "not an European Option");
116 ext::shared_ptr<EuropeanExercise> exercise =
118 QL_REQUIRE(exercise,
"not an European Option");
120 ext::shared_ptr<BasketPayoff> basket_payoff =
123 ext::shared_ptr<MinBasketPayoff> min_basket =
126 ext::shared_ptr<MaxBasketPayoff> max_basket =
128 QL_REQUIRE(min_basket || max_basket,
"unknown basket type");
130 ext::shared_ptr<PlainVanillaPayoff> payoff =
131 ext::dynamic_pointer_cast<PlainVanillaPayoff>(basket_payoff->basePayoff());
132 QL_REQUIRE(payoff,
"non-plain payoff given");
134 Real strike = payoff->strike();
136 Real variance1 =
process1_->blackVolatility()->blackVariance(
137 exercise->lastDate(), strike);
138 Real variance2 =
process2_->blackVolatility()->blackVariance(
139 exercise->lastDate(), strike);
142 process1_->riskFreeRate()->discount(exercise->lastDate());
146 process1_->dividendYield()->discount(exercise->lastDate());
148 process2_->dividendYield()->discount(exercise->lastDate());
151 dividendDiscount1 / riskFreeDiscount;
153 dividendDiscount2 / riskFreeDiscount;
155 if (max_basket !=
nullptr) {
156 switch (payoff->optionType()) {
160 euroTwoAssetMaxBasketCall(forward1, forward2, strike,
162 variance1, variance2,
169 euroTwoAssetMaxBasketCall(forward1, forward2, 0.0,
171 variance1, variance2,
rho_) +
172 euroTwoAssetMaxBasketCall(forward1, forward2, strike,
174 variance1, variance2,
rho_);
177 QL_FAIL(
"unknown option type");
179 }
else if (min_basket !=
nullptr) {
180 switch (payoff->optionType()) {
184 euroTwoAssetMinBasketCall(forward1, forward2, strike,
186 variance1, variance2,
192 euroTwoAssetMinBasketCall(forward1, forward2, 0.0,
194 variance1, variance2,
rho_) +
195 euroTwoAssetMinBasketCall(forward1, forward2, strike,
197 variance1, variance2,
rho_);
200 QL_FAIL(
"unknown option type");
203 QL_FAIL(
"unknown type");
BasketOption::results results_
BasketOption::arguments arguments_
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
ext::shared_ptr< Exercise > exercise
ext::shared_ptr< Payoff > payoff
ext::shared_ptr< GeneralizedBlackScholesProcess > process2_
ext::shared_ptr< GeneralizedBlackScholesProcess > process1_
StulzEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process1, ext::shared_ptr< GeneralizedBlackScholesProcess > process2, Real correlation)
void calculate() const override
Real DiscountFactor
discount factor between dates
BivariateCumulativeNormalDistributionWe04DP BivariateCumulativeNormalDistribution
default bivariate implementation
Real blackFormula(Option::Type optionType, Real strike, Real forward, Real stdDev, Real discount, Real displacement)