QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
Loading...
Searching...
No Matches
analyticpartialtimebarrieroptionengine.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2014 Master IMAFA - Polytech'Nice Sophia - Université de Nice Sophia Antipolis
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
20#include <ql/exercise.hpp>
24#include <utility>
25
26namespace QuantLib {
27
29 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
30 : process_(std::move(process)) {
32 }
33
35 const ext::shared_ptr<PlainVanillaPayoff>& payoff,
36 const ext::shared_ptr<GeneralizedBlackScholesProcess>& process) const {
37 Barrier::Type barrierType = arguments.barrierType;
38 PartialBarrier::Range barrierRange = arguments.barrierRange;
39 Rate r = process->riskFreeRate()->zeroRate(residualTime(), Continuous,
41 Rate q = process->dividendYield()->zeroRate(residualTime(), Continuous,
43 Real barrier = arguments.barrier;
44 Real strike = payoff->strike();
45
46 switch (barrierType) {
48 switch (barrierRange) {
50 return CA(1, barrier, strike, r, q);
52 return CoB1(barrier, strike, r, q);
54 return CoB2(Barrier::DownOut, barrier, strike, r, q);
55 default:
56 QL_FAIL("invalid barrier range");
57 }
58 break;
59
60 case Barrier::DownIn:
61 switch (barrierRange) {
63 return CIA(1, barrier, strike, r, q);
66 QL_FAIL("Down-and-in partial-time end barrier is not implemented");
67 default:
68 QL_FAIL("invalid barrier range");
69 }
70 break;
71
72 case Barrier::UpOut:
73 switch (barrierRange) {
75 return CA(-1, barrier, strike, r, q);
77 return CoB1(barrier, strike, r, q);
79 return CoB2(Barrier::UpOut, barrier, strike, r, q);
80 default:
81 QL_FAIL("invalid barrier range");
82 }
83 break;
84
85 case Barrier::UpIn:
86 switch (barrierRange) {
88 return CIA(-1, barrier, strike, r, q);
91 QL_FAIL("Up-and-in partial-time end barrier is not implemented");
92 default:
93 QL_FAIL("invalid barrier range");
94 }
95 break;
96 default:
97 QL_FAIL("unknown barrier type");
98 }
99 }
100
102 ext::shared_ptr<PlainVanillaPayoff> payoff =
103 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
104 QL_REQUIRE(payoff, "non-plain payoff given");
105 QL_REQUIRE(payoff->strike()>0.0,
106 "strike must be positive");
107
108 Real spot = process_->x0();
109 QL_REQUIRE(spot > 0.0, "negative or null underlying given");
110
111 auto getSymmetricBarrierType = [](Barrier::Type barrierType) -> Barrier::Type {
112 if (barrierType == Barrier::UpIn) return Barrier::DownIn;
113 if (barrierType == Barrier::DownIn) return Barrier::UpIn;
114 if (barrierType == Barrier::UpOut) return Barrier::DownOut;
115 return Barrier::UpOut;
116 };
117
118 auto tmp_arguments_ = arguments_;
119 if (payoff->optionType() == Option::Put)
120 {
121 Real spotSq = spot * spot;
122 Real callStrike = spotSq / payoff->strike();
123 ext::shared_ptr<PlainVanillaPayoff> callPayoff =
124 ext::make_shared<PlainVanillaPayoff>(Option::Call, callStrike);
125 tmp_arguments_.barrierType = getSymmetricBarrierType(arguments_.barrierType);
126 tmp_arguments_.barrier = spotSq / arguments_.barrier;
127 tmp_arguments_.payoff = callPayoff;
128 auto callProcess = ext::make_shared<GeneralizedBlackScholesProcess>(
129 process_->stateVariable(),
130 process_->riskFreeRate(),
131 process_->dividendYield(),
132 process_->blackVolatility()
133 );
134
135 results_.value = payoff->strike() / spot * calculate(tmp_arguments_, callPayoff, callProcess);
136 } else
137 results_.value = calculate(tmp_arguments_, payoff, process_);
138 }
139
141 Barrier::Type barrierType,
142 Real barrier, Real strike, Rate r, Rate q) const {
143 Real result = 0.0;
144 Real b = r - q;
145 Real T = residualTime();
146 Real S = underlying();
147 Real mu_ = mu(strike, b);
148 Real g1_ = g1(barrier, strike, b);
149 Real g2_ = g2(barrier, strike, b);
150 Real g3_ = g3(barrier, strike, b);
151 Real g4_ = g4(barrier, strike, b);
152 Real e1_ = e1(barrier, strike, b);
153 Real e2_ = e2(barrier, strike, b);
154 Real e3_ = e3(barrier, strike, b);
155 Real e4_ = e4(barrier, strike, b);
156 Real rho_ = rho();
157 Real HSMu = HS(S, barrier, 2 * mu_);
158 Real HSMu1 = HS(S, barrier, 2 * (mu_ + 1));
159 Real X1 = strike * std::exp(-r * T);
160
161 if (strike < barrier){
162 switch (barrierType) {
163 case Barrier::DownOut:
164 result = S * std::exp((b - r) * T);
165 result *= (M(g1_, e1_, rho_) - HSMu1 * M(g3_, -e3_, -rho_));
166 result -= X1 * (M(g2_, e2_, rho_)-HSMu*M(g4_, -e4_, -rho_));
167 return result;
168
169 case Barrier::UpOut:
170 result = S * std::exp((b - r) * T);
171 result *= (M(-g1_, -e1_, rho_) - HSMu1 * M(-g3_, e3_, -rho_));
172 result -= X1 * (M(-g2_, -e2_, rho_) - HSMu * M(-g4_, e4_, -rho_));
173 result -= S * std::exp((b - r) * T) *
174 (M(-d1(strike, b), -e1_, rho_) - HSMu1 *
175 M(e3_, -f1(barrier, strike, b),-rho_));
176 result += X1 * (M(-d2(strike, b), -e2_, rho_) - HSMu *
177 M(e4_, -f2(barrier, strike, b), -rho_));
178 return result;
179
180 default:
181 QL_FAIL("invalid barrier type");
182 }
183 } else {
184 QL_FAIL("case of strike>barrier is not implemented for OutEnd B2 type");
185 }
186 }
187
189 Real result = 0.0;
190 Rate b = r - q;
191 Real T = residualTime();
192 Real S = underlying();
193 Real mu_ = mu(strike, b);
194 Real g1_ = g1(barrier, strike, b);
195 Real g2_ = g2(barrier, strike, b);
196 Real g3_ = g3(barrier, strike, b);
197 Real g4_ = g4(barrier, strike, b);
198 Real e1_ = e1(barrier, strike, b);
199 Real e2_ = e2(barrier, strike, b);
200 Real e3_ = e3(barrier, strike, b);
201 Real e4_ = e4(barrier, strike, b);
202 Real rho_ = rho();
203 Real HSMu = HS(S, barrier, 2 * mu_);
204 Real HSMu1 = HS(S, barrier, 2 * (mu_ + 1));
205 Real X1 = strike * std::exp(-r * T);
206
207 if (strike > barrier) {
208 result = S * std::exp((b - r) * T);
209 result *= (M(d1(strike, b), e1_, rho_) - HSMu1 * M(f1(barrier, strike, b), -e3_, -rho_));
210 result -= X1 * (M(d2(strike, b), e2_, rho_) - HSMu * M(f2(barrier, strike, b), -e4_, -rho_));
211 return result;
212 } else {
213 Real S1 = S * std::exp((b - r) * T);
214 result = S1;
215 result *= (M(-g1_, -e1_, rho_) - HSMu1 * M(-g3_,e3_,-rho_));
216 result -= X1 * (M(-g2_, -e2_, rho_) - HSMu * M(-g4_, e4_, -rho_));
217 result -= S1 * (M(-d1(strike, b), -e1_, rho_) - HSMu1 * M(-f1(barrier, strike, b), e3_, -rho_));
218 result += X1 * (M(-d2(strike, b), -e2_, rho_) - HSMu * M(-f2(barrier, strike, b), e4_, -rho_));
219 result += S1 * (M(g1_, e1_, rho_) - HSMu1 * M(g3_, -e3_, -rho_));
220 result -= X1 * (M(g2_, e2_, rho_) - HSMu * M(g4_, -e4_, -rho_));
221 return result;
222 }
223 }
224
225 // eta = -1: Up-and-In Call
226 // eta = 1: Down-and-In Call
228 ext::shared_ptr<EuropeanExercise> exercise =
229 ext::dynamic_pointer_cast<EuropeanExercise>(arguments_.exercise);
230
231 ext::shared_ptr<PlainVanillaPayoff> payoff =
232 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
233
234 VanillaOption europeanOption(payoff, exercise);
235
236 europeanOption.setPricingEngine(
237 ext::make_shared<AnalyticEuropeanEngine>(process_));
238
239 return europeanOption.NPV() - CA(eta, barrier, strike, r, q);
240 }
241
243 //Partial-Time-Start- OUT Call Option calculation
244 Real b = r - q;
245 Real rho_ = rho();
246 Real T = residualTime();
247 Real S = underlying();
248 Real mu_ = mu(strike, b);
249 Real e1_ = e1(barrier, strike, b);
250 Real e2_ = e2(barrier, strike, b);
251 Real e3_ = e3(barrier, strike, b);
252 Real e4_ = e4(barrier, strike, b);
253 Real HSMu = HS(S, barrier,2 * mu_);
254 Real HSMu1 = HS(S, barrier, 2 * (mu_ + 1));
255
256 Real result;
257 result = S * std::exp((b - r) * T);
258 result *= (M(d1(strike, b), eta * e1_, eta * rho_)-HSMu1 *
259 M(f1(barrier, strike, b), eta * e3_, eta * rho_));
260 result -= (strike * std::exp(-r * T) *
261 (M(d2(strike, b),eta * e2_, eta * rho_) - HSMu *
262 M(f2(barrier, strike, b), eta * e4_, eta * rho_)));
263 return result;
264 }
265
267 return process_->x0();
268 }
269
271 return process_->time(arguments_.exercise->lastDate());
272 }
273
275 return process_->time(arguments_.coverEventDate);
276 }
277
279 return process_->blackVolatility()->blackVol(t, strike);
280 }
281
283 Real S = underlying();
284 Real T = residualTime();
285 Real sigma = volatility(T, strike);
286 return (std::log(S / strike) + 2 * std::log(barrier / S) +
287 (b + (std::pow(sigma, 2) / 2))*T) / (sigma*std::sqrt(T));
288 }
289
291 Time T = residualTime();
292 return f1(barrier, strike, b) - volatility(T, strike) * std::sqrt(T);
293 }
294
297 return CmlNormDist(a,b);
298 }
299
301 return std::sqrt(coverEventTime() / residualTime());
302 }
303
305 Volatility vol = volatility(coverEventTime(), strike);
306 return (b - (vol * vol) / 2) / (vol * vol);
307 }
308
310 Time T2 = residualTime();
311 Volatility vol = volatility(T2, strike);
312 return (std::log(underlying() / strike) + (b + vol * vol / 2) * T2) / (std::sqrt(T2) * vol);
313 }
314
316 Time T2 = residualTime();
317 Volatility vol = volatility(T2, strike);
318 return d1(strike, b) - vol * std::sqrt(T2);
319 }
320
322 Time T1 = coverEventTime();
323 Volatility vol = volatility(T1, strike);
324 return (std::log(underlying() / barrier) + (b + vol * vol / 2) * T1) / (std::sqrt(T1) * vol);
325 }
326
328 Time T1 = coverEventTime();
329 Volatility vol = volatility(T1, strike);
330 return e1(barrier, strike, b) - vol * std::sqrt(T1);
331 }
332
334 Time T1 = coverEventTime();
335 Real vol = volatility(T1, strike);
336 return e1(barrier, strike, b) + (2 * std::log(barrier / underlying()) / (vol * std::sqrt(T1)));
337 }
338
341 return e3(barrier, strike, b) - volatility(t, strike) * std::sqrt(t);
342 }
343
345 Time T2 = residualTime();
346 Volatility vol = volatility(T2, strike);
347 return (std::log(underlying() / barrier) + (b + vol * vol / 2) * T2) / (std::sqrt(T2) * vol);
348 }
349
351 Time T2 = residualTime();
352 Volatility vol = volatility(T2, strike);
353 return g1(barrier, strike, b) - vol * std::sqrt(T2);
354 }
355
357 Time T2 = residualTime();
358 Real vol = volatility(T2, strike);
359 return g1(barrier, strike, b) + (2 * std::log(barrier / underlying()) /(vol * std::sqrt(T2)));
360 }
361
363 Time T2 = residualTime();
364 Real vol = volatility(T2, strike);
365 return g3(barrier, strike, b) - vol * std::sqrt(T2);
366 }
367
369 return std::pow((H / S), power);
370 }
371
372}
373
Analytic European engine.
bivariate cumulative normal distribution
Real CA(Integer n, Real barrier, Real strike, Rate r, Rate q) const
Real CIA(Integer n, Real barrier, Real strike, Rate r, Rate q) const
AnalyticPartialTimeBarrierOptionEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
Real CoB2(Barrier::Type barrierType, Real barrier, Real strike, Rate r, Rate q) const
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
Real CoB1(Real barrier, Real strike, Rate r, Rate q) const
Cumulative bivariate normal distribution function.
Real NPV() const
returns the net present value of the instrument.
Definition: instrument.hpp:167
void setPricingEngine(const ext::shared_ptr< PricingEngine > &)
set the pricing engine to be used.
Definition: instrument.cpp:35
std::pair< iterator, bool > registerWith(const ext::shared_ptr< Observable > &)
Definition: observable.hpp:226
ext::shared_ptr< Exercise > exercise
Definition: option.hpp:65
ext::shared_ptr< Payoff > payoff
Definition: option.hpp:64
Arguments for partial-time barrier option calculation
Vanilla option (no discrete dividends, no barriers) on a single asset.
const DefaultType & t
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
Option exercise classes and payoff function.
std::function< Real(Real)> b
@ NoFrequency
null frequency
Definition: frequency.hpp:37
Real Time
continuous quantity with 1-year units
Definition: types.hpp:62
QL_REAL Real
real number
Definition: types.hpp:50
Real Volatility
volatility
Definition: types.hpp:78
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Rate
interest rates
Definition: types.hpp:70
Real rho
Real sigma
ext::shared_ptr< QuantLib::Payoff > payoff
Definition: any.hpp:37
STL namespace.
ext::shared_ptr< YieldTermStructure > q
ext::shared_ptr< YieldTermStructure > r
Analytic engine for partial-time barrier options.