Coverage Report

Created: 2025-08-05 06:45

/src/quantlib/ql/methods/lattices/lattice.hpp
Line
Count
Source (jump to first uncovered line)
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) 2004, 2005 StatPro Italia srl
6
7
 This file is part of QuantLib, a free-software/open-source library
8
 for financial quantitative analysts and developers - http://quantlib.org/
9
10
 QuantLib is free software: you can redistribute it and/or modify it
11
 under the terms of the QuantLib license.  You should have received a
12
 copy of the license along with this program; if not, please email
13
 <quantlib-dev@lists.sf.net>. The license is also available online at
14
 <http://quantlib.org/license.shtml>.
15
16
 This program is distributed in the hope that it will be useful, but WITHOUT
17
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 FOR A PARTICULAR PURPOSE.  See the license for more details.
19
*/
20
21
/*! \file lattice.hpp
22
    \brief Tree-based lattice-method class
23
*/
24
25
#ifndef quantlib_tree_based_lattice_hpp
26
#define quantlib_tree_based_lattice_hpp
27
28
#include <ql/numericalmethod.hpp>
29
#include <ql/discretizedasset.hpp>
30
#include <ql/patterns/curiouslyrecurring.hpp>
31
32
namespace QuantLib {
33
34
    //! Tree-based lattice-method base class
35
    /*! This class defines a lattice method that is able to rollback
36
        (with discount) a discretized asset object. It will be based
37
        on one or more trees.
38
39
        Derived classes must implement the following interface:
40
        \code
41
        public:
42
          DiscountFactor discount(Size i, Size index) const;
43
          Size descendant(Size i, Size index, Size branch) const;
44
          Real probability(Size i, Size index, Size branch) const;
45
        \endcode
46
        and may implement the following:
47
        \code
48
        public:
49
          void stepback(Size i,
50
                        const Array& values,
51
                        Array& newValues) const;
52
        \endcode
53
54
        \ingroup lattices
55
    */
56
    template <class Impl>
57
    class TreeLattice : public Lattice,
58
                        public CuriouslyRecurringTemplate<Impl> {
59
      public:
60
        TreeLattice(const TimeGrid& timeGrid,
61
                    Size n)
62
0
        : Lattice(timeGrid), n_(n) {
63
0
            QL_REQUIRE(n>0, "there is no zeronomial lattice!");
64
0
            statePrices_ = std::vector<Array>(1, Array(1, 1.0));
65
0
            statePricesLimit_ = 0;
66
0
        }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::TreeLattice(QuantLib::TimeGrid const&, unsigned long)
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::TreeLattice(QuantLib::TimeGrid const&, unsigned long)
67
68
        //! \name Lattice interface
69
        //@{
70
        void initialize(DiscretizedAsset&, Time t) const override;
71
        void rollback(DiscretizedAsset&, Time to) const override;
72
        void partialRollback(DiscretizedAsset&, Time to) const override;
73
        //! Computes the present value of an asset using Arrow-Debrew prices
74
        Real presentValue(DiscretizedAsset&) const override;
75
        //@}
76
77
        const Array& statePrices(Size i) const;
78
79
        void stepback(Size i,
80
                      const Array& values,
81
                      Array& newValues) const;
82
83
      protected:
84
        void computeStatePrices(Size until) const;
85
86
        // Arrow-Debrew state prices
87
        mutable std::vector<Array> statePrices_;
88
89
      private:
90
        Size n_;
91
        mutable Size statePricesLimit_;
92
    };
93
94
95
    // template definitions
96
97
    template <class Impl>
98
0
    void TreeLattice<Impl>::computeStatePrices(Size until) const {
99
0
        for (Size i=statePricesLimit_; i<until; i++) {
100
0
            statePrices_.push_back(Array(this->impl().size(i+1), 0.0));
101
0
            for (Size j=0; j<this->impl().size(i); j++) {
102
0
                DiscountFactor disc = this->impl().discount(i,j);
103
0
                Real statePrice = statePrices_[i][j];
104
0
                for (Size l=0; l<n_; l++) {
105
0
                    statePrices_[i+1][this->impl().descendant(i,j,l)] +=
106
0
                        statePrice*disc*this->impl().probability(i,j,l);
107
0
                }
108
0
            }
109
0
        }
110
0
        statePricesLimit_ = until;
111
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::computeStatePrices(unsigned long) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::computeStatePrices(unsigned long) const
112
113
    template <class Impl>
114
0
    const Array& TreeLattice<Impl>::statePrices(Size i) const {
115
0
        if (i>statePricesLimit_)
116
0
            computeStatePrices(i);
117
0
        return statePrices_[i];
118
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::statePrices(unsigned long) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::statePrices(unsigned long) const
119
120
    template <class Impl>
121
0
    inline Real TreeLattice<Impl>::presentValue(DiscretizedAsset& asset) const {
122
0
        Size i = t_.index(asset.time());
123
0
        return DotProduct(asset.values(), statePrices(i));
124
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::presentValue(QuantLib::DiscretizedAsset&) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::presentValue(QuantLib::DiscretizedAsset&) const
125
126
    template <class Impl>
127
0
    inline void TreeLattice<Impl>::initialize(DiscretizedAsset& asset, Time t) const {
128
0
        Size i = t_.index(t);
129
0
        asset.time() = t;
130
0
        asset.reset(this->impl().size(i));
131
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::initialize(QuantLib::DiscretizedAsset&, double) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::initialize(QuantLib::DiscretizedAsset&, double) const
132
133
    template <class Impl>
134
0
    inline void TreeLattice<Impl>::rollback(DiscretizedAsset& asset, Time to) const {
135
0
        partialRollback(asset,to);
136
0
        asset.adjustValues();
137
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::rollback(QuantLib::DiscretizedAsset&, double) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::rollback(QuantLib::DiscretizedAsset&, double) const
138
139
    template <class Impl>
140
    void TreeLattice<Impl>::partialRollback(DiscretizedAsset& asset,
141
0
                                            Time to) const {
142
143
0
        Time from = asset.time();
144
145
0
        if (close(from,to))
146
0
            return;
147
148
0
        QL_REQUIRE(from > to,
149
0
                   "cannot roll the asset back to" << to
150
0
                   << " (it is already at t = " << from << ")");
151
152
0
        auto iFrom = Integer(t_.index(from));
153
0
        auto iTo = Integer(t_.index(to));
154
155
0
        for (Integer i=iFrom-1; i>=iTo; --i) {
156
0
            Array newValues(this->impl().size(i));
157
0
            this->impl().stepback(i, asset.values(), newValues);
158
0
            asset.time() = t_[i];
159
0
            asset.values() = newValues;
160
            // skip the very last adjustment
161
0
            if (i != iTo)
162
0
                asset.adjustValues();
163
0
        }
164
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::partialRollback(QuantLib::DiscretizedAsset&, double) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::partialRollback(QuantLib::DiscretizedAsset&, double) const
165
166
    template <class Impl>
167
    void TreeLattice<Impl>::stepback(Size i, const Array& values,
168
0
                                     Array& newValues) const {
169
0
        #pragma omp parallel for
170
0
        for (long j=0; j<(long)this->impl().size(i); j++) {
171
0
            Real value = 0.0;
172
0
            for (Size l=0; l<n_; l++) {
173
0
                value += this->impl().probability(i,j,l) *
174
0
                         values[this->impl().descendant(i,j,l)];
175
0
            }
176
0
            value *= this->impl().discount(i,j);
177
0
            newValues[j] = value;
178
0
        }
179
0
    }
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::OneFactorModel::ShortRateTree>::stepback(unsigned long, QuantLib::Array const&, QuantLib::Array&) const
Unexecuted instantiation: QuantLib::TreeLattice<QuantLib::TwoFactorModel::ShortRateTree>::stepback(unsigned long, QuantLib::Array const&, QuantLib::Array&) const
180
181
}
182
183
184
#endif