/src/quantlib/ql/experimental/lattices/extendedbinomialtree.cpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2001, 2002, 2003 Sadruddin Rejeb |
5 | | Copyright (C) 2003 Ferdinando Ametrano |
6 | | Copyright (C) 2005 StatPro Italia srl |
7 | | Copyright (C) 2008 John Maiden |
8 | | |
9 | | This file is part of QuantLib, a free-software/open-source library |
10 | | for financial quantitative analysts and developers - http://quantlib.org/ |
11 | | |
12 | | QuantLib is free software: you can redistribute it and/or modify it |
13 | | under the terms of the QuantLib license. You should have received a |
14 | | copy of the license along with this program; if not, please email |
15 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
16 | | <https://www.quantlib.org/license.shtml>. |
17 | | |
18 | | This program is distributed in the hope that it will be useful, but WITHOUT |
19 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
20 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
21 | | */ |
22 | | |
23 | | #include <ql/experimental/lattices/extendedbinomialtree.hpp> |
24 | | #include <ql/math/distributions/binomialdistribution.hpp> |
25 | | |
26 | | namespace QuantLib { |
27 | | |
28 | | ExtendedJarrowRudd::ExtendedJarrowRudd( |
29 | | const ext::shared_ptr<StochasticProcess1D>& process, |
30 | | Time end, Size steps, Real) |
31 | 0 | : ExtendedEqualProbabilitiesBinomialTree<ExtendedJarrowRudd>( |
32 | 0 | process, end, steps) { |
33 | | // drift removed |
34 | 0 | up_ = process->stdDeviation(0.0, x0_, dt_); |
35 | 0 | } |
36 | | |
37 | 0 | Real ExtendedJarrowRudd::upStep(Time stepTime) const { |
38 | 0 | return treeProcess_->stdDeviation(stepTime, x0_, dt_); |
39 | 0 | } |
40 | | |
41 | | |
42 | | |
43 | | ExtendedCoxRossRubinstein::ExtendedCoxRossRubinstein( |
44 | | const ext::shared_ptr<StochasticProcess1D>& process, |
45 | | Time end, Size steps, Real) |
46 | 0 | : ExtendedEqualJumpsBinomialTree<ExtendedCoxRossRubinstein>( |
47 | 0 | process, end, steps) { |
48 | |
|
49 | 0 | dx_ = process->stdDeviation(0.0, x0_, dt_); |
50 | 0 | pu_ = 0.5 + 0.5*this->driftStep(0.0)/dx_; |
51 | 0 | pd_ = 1.0 - pu_; |
52 | |
|
53 | 0 | QL_REQUIRE(pu_<=1.0, "negative probability"); |
54 | 0 | QL_REQUIRE(pu_>=0.0, "negative probability"); |
55 | 0 | } |
56 | | |
57 | 0 | Real ExtendedCoxRossRubinstein::dxStep(Time stepTime) const { |
58 | 0 | return this->treeProcess_->stdDeviation(stepTime, x0_, dt_); |
59 | 0 | } |
60 | | |
61 | 0 | Real ExtendedCoxRossRubinstein::probUp(Time stepTime) const { |
62 | 0 | return 0.5 + 0.5*this->driftStep(stepTime)/dxStep(stepTime); |
63 | 0 | } |
64 | | |
65 | | |
66 | | ExtendedAdditiveEQPBinomialTree::ExtendedAdditiveEQPBinomialTree( |
67 | | const ext::shared_ptr<StochasticProcess1D>& process, |
68 | | Time end, Size steps, Real) |
69 | 0 | : ExtendedEqualProbabilitiesBinomialTree<ExtendedAdditiveEQPBinomialTree>( |
70 | 0 | process, end, steps) { |
71 | |
|
72 | 0 | up_ = - 0.5 * this->driftStep(0.0) + 0.5 * |
73 | 0 | std::sqrt(4.0*process->variance(0.0, x0_, dt_)- |
74 | 0 | 3.0*this->driftStep(0.0)*this->driftStep(0.0)); |
75 | 0 | } |
76 | | |
77 | 0 | Real ExtendedAdditiveEQPBinomialTree::upStep(Time stepTime) const { |
78 | 0 | return (- 0.5 * this->driftStep(stepTime) + 0.5 * |
79 | 0 | std::sqrt(4.0*this->treeProcess_->variance(stepTime, x0_, dt_)- |
80 | 0 | 3.0*this->driftStep(stepTime)*this->driftStep(stepTime))); |
81 | 0 | } |
82 | | |
83 | | |
84 | | |
85 | | |
86 | | ExtendedTrigeorgis::ExtendedTrigeorgis( |
87 | | const ext::shared_ptr<StochasticProcess1D>& process, |
88 | | Time end, Size steps, Real) |
89 | 0 | : ExtendedEqualJumpsBinomialTree<ExtendedTrigeorgis>(process, end, steps) { |
90 | |
|
91 | 0 | dx_ = std::sqrt(process->variance(0.0, x0_, dt_)+ |
92 | 0 | this->driftStep(0.0)*this->driftStep(0.0)); |
93 | 0 | pu_ = 0.5 + 0.5*this->driftStep(0.0) / ExtendedTrigeorgis::dxStep(0.0); |
94 | 0 | pd_ = 1.0 - pu_; |
95 | |
|
96 | 0 | QL_REQUIRE(pu_<=1.0, "negative probability"); |
97 | 0 | QL_REQUIRE(pu_>=0.0, "negative probability"); |
98 | 0 | } |
99 | | |
100 | 0 | Real ExtendedTrigeorgis::dxStep(Time stepTime) const { |
101 | 0 | return std::sqrt(this->treeProcess_->variance(stepTime, x0_, dt_)+ |
102 | 0 | this->driftStep(stepTime)*this->driftStep(stepTime)); |
103 | 0 | } |
104 | | |
105 | 0 | Real ExtendedTrigeorgis::probUp(Time stepTime) const { |
106 | 0 | return 0.5 + 0.5*this->driftStep(stepTime)/dxStep(stepTime); |
107 | 0 | } |
108 | | |
109 | | |
110 | | ExtendedTian::ExtendedTian( |
111 | | const ext::shared_ptr<StochasticProcess1D>& process, |
112 | | Time end, Size steps, Real) |
113 | 0 | : ExtendedBinomialTree<ExtendedTian>(process, end, steps) { |
114 | |
|
115 | 0 | Real q = std::exp(process->variance(0.0, x0_, dt_)); |
116 | |
|
117 | 0 | Real r = std::exp(this->driftStep(0.0))*std::sqrt(q); |
118 | |
|
119 | 0 | up_ = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3)); |
120 | 0 | down_ = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3)); |
121 | |
|
122 | 0 | pu_ = (r - down_) / (up_ - down_); |
123 | 0 | pd_ = 1.0 - pu_; |
124 | | |
125 | | // doesn't work |
126 | | // treeCentering_ = (up_+down_)/2.0; |
127 | | // up_ = up_-treeCentering_; |
128 | |
|
129 | 0 | QL_REQUIRE(pu_<=1.0, "negative probability"); |
130 | 0 | QL_REQUIRE(pu_>=0.0, "negative probability"); |
131 | 0 | } |
132 | | |
133 | 0 | Real ExtendedTian::underlying(Size i, Size index) const { |
134 | 0 | Time stepTime = i*this->dt_; |
135 | 0 | Real q = std::exp(this->treeProcess_->variance(stepTime, x0_, dt_)); |
136 | 0 | Real r = std::exp(this->driftStep(stepTime))*std::sqrt(q); |
137 | |
|
138 | 0 | Real up = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3)); |
139 | 0 | Real down = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3)); |
140 | |
|
141 | 0 | return x0_ * std::pow(down, Real(BigInteger(i)-BigInteger(index))) |
142 | 0 | * std::pow(up, Real(index)); |
143 | 0 | } |
144 | | |
145 | 0 | Real ExtendedTian::probability(Size i, Size, Size branch) const { |
146 | 0 | Time stepTime = i*this->dt_; |
147 | 0 | Real q = std::exp(this->treeProcess_->variance(stepTime, x0_, dt_)); |
148 | 0 | Real r = std::exp(this->driftStep(stepTime))*std::sqrt(q); |
149 | |
|
150 | 0 | Real up = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3)); |
151 | 0 | Real down = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3)); |
152 | |
|
153 | 0 | Real pu = (r - down) / (up - down); |
154 | 0 | Real pd = 1.0 - pu; |
155 | |
|
156 | 0 | return (branch == 1 ? pu : pd); |
157 | 0 | } |
158 | | |
159 | | |
160 | | ExtendedLeisenReimer::ExtendedLeisenReimer(const ext::shared_ptr<StochasticProcess1D>& process, |
161 | | Time end, |
162 | | Size steps, |
163 | | Real strike) |
164 | 0 | : ExtendedBinomialTree<ExtendedLeisenReimer>( |
165 | 0 | process, end, ((steps % 2) != 0U ? steps : steps + 1)), |
166 | 0 | end_(end), oddSteps_((steps % 2) != 0U ? steps : steps + 1), strike_(strike) { |
167 | |
|
168 | 0 | QL_REQUIRE(strike>0.0, "strike " << strike << "must be positive"); |
169 | 0 | Real variance = process->variance(0.0, x0_, end); |
170 | |
|
171 | 0 | Real ermqdt = std::exp(this->driftStep(0.0) + 0.5*variance/oddSteps_); |
172 | 0 | Real d2 = (std::log(x0_/strike) + this->driftStep(0.0)*oddSteps_ ) / |
173 | 0 | std::sqrt(variance); |
174 | |
|
175 | 0 | pu_ = PeizerPrattMethod2Inversion(d2, oddSteps_); |
176 | 0 | pd_ = 1.0 - pu_; |
177 | 0 | Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance), |
178 | 0 | oddSteps_); |
179 | 0 | up_ = ermqdt * pdash / pu_; |
180 | 0 | down_ = (ermqdt - pu_ * up_) / (1.0 - pu_); |
181 | 0 | } |
182 | | |
183 | 0 | Real ExtendedLeisenReimer::underlying(Size i, Size index) const { |
184 | 0 | Time stepTime = i*this->dt_; |
185 | 0 | Real variance = this->treeProcess_->variance(stepTime, x0_, end_); |
186 | 0 | Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/oddSteps_); |
187 | 0 | Real d2 = (std::log(x0_/strike_) + this->driftStep(stepTime)*oddSteps_ ) / |
188 | 0 | std::sqrt(variance); |
189 | |
|
190 | 0 | Real pu = PeizerPrattMethod2Inversion(d2, oddSteps_); |
191 | 0 | Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance), |
192 | 0 | oddSteps_); |
193 | 0 | Real up = ermqdt * pdash / pu; |
194 | 0 | Real down = (ermqdt - pu * up) / (1.0 - pu); |
195 | |
|
196 | 0 | return x0_ * std::pow(down, Real(BigInteger(i)-BigInteger(index))) |
197 | 0 | * std::pow(up, Real(index)); |
198 | 0 | } |
199 | | |
200 | 0 | Real ExtendedLeisenReimer::probability(Size i, Size, Size branch) const { |
201 | 0 | Time stepTime = i*this->dt_; |
202 | 0 | Real variance = this->treeProcess_->variance(stepTime, x0_, end_); |
203 | 0 | Real d2 = (std::log(x0_/strike_) + this->driftStep(stepTime)*oddSteps_ ) / |
204 | 0 | std::sqrt(variance); |
205 | |
|
206 | 0 | Real pu = PeizerPrattMethod2Inversion(d2, oddSteps_); |
207 | 0 | Real pd = 1.0 - pu; |
208 | |
|
209 | 0 | return (branch == 1 ? pu : pd); |
210 | 0 | } |
211 | | |
212 | | |
213 | | |
214 | 0 | Real ExtendedJoshi4::computeUpProb(Real k, Real dj) const { |
215 | 0 | Real alpha = dj/(std::sqrt(8.0)); |
216 | 0 | Real alpha2 = alpha*alpha; |
217 | 0 | Real alpha3 = alpha*alpha2; |
218 | 0 | Real alpha5 = alpha3*alpha2; |
219 | 0 | Real alpha7 = alpha5*alpha2; |
220 | 0 | Real beta = -0.375*alpha-alpha3; |
221 | 0 | Real gamma = (5.0/6.0)*alpha5 + (13.0/12.0)*alpha3 |
222 | 0 | +(25.0/128.0)*alpha; |
223 | 0 | Real delta = -0.1025 *alpha- 0.9285 *alpha3 |
224 | 0 | -1.43 *alpha5 -0.5 *alpha7; |
225 | 0 | Real p =0.5; |
226 | 0 | Real rootk= std::sqrt(k); |
227 | 0 | p+= alpha/rootk; |
228 | 0 | p+= beta /(k*rootk); |
229 | 0 | p+= gamma/(k*k*rootk); |
230 | | // delete next line to get results for j three tree |
231 | 0 | p+= delta/(k*k*k*rootk); |
232 | 0 | return p; |
233 | 0 | } |
234 | | |
235 | | ExtendedJoshi4::ExtendedJoshi4(const ext::shared_ptr<StochasticProcess1D>& process, |
236 | | Time end, |
237 | | Size steps, |
238 | | Real strike) |
239 | 0 | : ExtendedBinomialTree<ExtendedJoshi4>(process, end, ((steps % 2) != 0U ? steps : steps + 1)), |
240 | 0 | end_(end), oddSteps_((steps % 2) != 0U ? steps : steps + 1), strike_(strike) { |
241 | |
|
242 | 0 | QL_REQUIRE(strike>0.0, "strike " << strike << "must be positive"); |
243 | 0 | Real variance = process->variance(0.0, x0_, end); |
244 | |
|
245 | 0 | Real ermqdt = std::exp(this->driftStep(0.0) + 0.5*variance/oddSteps_); |
246 | 0 | Real d2 = (std::log(x0_/strike) + this->driftStep(0.0)*oddSteps_ ) / |
247 | 0 | std::sqrt(variance); |
248 | |
|
249 | 0 | pu_ = computeUpProb((oddSteps_-1.0)/2.0,d2 ); |
250 | 0 | pd_ = 1.0 - pu_; |
251 | 0 | Real pdash = computeUpProb((oddSteps_-1.0)/2.0,d2+std::sqrt(variance)); |
252 | 0 | up_ = ermqdt * pdash / pu_; |
253 | 0 | down_ = (ermqdt - pu_ * up_) / (1.0 - pu_); |
254 | 0 | } |
255 | | |
256 | 0 | Real ExtendedJoshi4::underlying(Size i, Size index) const { |
257 | 0 | Time stepTime = i*this->dt_; |
258 | 0 | Real variance = this->treeProcess_->variance(stepTime, x0_, end_); |
259 | 0 | Real ermqdt = std::exp(this->driftStep(stepTime) + 0.5*variance/oddSteps_); |
260 | 0 | Real d2 = (std::log(x0_/strike_) + this->driftStep(stepTime)*oddSteps_ ) / |
261 | 0 | std::sqrt(variance); |
262 | |
|
263 | 0 | Real pu = computeUpProb((oddSteps_-1.0)/2.0,d2 ); |
264 | 0 | Real pdash = computeUpProb((oddSteps_-1.0)/2.0,d2+std::sqrt(variance)); |
265 | 0 | Real up = ermqdt * pdash / pu; |
266 | 0 | Real down = (ermqdt - pu * up) / (1.0 - pu); |
267 | |
|
268 | 0 | return x0_ * std::pow(down, Real(BigInteger(i)-BigInteger(index))) |
269 | 0 | * std::pow(up, Real(index)); |
270 | 0 | } |
271 | | |
272 | 0 | Real ExtendedJoshi4::probability(Size i, Size, Size branch) const { |
273 | 0 | Time stepTime = i*this->dt_; |
274 | 0 | Real variance = this->treeProcess_->variance(stepTime, x0_, end_); |
275 | 0 | Real d2 = (std::log(x0_/strike_) + this->driftStep(stepTime)*oddSteps_ ) / |
276 | 0 | std::sqrt(variance); |
277 | |
|
278 | 0 | Real pu = computeUpProb((oddSteps_-1.0)/2.0,d2 ); |
279 | 0 | Real pd = 1.0 - pu; |
280 | |
|
281 | 0 | return (branch == 1 ? pu : pd); |
282 | 0 | } |
283 | | |
284 | | } |