QuantLib: a free/open-source library for quantitative finance
Fully annotated sources - version 1.32
Loading...
Searching...
No Matches
sobolbrowniangenerator.cpp
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
20#include <ql/models/marketmodels/browniangenerators/sobolbrowniangenerator.hpp>
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 unsigned long seed,
115 : factors_(factors), steps_(steps), ordering_(ordering),
116 generator_(SobolRsg(factors * steps, seed, integers), InverseCumulativeNormal()),
117 bridge_(steps), orderedIndices_(factors, std::vector<Size>(steps)),
118 bridgedVariates_(factors, std::vector<Real>(steps)) {
119
120 switch (ordering_) {
121 case Factors:
122 fillByFactor(orderedIndices_, factors_, steps_);
123 break;
124 case Steps:
125 fillByStep(orderedIndices_, factors_, steps_);
126 break;
127 case Diagonal:
128 fillByDiagonal(orderedIndices_, factors_, steps_);
129 break;
130 default:
131 QL_FAIL("unknown ordering");
132 }
133 }
134
135
138 InverseCumulativeNormal>::sample_type
139 sample_type;
140
141 const sample_type& sample = generator_.nextSequence();
142 // Brownian-bridge the variates according to the ordered indices
143 for (Size i=0; i<factors_; ++i) {
144 bridge_.transform(boost::make_permutation_iterator(
145 sample.value.begin(),
146 orderedIndices_[i].begin()),
147 boost::make_permutation_iterator(
148 sample.value.begin(),
149 orderedIndices_[i].end()),
150 bridgedVariates_[i].begin());
151 }
152 lastStep_ = 0;
153 return sample.weight;
154 }
155
156
157 const std::vector<std::vector<Size> >&
159 return orderedIndices_;
160 }
161
162 std::vector<std::vector<Real> > SobolBrownianGenerator::transform(
163 const std::vector<std::vector<Real> >& variates) {
164
165 QL_REQUIRE( (variates.size() == factors_*steps_),
166 "inconsistent variate vector");
167
168 const Size dim = factors_*steps_;
169 const Size nPaths = variates.front().size();
170
171 std::vector<std::vector<Real> >
172 retVal(factors_, std::vector<Real>(nPaths*steps_));
173
174 for (Size j=0; j < nPaths; ++j) {
175 std::vector<Real> sample(steps_*factors_);
176 for (Size k=0; k < dim; ++k) {
177 sample[k] = variates[k][j];
178 }
179 for (Size i=0; i<factors_; ++i) {
180 bridge_.transform(boost::make_permutation_iterator(
181 sample.begin(),
182 orderedIndices_[i].begin()),
183 boost::make_permutation_iterator(
184 sample.begin(),
185 orderedIndices_[i].end()),
186 retVal[i].begin()+j*steps_);
187 }
188 }
189
190 return retVal;
191 }
192
193 Real SobolBrownianGenerator::nextStep(std::vector<Real>& output) {
194 #if defined(QL_EXTRA_SAFETY_CHECKS)
195 QL_REQUIRE(output.size() == factors_, "size mismatch");
196 QL_REQUIRE(lastStep_<steps_, "sequence exhausted");
197 #endif
198 for (Size i=0; i<factors_; ++i)
199 output[i] = bridgedVariates_[i][lastStep_];
200 ++lastStep_;
201 return 1.0;
202 }
203
205
207
208
209
212 unsigned long seed,
214 : ordering_(ordering), seed_(seed), integers_(integers) {}
215
216 ext::shared_ptr<BrownianGenerator>
218 return ext::shared_ptr<BrownianGenerator>(
219 new SobolBrownianGenerator(factors, steps, ordering_,
220 seed_, integers_));
221 }
222
223}
224
void transform(RandomAccessIterator1 begin, RandomAccessIterator1 end, RandomAccessIterator2 output) const
Brownian-bridge generator function.
Inverse cumulative normal distribution function.
Inverse cumulative random sequence generator.
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)
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
std::vector< std::vector< Real > > bridgedVariates_
SobolBrownianGenerator(Size factors, Size steps, Ordering ordering, unsigned long seed=0, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::Jaeckel)
const std::vector< std::vector< Size > > & orderedIndices() const
InverseCumulativeRsg< SobolRsg, InverseCumulativeNormal > generator_
Sobol low-discrepancy sequence generator.
Definition: sobolrsg.hpp:110
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.