Coverage Report

Created: 2026-02-03 07:02

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/quantlib/ql/methods/montecarlo/brownianbridge.hpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2003 Ferdinando Ametrano
5
 Copyright (C) 2006 StatPro Italia srl
6
 Copyright (C) 2009 Bojan Nikolic
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
/*! \file brownianbridge.hpp
23
    \brief Browian bridge
24
*/
25
26
// ===========================================================================
27
// NOTE: The following copyright notice applies to the original code,
28
//
29
// Copyright (C) 2002 Peter J�ckel "Monte Carlo Methods in Finance".
30
// All rights reserved.
31
//
32
// Permission to use, copy, modify, and distribute this software is freely
33
// granted, provided that this notice is preserved.
34
// ===========================================================================
35
36
#ifndef quantlib_brownian_bridge_hpp
37
#define quantlib_brownian_bridge_hpp
38
39
#include <ql/methods/montecarlo/path.hpp>
40
#include <ql/methods/montecarlo/sample.hpp>
41
42
namespace QuantLib {
43
44
    //! Builds Wiener process paths using Gaussian variates
45
    /*! This class generates normalized (i.e., unit-variance) paths as
46
        sequences of variations. In order to obtain the actual path of
47
        the underlying, the returned variations must be multiplied by
48
        the integrated variance (including time) over the
49
        corresponding time step.
50
51
        \ingroup mcarlo
52
    */
53
    class BrownianBridge {
54
      public:
55
        /*! The constructor generates the time grid so that each step
56
            is of unit-time length.
57
58
            \param steps The number of steps in the path
59
        */
60
        BrownianBridge(Size steps);
61
        /*! The step times are copied from the supplied vector
62
63
            \param times A vector containing the times at which the
64
                         steps occur. This also defines the number of
65
                         steps that will be generated.
66
67
            \note the starting time of the path is assumed to be 0 and
68
                  must not be included
69
        */
70
        BrownianBridge(const std::vector<Time>& times);
71
        /*! The step times are copied from the TimeGrid object
72
73
            \param timeGrid a time grid containing the times at which
74
                            the steps will occur
75
        */
76
        BrownianBridge(const TimeGrid& timeGrid);
77
        //! \name inspectors
78
        //@{
79
0
        Size size() const { return size_; }
80
0
        const std::vector<Time>& times() const { return t_; }
81
0
        const std::vector<Size>& bridgeIndex()  const { return bridgeIndex_; }
82
0
        const std::vector<Size>& leftIndex()    const { return leftIndex_; }
83
0
        const std::vector<Size>& rightIndex()   const { return rightIndex_; }
84
0
        const std::vector<Real>& leftWeight()   const { return leftWeight_; }
85
0
        const std::vector<Real>& rightWeight()  const { return rightWeight_; }
86
0
        const std::vector<Real>& stdDeviation() const { return stdDev_; }
87
        //@}
88
89
        //! Brownian-bridge generator function
90
        /*! Transforms an input sequence of random variates into a
91
            sequence of variations in a Brownian bridge path.
92
93
            \param begin  The start iterator of the input sequence.
94
            \param end    The end iterator of the input sequence.
95
            \param output The start iterator of the output sequence.
96
97
            \note To get the canonical Brownian bridge which starts
98
                  and finishes at the same value, the first element of
99
                  the input sequence must be zero. Conversely, to get
100
                  a sloped bridge set the first element to a non-zero
101
                  value. In this case, the final value in the bridge
102
                  will be sqrt(last time point)*(first element of
103
                  input sequence).
104
        */
105
        template <class RandomAccessIterator1,
106
                  class RandomAccessIterator2>
107
        void transform(RandomAccessIterator1 begin,
108
                       RandomAccessIterator1 end,
109
0
                       RandomAccessIterator2 output) const {
110
0
            QL_REQUIRE(end >= begin, "invalid sequence");
111
0
            QL_REQUIRE(Size(end-begin) == size_,
112
0
                       "incompatible sequence size");
113
            // We use output to store the path...
114
0
            output[size_-1] = stdDev_[0] * begin[0];
115
0
            for (Size i=1; i<size_; ++i) {
116
0
                Size j = leftIndex_[i];
117
0
                Size k = rightIndex_[i];
118
0
                Size l = bridgeIndex_[i];
119
0
                if (j != 0) {
120
0
                    output[l] =
121
0
                        leftWeight_[i] * output[j-1] +
122
0
                        rightWeight_[i] * output[k]   +
123
0
                        stdDev_[i] * begin[i];
124
0
                } else {
125
0
                    output[l] =
126
0
                        rightWeight_[i] * output[k]   +
127
0
                        stdDev_[i] * begin[i];
128
0
                }
129
0
            }
130
            // ...after which, we calculate the variations and
131
            // normalize to unit times
132
0
            for (Size i=size_-1; i>=1; --i) {
133
0
                output[i] -= output[i-1];
134
0
                output[i] /= sqrtdt_[i];
135
0
            }
136
0
            output[0] /= sqrtdt_[0];
137
0
        }
Unexecuted instantiation: void QuantLib::BrownianBridge::transform<boost::iterators::permutation_iterator<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<unsigned long*> >, std::__1::__wrap_iter<double*> >(boost::iterators::permutation_iterator<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<unsigned long*> >, boost::iterators::permutation_iterator<std::__1::__wrap_iter<double const*>, std::__1::__wrap_iter<unsigned long*> >, std::__1::__wrap_iter<double*>) const
Unexecuted instantiation: void QuantLib::BrownianBridge::transform<boost::iterators::permutation_iterator<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<unsigned long*> >, std::__1::__wrap_iter<double*> >(boost::iterators::permutation_iterator<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<unsigned long*> >, boost::iterators::permutation_iterator<std::__1::__wrap_iter<double*>, std::__1::__wrap_iter<unsigned long*> >, std::__1::__wrap_iter<double*>) const
138
      private:
139
        void initialize();
140
        Size size_;
141
        std::vector<Time> t_;
142
        std::vector<Real> sqrtdt_;
143
        std::vector<Size> bridgeIndex_, leftIndex_, rightIndex_;
144
        std::vector<Real> leftWeight_, rightWeight_, stdDev_;
145
    };
146
147
}
148
149
#endif