Coverage Report

Created: 2026-10-31 06:47

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/stochasticprocess.hpp>
24
25
namespace QuantLib {
26
27
    JarrowRudd::JarrowRudd(
28
                        const ext::shared_ptr<StochasticProcess1D>& process,
29
                        Time end, Size steps, Real)
30
0
    : EqualProbabilitiesBinomialTree<JarrowRudd>(process, end, steps) {
31
        // drift removed
32
0
        up_ = process->stdDeviation(0.0, x0_, dt_);
33
0
    }
34
35
36
    CoxRossRubinstein::CoxRossRubinstein(
37
                        const ext::shared_ptr<StochasticProcess1D>& process,
38
                        Time end, Size steps, Real)
39
0
    : EqualJumpsBinomialTree<CoxRossRubinstein>(process, end, steps) {
40
41
0
        dx_ = process->stdDeviation(0.0, x0_, dt_);
42
0
        pu_ = 0.5 + 0.5*driftPerStep_/dx_;;
43
0
        pd_ = 1.0 - pu_;
44
45
0
        QL_REQUIRE(pu_<=1.0, "negative probability");
46
0
        QL_REQUIRE(pu_>=0.0, "negative probability");
47
0
    }
48
49
50
    AdditiveEQPBinomialTree::AdditiveEQPBinomialTree(
51
                        const ext::shared_ptr<StochasticProcess1D>& process,
52
                        Time end, Size steps, Real)
53
0
    : EqualProbabilitiesBinomialTree<AdditiveEQPBinomialTree>(process,
54
0
                                                              end, steps) {
55
0
        Real radicand = 4.0*process->variance(0.0, x0_, dt_)-
56
0
                        3.0*driftPerStep_*driftPerStep_;
57
0
        QL_REQUIRE(radicand >= 0.0,
58
0
                   "drift per step too large for the additive EQP tree: "
59
0
                   "more steps are needed");
60
0
        up_ = - 0.5 * driftPerStep_ + 0.5 * std::sqrt(radicand);
61
0
    }
62
63
64
    Trigeorgis::Trigeorgis(
65
                        const ext::shared_ptr<StochasticProcess1D>& process,
66
                        Time end, Size steps, Real)
67
0
    : EqualJumpsBinomialTree<Trigeorgis>(process, end, steps) {
68
69
0
        dx_ = std::sqrt(process->variance(0.0, x0_, dt_)+
70
0
                        driftPerStep_*driftPerStep_);
71
0
        pu_ = 0.5 + 0.5*driftPerStep_/dx_;;
72
0
        pd_ = 1.0 - pu_;
73
74
0
        QL_REQUIRE(pu_<=1.0, "negative probability");
75
0
        QL_REQUIRE(pu_>=0.0, "negative probability");
76
0
    }
77
78
79
    Tian::Tian(const ext::shared_ptr<StochasticProcess1D>& process,
80
               Time end, Size steps, Real)
81
0
    : BinomialTree<Tian>(process, end, steps) {
82
83
0
        Real q = std::exp(process->variance(0.0, x0_, dt_));
84
0
        Real r = std::exp(driftPerStep_)*std::sqrt(q);
85
86
0
        up_ = 0.5 * r * q * (q + 1 + std::sqrt(q * q + 2 * q - 3));
87
0
        down_ = 0.5 * r * q * (q + 1 - std::sqrt(q * q + 2 * q - 3));
88
89
0
        pu_ = (r - down_) / (up_ - down_);
90
0
        pd_ = 1.0 - pu_;
91
92
        // doesn't work
93
        //     treeCentering_ = (up_+down_)/2.0;
94
        //     up_ = up_-treeCentering_;
95
96
0
        QL_REQUIRE(pu_<=1.0, "negative probability");
97
0
        QL_REQUIRE(pu_>=0.0, "negative probability");
98
0
    }
99
100
101
    LeisenReimer::LeisenReimer(const ext::shared_ptr<StochasticProcess1D>& process,
102
                               Time end,
103
                               Size steps,
104
                               Real strike)
105
0
    : BinomialTree<LeisenReimer>(process, end, ((steps % 2) != 0U ? steps : (steps + 1))) {
106
107
0
        QL_REQUIRE(strike>0.0, "strike must be positive");
108
0
        Size oddSteps = ((steps % 2) != 0U ? steps : (steps + 1));
109
0
        Real variance = process->variance(0.0, x0_, end);
110
0
        Real ermqdt = std::exp(driftPerStep_ + 0.5*variance/oddSteps);
111
0
        Real d2 = (std::log(x0_/strike) + driftPerStep_*oddSteps ) /
112
0
                                                          std::sqrt(variance);
113
0
        const LeisenReimerStep step =
114
0
            leisenReimerStep(d2, ermqdt, variance, oddSteps);
115
0
        pu_ = step.upProbability;
116
0
        pd_ = step.downProbability;
117
0
        up_ = step.up;
118
0
        down_ = step.down;
119
0
    }
120
121
0
    Real Joshi4::computeUpProb(Real k, Real dj) const {
122
0
        Real alpha = dj/(std::sqrt(8.0));
123
0
        Real alpha2 = alpha*alpha;
124
0
        Real alpha3 = alpha*alpha2;
125
0
        Real alpha5 = alpha3*alpha2;
126
0
        Real alpha7 = alpha5*alpha2;
127
0
        Real beta = -0.375*alpha-alpha3;
128
0
        Real gamma = (5.0/6.0)*alpha5 + (13.0/12.0)*alpha3
129
0
            +(25.0/128.0)*alpha;
130
0
        Real delta = -0.1025 *alpha- 0.9285 *alpha3
131
0
            -1.43 *alpha5 -0.5 *alpha7;
132
0
        Real p =0.5;
133
0
        Real rootk = std::sqrt(k);
134
0
        p+= alpha/rootk;
135
0
        p+= beta /(k*rootk);
136
0
        p+= gamma/(k*k*rootk);
137
        // delete next line to get results for j three tree
138
0
        p+= delta/(k*k*k*rootk);
139
0
        return p;
140
0
    }
141
142
    Joshi4::Joshi4(const ext::shared_ptr<StochasticProcess1D>& process,
143
                   Time end,
144
                   Size steps,
145
                   Real strike)
146
0
    : BinomialTree<Joshi4>(process, end, (steps % 2) != 0U ? steps : (steps + 1)) {
147
148
0
        QL_REQUIRE(strike>0.0, "strike must be positive");
149
0
        Size oddSteps = (steps % 2) != 0U ? steps : (steps + 1);
150
0
        Real variance = process->variance(0.0, x0_, end);
151
0
        Real ermqdt = std::exp(driftPerStep_ + 0.5*variance/oddSteps);
152
0
        Real d2 = (std::log(x0_/strike) + driftPerStep_*oddSteps ) /
153
0
                                                          std::sqrt(variance);
154
0
        pu_ = computeUpProb((oddSteps-1.0)/2.0,d2 );
155
0
        QL_REQUIRE(pu_ > 0.0 && pu_ < 1.0, "invalid up probability: " << pu_);
156
0
        pd_ = 1.0 - pu_;
157
0
        Real pdash = computeUpProb((oddSteps-1.0)/2.0,d2+std::sqrt(variance));
158
0
        up_ = ermqdt * pdash / pu_;
159
0
        down_ = (ermqdt - pu_ * up_) / (1.0 - pu_);
160
0
    }
161
}