QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
analyticpartialtimebarrieroptionengine.cpp
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>
21#include <ql/experimental/exoticoptions/analyticpartialtimebarrieroptionengine.hpp>
22#include <ql/math/distributions/bivariatenormaldistribution.hpp>
23#include <ql/pricingengines/vanilla/analyticeuropeanengine.hpp>
24#include <utility>
25
26namespace QuantLib {
27
29 ext::shared_ptr<GeneralizedBlackScholesProcess> process)
30 : process_(std::move(process)) {
32 }
33
35 ext::shared_ptr<PlainVanillaPayoff> payoff =
36 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
37 QL_REQUIRE(payoff, "non-plain payoff given");
38 QL_REQUIRE(payoff->strike()>0.0,
39 "strike must be positive");
40
41 Real spot = process_->x0();
42 QL_REQUIRE(spot > 0.0, "negative or null underlying given");
43
46
47 switch (payoff->optionType()) {
48 //Call Option
49 case Option::Call:
50 switch (barrierType) {
52 switch (barrierRange) {
54 results_.value = CA(1);
55 break;
58 break;
61 break;
62 default:
63 QL_FAIL("invalid barrier range");
64 }
65 break;
66
68 switch (barrierRange) {
70 results_.value = CIA(1);
71 break;
73 QL_FAIL("Down-and-in partial-time end barrier is not implemented");
74 default:
75 QL_FAIL("invalid barrier range");
76 }
77 break;
78
80 switch (barrierRange) {
82 results_.value = CA(-1);
83 break;
86 break;
89 break;
90 default:
91 QL_FAIL("invalid barrier range");
92 }
93 break;
94
96 switch (barrierRange) {
98 results_.value = CIA(-1);
99 break;
101 QL_FAIL("Up-and-in partial-time end barrier is not implemented");
102 default:
103 QL_FAIL("invalid barrier range");
104 }
105 break;
106 default:
107 QL_FAIL("unknown barrier type");
108 }
109 break;
110
111 case Option::Put:
112 QL_FAIL("Partial-time barrier Put option is not implemented");
113
114 default:
115 QL_FAIL("unknown option type");
116 }
117 }
118
120 PartialBarrier::Type barrierType) const {
121 Real result = 0.0;
123 if (strike()<barrier()){
124 switch (barrierType) {
126 result = underlying()*std::exp((b-riskFreeRate())*residualTime());
127 result *= (M(g1(),e1(),rho())-HS(underlying(),barrier(),2*(mu()+1))*M(g3(),-e3(),-rho()));
128 result -= strike()*std::exp(-riskFreeRate()*residualTime())*(M(g2(),e2(),rho())-HS(underlying(),barrier(),2*mu())*M(g4(),-e4(),-rho()));
129 return result;
130
132 result = underlying()*std::exp((b-riskFreeRate())*residualTime());
133 result *= (M(-g1(),-e1(),rho())-HS(underlying(),barrier(),2*(mu()+1))*M(-g3(),e3(),-rho()));
134 result -= strike()*std::exp(-riskFreeRate()*residualTime())*(M(-g2(),-e2(),rho())-HS(underlying(),barrier(),2*mu())*M(-g4(),e4(),-rho()));
135 result -= underlying()*std::exp((b-riskFreeRate())*residualTime())*(M(-d1(),-e1(),rho())-HS(underlying(),barrier(),2*(mu()+1))*M(e3(),-f1(),-rho()));
136 result += strike()*std::exp(-riskFreeRate()*residualTime())*(M(-d2(),-e2(),rho())-HS(underlying(),barrier(),2*mu())*M(e4(),-f2(),-rho()));
137 return result;
138
139 default:
140 QL_FAIL("invalid barrier type");
141 }
142 } else {
143 QL_FAIL("case of strike>barrier is not implemented for OutEnd B2 type");
144 }
145 }
146
148 Real result = 0.0;
150 if (strike()>barrier()) {
151 result = underlying()*std::exp((b-riskFreeRate())*residualTime());
152 result *= (M(d1(),e1(),rho())-HS(underlying(),barrier(),2*(mu()+1))*M(f1(),-e3(),-rho()));
153 result -= (strike()*std::exp(-riskFreeRate()*residualTime()))*(M(d2(),e2(),rho())-HS(underlying(),barrier(),2*mu())*M(f2(),-e4(),-rho()));
154 return result;
155 } else {
156 Real S1 = underlying()*std::exp((b-riskFreeRate())*residualTime());
157 Real X1 = (strike()*std::exp(-riskFreeRate()*residualTime()));
158 Real HS1 = HS(underlying(),barrier(),2*(mu()+1));
159 Real HS2 = HS(underlying(), barrier(), 2 * mu());
160 result = S1;
161 result *= (M(-g1(),-e1(),rho())-HS1*M(-g3(),e3(),-rho()));
162 result -= X1*(M(-g2(), -e2(), rho()) - HS2*M(-g4(), e4(), -rho()));
163 result -= S1*(M(-d1(), -e1(), rho()) - HS1*M(-f1(), e3(), -rho()));
164 result += X1*(M(-d2(), -e2(), rho()) - HS2*M(-f2(), e4(), -rho()));
165 result += S1*(M(g1(), e1(), rho()) - HS1*M(g3(), -e3(), -rho()));
166 result -= X1*(M(g2(), e2(), rho()) - HS2*M(g4(), -e4(), -rho()));
167 return result;
168 }
169 }
170
171 // eta = -1: Up-and-In Call
172 // eta = 1: Down-and-In Call
174 ext::shared_ptr<EuropeanExercise> exercise =
175 ext::dynamic_pointer_cast<EuropeanExercise>(arguments_.exercise);
176
177 ext::shared_ptr<PlainVanillaPayoff> payoff =
178 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
179
180 VanillaOption europeanOption(payoff, exercise);
181
182 europeanOption.setPricingEngine(
183 ext::make_shared<AnalyticEuropeanEngine>(process_));
184
185 return europeanOption.NPV() - CA(eta);
186 }
187
189 //Partial-Time-Start- OUT Call Option calculation
191 Real result;
192 result = underlying()*std::exp((b-riskFreeRate())*residualTime());
193 result *= (M(d1(),eta*e1(),eta*rho())-HS(underlying(),barrier(),2*(mu()+1))*M(f1(),eta*e3(),eta*rho()));
194 result -= (strike()*std::exp(-riskFreeRate()*residualTime())*(M(d2(),eta*e2(),eta*rho())-HS(underlying(),barrier(),2*mu())*M(f2(),eta*e4(),eta*rho())));
195 return result;
196 }
197
199 return process_->x0();
200 }
201
203 ext::shared_ptr<PlainVanillaPayoff> payoff =
204 ext::dynamic_pointer_cast<PlainVanillaPayoff>(arguments_.payoff);
205 QL_REQUIRE(payoff, "non-plain payoff given");
206 return payoff->strike();
207 }
208
210 return process_->time(arguments_.exercise->lastDate());
211 }
212
214 return process_->time(arguments_.coverEventDate);
215 }
216
218 return process_->blackVolatility()->blackVol(t, strike());
219 }
220
222 Time T = residualTime();
223 return volatility(T) * std::sqrt(T);
224 }
225
227 return arguments_.barrier;
228 }
229
231 return arguments_.rebate;
232 }
233
235 return process_->riskFreeRate()->zeroRate(residualTime(), Continuous,
237 }
238
240 return process_->riskFreeRate()->discount(residualTime());
241 }
242
244 return process_->dividendYield()->zeroRate(residualTime(), Continuous,
246 }
247
249 return process_->dividendYield()->discount(residualTime());
250 }
251
252
254 Real S = underlying();
255 Real T = residualTime();
256 Real sigma = volatility(T);
257 return (std::log(S / strike()) + 2 * std::log(barrier() / S) + ((riskFreeRate()-dividendYield()) + (std::pow(sigma, 2) / 2))*T) / (sigma*std::sqrt(T));
258 }
259
261 Time T = residualTime();
262 return f1() - volatility(T)*std::sqrt(T);
263 }
264
267 return CmlNormDist(a,b);
268 }
269
271 return std::sqrt(coverEventTime()/residualTime());
272 }
273
276 return ((riskFreeRate() - dividendYield()) - (vol * vol) / 2) / (vol * vol);
277 }
278
281 Time T2 = residualTime();
282 Volatility vol = volatility(T2);
283 return (std::log(underlying()/strike())+(b+vol*vol/2)*T2)/(std::sqrt(T2)*vol);
284 }
285
287 Time T2 = residualTime();
288 Volatility vol = volatility(T2);
289 return d1() - vol*std::sqrt(T2);
290 }
291
294 Time T1 = coverEventTime();
295 Volatility vol = volatility(T1);
296 return (std::log(underlying()/barrier())+(b+vol*vol/2)*T1)/(std::sqrt(T1)*vol);
297 }
298
300 Time T1 = coverEventTime();
301 Volatility vol = volatility(T1);
302 return e1() - vol*std::sqrt(T1);
303 }
304
306 Time T1 = coverEventTime();
307 Real vol = volatility(T1);
308 return e1()+(2*std::log(barrier()/underlying()) /(vol*std::sqrt(T1)));
309 }
310
312 Time t = coverEventTime();
313 return e3()-volatility(t)*std::sqrt(t);
314 }
315
318 Time T2 = residualTime();
319 Volatility vol = volatility(T2);
320 return (std::log(underlying()/barrier())+(b+vol*vol/2)*T2)/(std::sqrt(T2)*vol);
321 }
322
324 Time T2 = residualTime();
325 Volatility vol = volatility(T2);
326 return g1() - vol*std::sqrt(T2);
327 }
328
330 Time T2 = residualTime();
331 Real vol = volatility(T2);
332 return g1()+(2*std::log(barrier()/underlying()) /(vol*std::sqrt(T2)));
333 }
334
336 Time T2 = residualTime();
337 Real vol = volatility(T2);
338 return g3()-vol*std::sqrt(T2);
339 }
340
342 return std::pow((H/S),power);
343 }
344
345}
346
AnalyticPartialTimeBarrierOptionEngine(ext::shared_ptr< GeneralizedBlackScholesProcess > process)
ext::shared_ptr< GeneralizedBlackScholesProcess > process_
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:228
ext::shared_ptr< Exercise > exercise
Definition: option.hpp:65
ext::shared_ptr< Payoff > payoff
Definition: option.hpp:64
Vanilla option (no discrete dividends, no barriers) on a single asset.
@ 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 DiscountFactor
discount factor between dates
Definition: types.hpp:66
Real Volatility
volatility
Definition: types.hpp:78
QL_INTEGER Integer
integer number
Definition: types.hpp:35
Real Rate
interest rates
Definition: types.hpp:70
Definition: any.hpp:35
STL namespace.