29 static Real PI= 3.14159265358979323846264338327950;
32 class AnalyticDoubleBarrierBinaryEngine_helper
36 AnalyticDoubleBarrierBinaryEngine_helper(
37 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process,
38 const ext::shared_ptr<CashOrNothingPayoff> &
payoff,
39 const DoubleBarrierOption::arguments &arguments):
48 Size maxIteration = 100,
49 Real requiredConvergence = 1e-8);
52 Size maxIteration = 1000,
53 Real requiredConvergence = 1e-8);
57 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process_;
58 const ext::shared_ptr<CashOrNothingPayoff> &
payoff_;
59 const DoubleBarrierOption::arguments &arguments_;
64 Real AnalyticDoubleBarrierBinaryEngine_helper::payoffAtExpiry(
66 Size maxIteration,
Real requiredConvergence)
69 "positive spot value required");
72 "negative variance not allowed");
74 Time residualTime = process_->time(arguments_.exercise->lastDate());
76 "expiration time must be > 0");
80 Real barrier_lo = arguments_.barrier_lo;
81 Real barrier_hi = arguments_.barrier_hi;
86 Real q = process_->dividendYield()->zeroRate(residualTime,
91 Real beta = -0.25 * std::pow(( 2*
b/sigmaq - 1), 2) - 2 *
r/sigmaq;
92 Real Z = std::log(barrier_hi / barrier_lo);
93 Real factor = ((2*
PI*cash)/std::pow(Z,2));
94 Real lo_alpha = std::pow(spot/barrier_lo,
alpha);
95 Real hi_alpha = std::pow(spot/barrier_hi,
alpha);
97 Real tot = 0, term = 0;
98 for (
Size i = 1 ; i < maxIteration ; ++i)
100 Real term1 = (lo_alpha-std::pow(-1.0, (
int)i)*hi_alpha) /
101 (std::pow(
alpha,2)+std::pow(i*PI/Z, 2));
102 Real term2 = std::sin(i*PI/Z * std::log(spot/barrier_lo));
104 term = factor * i * term1 * term2 * term3;
110 QL_REQUIRE(std::fabs(term) < requiredConvergence,
"serie did not converge sufficiently fast");
113 return std::max(tot, 0.0);
115 Rate discount = process_->riskFreeRate()->discount(
116 arguments_.exercise->lastDate());
118 "positive discount required");
119 return std::max(cash * discount - tot, 0.0);
124 Real AnalyticDoubleBarrierBinaryEngine_helper::payoffKIKO(
126 Size maxIteration,
Real requiredConvergence)
129 "positive spot value required");
132 "negative variance not allowed");
134 Time residualTime = process_->time(arguments_.exercise->lastDate());
136 "expiration time must be > 0");
139 Real barrier_lo = arguments_.barrier_lo;
140 Real barrier_hi = arguments_.barrier_hi;
142 std::swap(barrier_lo, barrier_hi);
147 Real q = process_->dividendYield()->zeroRate(residualTime,
152 Real beta = -0.25 * std::pow(( 2*
b/sigmaq - 1), 2) - 2 *
r/sigmaq;
153 Real Z = std::log(barrier_hi / barrier_lo);
154 Real log_S_L = std::log(spot / barrier_lo);
156 Real tot = 0, term = 0;
157 for (
Size i = 1 ; i < maxIteration ; ++i)
159 Real factor = std::pow(i*PI/Z,2)-
beta;
160 Real term1 = (
beta - std::pow(i*PI/Z,2) * std::exp(-0.5*factor*
variance)) / factor;
161 Real term2 = std::sin(i * PI/Z * log_S_L);
162 term = (2.0/(i*
PI)) * term1 * term2;
165 tot += 1 - log_S_L / Z;
166 tot *= cash*std::pow(spot/barrier_lo,
alpha);
169 QL_REQUIRE(fabs(term) < requiredConvergence,
"serie did not converge sufficiently fast");
171 return std::max(tot, 0.0);
175 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
176 : process_(
std::move(process)) {
184 ext::shared_ptr<AmericanExercise> ex =
185 ext::dynamic_pointer_cast<AmericanExercise>(
187 QL_REQUIRE(ex,
"KIKO/KOKI options must have American exercise");
189 process_->blackVolatility()->referenceDate(),
190 "American option with window exercise not handled yet");
192 ext::shared_ptr<EuropeanExercise> ex =
193 ext::dynamic_pointer_cast<EuropeanExercise>(
195 QL_REQUIRE(ex,
"non-European exercise given");
197 ext::shared_ptr<CashOrNothingPayoff>
payoff =
198 ext::dynamic_pointer_cast<CashOrNothingPayoff>(
arguments_.payoff);
202 QL_REQUIRE(spot > 0.0,
"negative or null underlying given");
205 process_->blackVolatility()->blackVariance(
212 "positive low barrier value required");
214 "positive high barrier value required");
216 "barrier_lo must be < barrier_hi");
221 "Unsupported barrier type");
224 switch (barrierType) {
226 if (spot <= barrier_lo || spot >= barrier_hi) {
238 if (spot <= barrier_lo || spot >= barrier_hi) {
250 if (spot >= barrier_hi) {
258 }
else if (spot <= barrier_lo) {
270 if (spot <= barrier_lo) {
278 }
else if (spot >= barrier_hi) {
290 AnalyticDoubleBarrierBinaryEngine_helper helper(
process_,
analytic binary double barrier (one-touch double barrier) option engine
void calculate() const override
AnalyticDoubleBarrierBinaryEngine(ext::shared_ptr< GeneralizedBlackScholesProcess >)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
DoubleBarrier::Type barrierType
DoubleBarrierOption::results results_
DoubleBarrierOption::arguments arguments_
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Option exercise classes and payoff function.
ext::function< Real(Real)> b
LinearInterpolation variance
const ext::shared_ptr< Payoff > payoff_
@ NoFrequency
null frequency
Real Time
continuous quantity with 1-year units
std::size_t Size
size of a container
ext::shared_ptr< QuantLib::Payoff > payoff
ext::shared_ptr< YieldTermStructure > q
ext::shared_ptr< YieldTermStructure > r
@ KOKI
lower barrier KI, upper KO