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.cpp
Line
Count
Source
1
/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*
4
 Copyright (C) 2006 StatPro Italia srl
5
6
 This file is part of QuantLib, a free-software/open-source library
7
 for financial quantitative analysts and developers - http://quantlib.org/
8
9
 QuantLib is free software: you can redistribute it and/or modify it
10
 under the terms of the QuantLib license.  You should have received a
11
 copy of the license along with this program; if not, please email
12
 <quantlib-dev@lists.sf.net>. The license is also available online at
13
 <https://www.quantlib.org/license.shtml>.
14
15
 This program is distributed in the hope that it will be useful, but WITHOUT
16
 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17
 FOR A PARTICULAR PURPOSE.  See the license for more details.
18
*/
19
20
// ===========================================================================
21
// NOTE: The following copyright notice applies to the original code,
22
//
23
// Copyright (C) 2002 Peter Jäckel "Monte Carlo Methods in Finance".
24
// All rights reserved.
25
//
26
// Permission to use, copy, modify, and distribute this software is freely
27
// granted, provided that this notice is preserved.
28
// ===========================================================================
29
30
#include <ql/methods/montecarlo/brownianbridge.hpp>
31
32
namespace QuantLib {
33
34
    BrownianBridge::BrownianBridge(Size steps)
35
0
    : size_(steps), t_(size_), sqrtdt_(size_),
36
0
      bridgeIndex_(size_), leftIndex_(size_), rightIndex_(size_),
37
0
      leftWeight_(size_), rightWeight_(size_), stdDev_(size_) {
38
0
        for (Size i=0; i<size_; ++i)
39
0
            t_[i] = static_cast<Time>(i+1);
40
0
        initialize();
41
0
    }
42
43
    BrownianBridge::BrownianBridge(const std::vector<Time>& times)
44
0
    : size_(times.size()), t_(times), sqrtdt_(size_),
45
0
      bridgeIndex_(size_), leftIndex_(size_), rightIndex_(size_),
46
0
      leftWeight_(size_), rightWeight_(size_), stdDev_(size_) {
47
0
        initialize();
48
0
    }
49
50
    BrownianBridge::BrownianBridge(const TimeGrid& timeGrid)
51
0
    : size_(timeGrid.size()-1), t_(size_), sqrtdt_(size_),
52
0
      bridgeIndex_(size_), leftIndex_(size_), rightIndex_(size_),
53
0
      leftWeight_(size_), rightWeight_(size_), stdDev_(size_) {
54
0
        for (Size i=0; i<size_; ++i)
55
0
            t_[i] = timeGrid[i+1];
56
0
        initialize();
57
0
    }
58
59
60
0
    void BrownianBridge::initialize() {
61
62
0
        sqrtdt_[0] = std::sqrt(t_[0]);
63
0
        for (Size i=1; i<size_; ++i)
64
0
            sqrtdt_[i] = std::sqrt(t_[i]-t_[i-1]);
65
66
        // map is used to indicate which points are already constructed.
67
        // If map[i] is zero, path point i is yet unconstructed.
68
        // map[i]-1 is the index of the variate that constructs
69
        // the path point # i.
70
0
        std::vector<Size> map(size_, 0);
71
72
        //  The first point in the construction is the global step.
73
0
        map[size_-1] = 1;
74
        //  The global step is constructed from the first variate.
75
0
        bridgeIndex_[0] = size_-1;
76
        //  The variance of the global step
77
0
        stdDev_[0] = std::sqrt(t_[size_-1]);
78
        //  The global step to the last point in time is special.
79
0
        leftWeight_[0] = rightWeight_[0] = 0.0;
80
0
        for (Size j=0, i=1; i<size_; ++i) {
81
            // Find the next unpopulated entry in the map.
82
0
            while (map[j] != 0U)
83
0
                ++j;
84
0
            Size k = j;
85
            // Find the next populated entry in the map from there.
86
0
            while (map[k] == 0U)
87
0
                ++k;
88
            // l-1 is now the index of the point to be constructed next.
89
0
            Size l = j + ((k-1-j)>>1);
90
0
            map[l] = i;
91
            // The i-th Gaussian variate will be used to set point l-1.
92
0
            bridgeIndex_[i] = l;
93
0
            leftIndex_[i]   = j;
94
0
            rightIndex_[i]  = k;
95
0
            if (j != 0) {
96
0
                leftWeight_[i]= (t_[k]-t_[l])/(t_[k]-t_[j-1]);
97
0
                rightWeight_[i] = (t_[l]-t_[j-1])/(t_[k]-t_[j-1]);
98
0
                stdDev_[i] =
99
0
                    std::sqrt(((t_[l]-t_[j-1])*(t_[k]-t_[l]))
100
0
                              /(t_[k]-t_[j-1]));
101
0
            } else {
102
0
                leftWeight_[i]  = (t_[k]-t_[l])/t_[k];
103
0
                rightWeight_[i] =  t_[l]/t_[k];
104
0
                stdDev_[i] = std::sqrt(t_[l]*(t_[k]-t_[l])/t_[k]);
105
0
            }
106
0
            j=k+1;
107
0
            if (j>=size_)
108
0
                j=0;    //  wrap around
109
0
        }
110
0
    }
111
112
}
113