QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.34
Loading...
Searching...
No Matches
sobolbrowniangenerator.cpp
Go to the documentation of this file.
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 <http://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
21#include <boost/iterator/permutation_iterator.hpp>
22
23namespace QuantLib {
24
25 namespace {
26
27 void fillByFactor(std::vector<std::vector<Size> >& M,
28 Size factors, Size steps) {
29 Size counter = 0;
30 for (Size i=0; i<factors; ++i)
31 for (Size j=0; j<steps; ++j)
32 M[i][j] = counter++;
33 }
34
35 void fillByStep(std::vector<std::vector<Size> >& M,
36 Size factors, Size steps) {
37 Size counter = 0;
38 for (Size j=0; j<steps; ++j)
39 for (Size i=0; i<factors; ++i)
40 M[i][j] = counter++;
41 }
42
43 // variate 2 is used for the second factor's full path
44 void fillByDiagonal(std::vector<std::vector<Size> >& M,
45 Size factors, Size steps) {
46 // starting position of the current diagonal
47 Size i0 = 0, j0 = 0;
48 // current position
49 Size i=0, j=0;
50 Size counter = 0;
51 while (counter < factors*steps) {
52 M[i][j] = counter++;
53 if (i == 0 || j == steps-1) {
54 // we completed a diagonal and have to start a new one
55 if (i0 < factors-1) {
56 // we start the path of the next factor
57 i0 = i0+1;
58 j0 = 0;
59 } else {
60 // we move along the path of the last factor
61 i0 = factors-1;
62 j0 = j0+1;
63 }
64 i = i0;
65 j = j0;
66 } else {
67 // we move along the diagonal
68 i = i-1;
69 j = j+1;
70 }
71 }
72 }
73
74 /*
75 // variate 2 is used for the first factor's half path
76 void fillByDiagonal(std::vector<std::vector<Size> >& M,
77 Size factors, Size steps) {
78 // starting position of the current diagonal
79 Size i0 = 0, j0 = 0;
80 // current position
81 Size i=0, j=0;
82 Size counter = 0;
83 while (counter < factors*steps) {
84 M[i][j] = counter++;
85 if (j == 0 || i == factors-1) {
86 // we completed a diagonal and have to start a new one
87 if (j0 < steps-1) {
88 // we move along the path of the first factor
89 i0 = 0;
90 j0 = j0+1;
91 } else {
92 // we complete the next path
93 i0 = i0+1;
94 j0 = steps-1;
95 }
96 i = i0;
97 j = j0;
98 } else {
99 // we move along the diagonal
100 i = i+1;
101 j = j-1;
102 }
103 }
104 }
105 */
106
107 }
108
109
111 Size steps,
112 Ordering ordering)
113 : factors_(factors), steps_(steps), ordering_(ordering),
114 bridge_(steps), orderedIndices_(factors, std::vector<Size>(steps)),
115 bridgedVariates_(factors, std::vector<Real>(steps)) {
116
117 switch (ordering_) {
118 case Factors:
119 fillByFactor(orderedIndices_, factors_, steps_);
120 break;
121 case Steps:
122 fillByStep(orderedIndices_, factors_, steps_);
123 break;
124 case Diagonal:
125 fillByDiagonal(orderedIndices_, factors_, steps_);
126 break;
127 default:
128 QL_FAIL("unknown ordering");
129 }
130 }
131
132
134 const auto& sample = nextSequence();
135 // Brownian-bridge the variates according to the ordered indices
136 for (Size i=0; i<factors_; ++i) {
137 bridge_.transform(boost::make_permutation_iterator(
138 sample.value.begin(),
139 orderedIndices_[i].begin()),
140 boost::make_permutation_iterator(
141 sample.value.begin(),
142 orderedIndices_[i].end()),
143 bridgedVariates_[i].begin());
144 }
145 lastStep_ = 0;
146 return sample.weight;
147 }
148
149
150 const std::vector<std::vector<Size> >&
152 return orderedIndices_;
153 }
154
155 std::vector<std::vector<Real> > SobolBrownianGeneratorBase::transform(
156 const std::vector<std::vector<Real> >& variates) {
157
158 QL_REQUIRE( (variates.size() == factors_*steps_),
159 "inconsistent variate vector");
160
161 const Size dim = factors_*steps_;
162 const Size nPaths = variates.front().size();
163
164 std::vector<std::vector<Real> >
165 retVal(factors_, std::vector<Real>(nPaths*steps_));
166
167 for (Size j=0; j < nPaths; ++j) {
168 std::vector<Real> sample(steps_*factors_);
169 for (Size k=0; k < dim; ++k) {
170 sample[k] = variates[k][j];
171 }
172 for (Size i=0; i<factors_; ++i) {
173 bridge_.transform(boost::make_permutation_iterator(
174 sample.begin(),
175 orderedIndices_[i].begin()),
176 boost::make_permutation_iterator(
177 sample.begin(),
178 orderedIndices_[i].end()),
179 retVal[i].begin()+j*steps_);
180 }
181 }
182
183 return retVal;
184 }
185
186 Real SobolBrownianGeneratorBase::nextStep(std::vector<Real>& output) {
187 #if defined(QL_EXTRA_SAFETY_CHECKS)
188 QL_REQUIRE(output.size() == factors_, "size mismatch");
189 QL_REQUIRE(lastStep_<steps_, "sequence exhausted");
190 #endif
191 for (Size i=0; i<factors_; ++i)
192 output[i] = bridgedVariates_[i][lastStep_];
193 ++lastStep_;
194 return 1.0;
195 }
196
198
200
202 Size steps,
203 Ordering ordering,
204 unsigned long seed,
206 : SobolBrownianGeneratorBase(factors, steps, ordering),
207 generator_(SobolRsg(factors * steps, seed, integers), InverseCumulativeNormal()) {}
208
210 return generator_.nextSequence();
211 }
212
215 unsigned long seed,
217 : ordering_(ordering), seed_(seed), integers_(integers) {}
218
219 ext::shared_ptr<BrownianGenerator>
221 return ext::shared_ptr<BrownianGenerator>(
222 new SobolBrownianGenerator(factors, steps, ordering_,
223 seed_, integers_));
224 }
225
227 Size factors,
228 Size steps,
229 Ordering ordering,
230 unsigned long seed,
232 unsigned long scrambleSeed)
233 : SobolBrownianGeneratorBase(factors, steps, ordering),
234 generator_(Burley2020SobolRsg(factors * steps, seed, integers, scrambleSeed),
236
238 return generator_.nextSequence();
239 }
240
243 unsigned long seed,
245 unsigned long scrambleSeed)
246 : ordering_(ordering), seed_(seed), integers_(integers), scrambleSeed_(scrambleSeed) {}
247
248 ext::shared_ptr<BrownianGenerator>
250 return ext::shared_ptr<BrownianGenerator>(new Burley2020SobolBrownianGenerator(
251 factors, steps, ordering_, seed_, integers_, scrambleSeed_));
252 }
253}
254
void transform(RandomAccessIterator1 begin, RandomAccessIterator1 end, RandomAccessIterator2 output) const
Brownian-bridge generator function.
Burley2020SobolBrownianGeneratorFactory(SobolBrownianGenerator::Ordering ordering, unsigned long seed=42, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::Jaeckel, unsigned long scrambleSeed=43)
ext::shared_ptr< BrownianGenerator > create(Size factors, Size steps) const override
Burley2020SobolBrownianGenerator(Size factors, Size steps, Ordering ordering, unsigned long seed=42, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::Jaeckel, unsigned long scrambleSeed=43)
const Burley2020SobolRsg::sample_type & nextSequence() override
InverseCumulativeRsg< Burley2020SobolRsg, InverseCumulativeNormal > generator_
Scrambled sobol sequence according to Burley, 2020.
Inverse cumulative normal distribution function.
Sobol Brownian generator for market-model simulations.
std::vector< std::vector< Size > > orderedIndices_
std::vector< std::vector< Real > > transform(const std::vector< std::vector< Real > > &variates)
Real nextStep(std::vector< Real > &) override
virtual const SobolRsg::sample_type & nextSequence()=0
std::vector< std::vector< Real > > bridgedVariates_
SobolBrownianGeneratorBase(Size factors, Size steps, Ordering ordering)
const std::vector< std::vector< Size > > & orderedIndices() const
SobolBrownianGenerator::Ordering ordering_
ext::shared_ptr< BrownianGenerator > create(Size factors, Size steps) const override
SobolBrownianGeneratorFactory(SobolBrownianGenerator::Ordering ordering, unsigned long seed=0, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::Jaeckel)
InverseCumulativeRsg< SobolRsg, InverseCumulativeNormal > generator_
SobolBrownianGenerator(Size factors, Size steps, Ordering ordering, unsigned long seed=0, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::Jaeckel)
const SobolRsg::sample_type & nextSequence() override
Sobol low-discrepancy sequence generator.
Definition: sobolrsg.hpp:110
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
QL_REAL Real
real number
Definition: types.hpp:50
std::size_t Size
size of a container
Definition: types.hpp:58
Definition: any.hpp:35
STL namespace.