Coverage Report

Created: 2026-03-31 07:01

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/methods/lattices/binomialtree.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
8
 This file is part of QuantLib, a free-software/open-source library
9
 for financial quantitative analysts and developers - http://quantlib.org/
10
11
 QuantLib is free software: you can redistribute it and/or modify it
12
 under the terms of the QuantLib license.  You should have received a
13
 copy of the license along with this program; if not, please email
14
 <quantlib-dev@lists.sf.net>. The license is also available online at
15
 <https://www.quantlib.org/license.shtml>.
16
17
 This program is distributed in the hope that it will be useful, but WITHOUT
18
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 FOR A PARTICULAR PURPOSE.  See the license for more details.
20
*/
21
22
#include <ql/methods/lattices/binomialtree.hpp>
23
#include <ql/math/distributions/binomialdistribution.hpp>
24
#include <ql/stochasticprocess.hpp>
25
26
namespace QuantLib {
27
28
    JarrowRudd::JarrowRudd(
29
                        const ext::shared_ptr<StochasticProcess1D>& process,
30
                        Time end, Size steps, Real)
31
0
    : EqualProbabilitiesBinomialTree<JarrowRudd>(process, end, steps) {
32
        // drift removed
33
0
        up_ = process->stdDeviation(0.0, x0_, dt_);
34
0
    }
35
36
37
    CoxRossRubinstein::CoxRossRubinstein(
38
                        const ext::shared_ptr<StochasticProcess1D>& process,
39
                        Time end, Size steps, Real)
40
0
    : EqualJumpsBinomialTree<CoxRossRubinstein>(process, end, steps) {
41
42
0
        dx_ = process->stdDeviation(0.0, x0_, dt_);
43
0
        pu_ = 0.5 + 0.5*driftPerStep_/dx_;;
44
0
        pd_ = 1.0 - pu_;
45
46
0
        QL_REQUIRE(pu_<=1.0, "negative probability");
47
0
        QL_REQUIRE(pu_>=0.0, "negative probability");
48
0
    }
49
50
51
    AdditiveEQPBinomialTree::AdditiveEQPBinomialTree(
52
                        const ext::shared_ptr<StochasticProcess1D>& process,
53
                        Time end, Size steps, Real)
54
0
    : EqualProbabilitiesBinomialTree<AdditiveEQPBinomialTree>(process,
55
0
                                                              end, steps) {
56
0
        up_ = - 0.5 * driftPerStep_ + 0.5 *
57
0
            std::sqrt(4.0*process->variance(0.0, x0_, dt_)-
58
0
                      3.0*driftPerStep_*driftPerStep_);
59
0
    }
60
61
62
    Trigeorgis::Trigeorgis(
63
                        const ext::shared_ptr<StochasticProcess1D>& process,
64
                        Time end, Size steps, Real)
65
0
    : EqualJumpsBinomialTree<Trigeorgis>(process, end, steps) {
66
67
0
        dx_ = std::sqrt(process->variance(0.0, x0_, dt_)+
68
0
                        driftPerStep_*driftPerStep_);
69
0
        pu_ = 0.5 + 0.5*driftPerStep_/dx_;;
70
0
        pd_ = 1.0 - pu_;
71
72
0
        QL_REQUIRE(pu_<=1.0, "negative probability");
73
0
        QL_REQUIRE(pu_>=0.0, "negative probability");
74
0
    }
75
76
77
    Tian::Tian(const ext::shared_ptr<StochasticProcess1D>& process,
78
               Time end, Size steps, Real)
79
0
    : BinomialTree<Tian>(process, end, steps) {
80
81
0
        Real q = std::exp(process->variance(0.0, x0_, dt_));
82
0
        Real r = std::exp(driftPerStep_)*std::sqrt(q);
83
84
0
        up_ = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3));
85
0
        down_ = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3));
86
87
0
        pu_ = (r - down_) / (up_ - down_);
88
0
        pd_ = 1.0 - pu_;
89
90
        // doesn't work
91
        //     treeCentering_ = (up_+down_)/2.0;
92
        //     up_ = up_-treeCentering_;
93
94
0
        QL_REQUIRE(pu_<=1.0, "negative probability");
95
0
        QL_REQUIRE(pu_>=0.0, "negative probability");
96
0
    }
97
98
99
    LeisenReimer::LeisenReimer(const ext::shared_ptr<StochasticProcess1D>& process,
100
                               Time end,
101
                               Size steps,
102
                               Real strike)
103
0
    : BinomialTree<LeisenReimer>(process, end, ((steps % 2) != 0U ? steps : (steps + 1))) {
104
105
0
        QL_REQUIRE(strike>0.0, "strike must be positive");
106
0
        Size oddSteps = ((steps % 2) != 0U ? steps : (steps + 1));
107
0
        Real variance = process->variance(0.0, x0_, end);
108
0
        Real ermqdt = std::exp(driftPerStep_ + 0.5*variance/oddSteps);
109
0
        Real d2 = (std::log(x0_/strike) + driftPerStep_*oddSteps ) /
110
0
                                                          std::sqrt(variance);
111
0
        pu_ = PeizerPrattMethod2Inversion(d2, oddSteps);
112
0
        pd_ = 1.0 - pu_;
113
0
        Real pdash = PeizerPrattMethod2Inversion(d2+std::sqrt(variance),
114
0
                                                 oddSteps);
115
0
        up_ = ermqdt * pdash / pu_;
116
0
        down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);
117
0
    }
118
119
0
    Real Joshi4::computeUpProb(Real k, Real dj) const {
120
0
        Real alpha = dj/(std::sqrt(8.0));
121
0
        Real alpha2 = alpha*alpha;
122
0
        Real alpha3 = alpha*alpha2;
123
0
        Real alpha5 = alpha3*alpha2;
124
0
        Real alpha7 = alpha5*alpha2;
125
0
        Real beta = -0.375*alpha-alpha3;
126
0
        Real gamma = (5.0/6.0)*alpha5 + (13.0/12.0)*alpha3
127
0
            +(25.0/128.0)*alpha;
128
0
        Real delta = -0.1025 *alpha- 0.9285 *alpha3
129
0
            -1.43 *alpha5 -0.5 *alpha7;
130
0
        Real p =0.5;
131
0
        Real rootk = std::sqrt(k);
132
0
        p+= alpha/rootk;
133
0
        p+= beta /(k*rootk);
134
0
        p+= gamma/(k*k*rootk);
135
        // delete next line to get results for j three tree
136
0
        p+= delta/(k*k*k*rootk);
137
0
        return p;
138
0
    }
139
140
    Joshi4::Joshi4(const ext::shared_ptr<StochasticProcess1D>& process,
141
                   Time end,
142
                   Size steps,
143
                   Real strike)
144
0
    : BinomialTree<Joshi4>(process, end, (steps % 2) != 0U ? steps : (steps + 1)) {
145
146
0
        QL_REQUIRE(strike>0.0, "strike must be positive");
147
0
        Size oddSteps = (steps % 2) != 0U ? steps : (steps + 1);
148
0
        Real variance = process->variance(0.0, x0_, end);
149
0
        Real ermqdt = std::exp(driftPerStep_ + 0.5*variance/oddSteps);
150
0
        Real d2 = (std::log(x0_/strike) + driftPerStep_*oddSteps ) /
151
0
                                                          std::sqrt(variance);
152
0
        pu_ = computeUpProb((oddSteps-1.0)/2.0,d2 );
153
0
        pd_ = 1.0 - pu_;
154
0
        Real pdash = computeUpProb((oddSteps-1.0)/2.0,d2+std::sqrt(variance));
155
0
        up_ = ermqdt * pdash / pu_;
156
0
        down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);
157
0
    }
158
}