Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
multipathgeneratorbase.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2016 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
20
21#include <boost/make_shared.hpp>
22
23using namespace QuantLib;
24
25namespace QuantExt {
26
28 const QuantLib::ext::shared_ptr<StochasticProcess>& process, const TimeGrid& grid, BigNatural seed, bool antitheticSampling)
29 : process_(process), grid_(grid), seed_(seed), antitheticSampling_(antitheticSampling), antitheticVariate_(true),
30 next_(MultiPath(process->size(), grid), 1.0) {
32}
33
35 PseudoRandom::rsg_type rsg = PseudoRandom::make_sequence_generator(process_->factors() * (grid_.size() - 1), seed_);
36 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<StochasticProcess1D>(process_)) {
37 pg1D_ = QuantLib::ext::make_shared<PathGenerator<PseudoRandom::rsg_type>>(tmp, grid_, rsg, false);
38 } else {
39 pg_ = QuantLib::ext::make_shared<MultiPathGenerator<PseudoRandom::rsg_type>>(process_, grid_, rsg, false);
40 }
41 antitheticVariate_ = true;
42}
43
44const Sample<MultiPath>& MultiPathGeneratorMersenneTwister::next() const {
47 if (pg_) {
48 return antitheticVariate_ ? pg_->antithetic() : pg_->next();
49 } else {
50 next_.value.at(0) = antitheticVariate_ ? pg1D_->antithetic().value : pg1D_->next().value;
51 return next_;
52 }
53 } else {
54 if (pg_)
55 return pg_->next();
56 else {
57 next_.value.at(0) = pg1D_->next().value;
58 return next_;
59 }
60 }
61}
62
63MultiPathGeneratorSobol::MultiPathGeneratorSobol(const QuantLib::ext::shared_ptr<StochasticProcess>& process,
64 const TimeGrid& grid, BigNatural seed,
65 SobolRsg::DirectionIntegers directionIntegers)
66 : process_(process), grid_(grid), seed_(seed), directionIntegers_(directionIntegers),
67 next_(MultiPath(process->size(), grid), 1.0) {
69}
70
72 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<StochasticProcess1D>(process_)) {
73 pg1D_ = QuantLib::ext::make_shared<PathGenerator<InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal>>>(
74 tmp, grid_,
75 InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal>(
76 SobolRsg(process_->factors() * (grid_.size() - 1), seed_, directionIntegers_)),
77 false);
78
79 } else {
80 pg_ = QuantLib::ext::make_shared<MultiPathGenerator<InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal>>>(
82 InverseCumulativeRsg<SobolRsg, InverseCumulativeNormal>(
83 SobolRsg(process_->factors() * (grid_.size() - 1), seed_, directionIntegers_)));
84 }
85}
86
87const Sample<MultiPath>& MultiPathGeneratorSobol::next() const {
88 if (pg_)
89 return pg_->next();
90 else {
91 next_.value.at(0) = pg1D_->next().value;
92 return next_;
93 }
94}
95
96MultiPathGeneratorBurley2020Sobol::MultiPathGeneratorBurley2020Sobol(const QuantLib::ext::shared_ptr<StochasticProcess>& process,
97 const TimeGrid& grid, BigNatural seed,
98 SobolRsg::DirectionIntegers directionIntegers,
99 BigNatural scrambleSeed)
100 : process_(process), grid_(grid), seed_(seed), directionIntegers_(directionIntegers), scrambleSeed_(scrambleSeed),
101 next_(MultiPath(process->size(), grid), 1.0) {
103}
104
106 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<StochasticProcess1D>(process_)) {
107 pg1D_ = QuantLib::ext::make_shared<PathGenerator<InverseCumulativeRsg<Burley2020SobolRsg, InverseCumulativeNormal>>>(
108 tmp, grid_,
109 InverseCumulativeRsg<Burley2020SobolRsg, InverseCumulativeNormal>(
110 Burley2020SobolRsg(process_->factors() * (grid_.size() - 1), seed_, directionIntegers_, scrambleSeed_)),
111 false);
112
113 } else {
114 pg_ = QuantLib::ext::make_shared<MultiPathGenerator<InverseCumulativeRsg<Burley2020SobolRsg, InverseCumulativeNormal>>>(
116 InverseCumulativeRsg<Burley2020SobolRsg, InverseCumulativeNormal>(Burley2020SobolRsg(
117 process_->factors() * (grid_.size() - 1), seed_, directionIntegers_, scrambleSeed_)));
118 }
119}
120
121const Sample<MultiPath>& MultiPathGeneratorBurley2020Sobol::next() const {
122 if (pg_)
123 return pg_->next();
124 else {
125 next_.value.at(0) = pg1D_->next().value;
126 return next_;
127 }
128}
129
131 const QuantLib::ext::shared_ptr<StochasticProcess>& process, const TimeGrid& grid,
132 SobolBrownianGenerator::Ordering ordering, BigNatural seed, SobolRsg::DirectionIntegers directionIntegers)
133 : process_(process), grid_(grid), ordering_(ordering), seed_(seed), directionIntegers_(directionIntegers),
134 next_(MultiPath(process->size(), grid), 1.0) {
135 process1D_ = QuantLib::ext::dynamic_pointer_cast<StochasticProcess1D>(process);
136}
137
138const Sample<MultiPath>& MultiPathGeneratorSobolBrownianBridgeBase::next() const {
139 Array asset = process_->initialValues();
140 MultiPath& path = next_.value;
141 for (Size j = 0; j < asset.size(); ++j) {
142 path[j].front() = asset[j];
143 }
144 next_.weight = gen_->nextPath();
145 std::vector<Real> output(process_->factors());
146 for (Size i = 1; i < grid_.size(); ++i) {
147 Real t = grid_[i - 1];
148 Real dt = grid_.dt(i - 1);
149 gen_->nextStep(output);
150 if (process1D_) {
151 path[0][i] = asset[0] = process1D_->evolve(t, asset[0], dt, output[0]);
152 } else {
153 Array tmp(output.begin(), output.end());
154 asset = process_->evolve(t, asset, dt, tmp);
155 for (Size j = 0; j < asset.size(); ++j) {
156 path[j][i] = asset[j];
157 }
158 }
159 }
160 return next_;
161}
162
164 const QuantLib::ext::shared_ptr<StochasticProcess>& process, const TimeGrid& grid,
165 SobolBrownianGenerator::Ordering ordering, BigNatural seed, SobolRsg::DirectionIntegers directionIntegers)
166 : MultiPathGeneratorSobolBrownianBridgeBase(process, grid, ordering, seed, directionIntegers) {
168}
169
171 gen_ = QuantLib::ext::make_shared<SobolBrownianGenerator>(process_->factors(), grid_.size() - 1, ordering_, seed_,
173}
174
176 const QuantLib::ext::shared_ptr<StochasticProcess>& process, const TimeGrid& grid,
177 Burley2020SobolBrownianGenerator::Ordering ordering, BigNatural seed, SobolRsg::DirectionIntegers directionIntegers,
178 BigNatural scrambleSeed)
179 : MultiPathGeneratorSobolBrownianBridgeBase(process, grid, ordering, seed, directionIntegers),
180 scrambleSeed_(scrambleSeed) {
182}
183
185 gen_ = QuantLib::ext::make_shared<Burley2020SobolBrownianGenerator>(process_->factors(), grid_.size() - 1, ordering_, seed_,
187}
188
189QuantLib::ext::shared_ptr<MultiPathGeneratorBase>
190makeMultiPathGenerator(const SequenceType s, const QuantLib::ext::shared_ptr<StochasticProcess>& process,
191 const TimeGrid& timeGrid, const BigNatural seed, const SobolBrownianGenerator::Ordering ordering,
192 const SobolRsg::DirectionIntegers directionIntegers) {
193 switch (s) {
194 case MersenneTwister:
195 return QuantLib::ext::make_shared<QuantExt::MultiPathGeneratorMersenneTwister>(process, timeGrid, seed, false);
197 return QuantLib::ext::make_shared<QuantExt::MultiPathGeneratorMersenneTwister>(process, timeGrid, seed, true);
198 case Sobol:
199 return QuantLib::ext::make_shared<QuantExt::MultiPathGeneratorSobol>(process, timeGrid, seed, directionIntegers);
200 case Burley2020Sobol:
201 return QuantLib::ext::make_shared<QuantExt::MultiPathGeneratorBurley2020Sobol>(
202 process, timeGrid, seed, directionIntegers, seed == 0 ? 0 : seed + 1);
204 return QuantLib::ext::make_shared<QuantExt::MultiPathGeneratorSobolBrownianBridge>(process, timeGrid, ordering, seed,
205 directionIntegers);
207 return QuantLib::ext::make_shared<QuantExt::MultiPathGeneratorBurley2020SobolBrownianBridge>(
208 process, timeGrid, ordering, seed, directionIntegers, seed == 0 ? 0 : seed + 1);
209 default:
210 QL_FAIL("Unknown sequence type");
211 }
212}
213
214std::ostream& operator<<(std::ostream& out, const SequenceType s) {
215 switch (s) {
216 case MersenneTwister:
217 return out << "MersenneTwister";
219 return out << "MersenneTwisterAntithetic";
220 case Sobol:
221 return out << "Sobol";
222 case Burley2020Sobol:
223 return out << "Burley2020Sobol";
225 return out << "SobolBrownianBridge";
227 return out << "Burley2020SobolBrownianBridge";
228 default:
229 return out << "Unknown sequence type";
230 }
231}
232
233} // namespace QuantExt
MultiPathGeneratorBurley2020SobolBrownianBridge(const QuantLib::ext::shared_ptr< StochasticProcess > &, const TimeGrid &, SobolBrownianGenerator::Ordering ordering=SobolBrownianGenerator::Steps, BigNatural seed=42, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::JoeKuoD7, BigNatural scrambleSeed=43)
const QuantLib::ext::shared_ptr< StochasticProcess > process_
MultiPathGeneratorBurley2020Sobol(const QuantLib::ext::shared_ptr< StochasticProcess > &, const TimeGrid &, BigNatural seed=42, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::JoeKuoD7, BigNatural scrambleSeed=43)
QuantLib::ext::shared_ptr< MultiPathGenerator< InverseCumulativeRsg< Burley2020SobolRsg, InverseCumulativeNormal > > > pg_
QuantLib::ext::shared_ptr< PathGenerator< InverseCumulativeRsg< Burley2020SobolRsg, InverseCumulativeNormal > > > pg1D_
const Sample< MultiPath > & next() const override
const QuantLib::ext::shared_ptr< StochasticProcess > process_
MultiPathGeneratorMersenneTwister(const QuantLib::ext::shared_ptr< StochasticProcess > &, const TimeGrid &, BigNatural seed=0, bool antitheticSampling=false)
QuantLib::ext::shared_ptr< PathGenerator< PseudoRandom::rsg_type > > pg1D_
QuantLib::ext::shared_ptr< MultiPathGenerator< PseudoRandom::rsg_type > > pg_
const Sample< MultiPath > & next() const override
Base class for instantiations using brownian generators from models/marketmodels/browniangenerators.
const QuantLib::ext::shared_ptr< StochasticProcess > process_
QuantLib::ext::shared_ptr< StochasticProcess1D > process1D_
MultiPathGeneratorSobolBrownianBridgeBase(const QuantLib::ext::shared_ptr< StochasticProcess > &, const TimeGrid &, SobolBrownianGenerator::Ordering ordering=SobolBrownianGenerator::Steps, BigNatural seed=0, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::JoeKuoD7)
const Sample< MultiPath > & next() const override
QuantLib::ext::shared_ptr< SobolBrownianGeneratorBase > gen_
MultiPathGeneratorSobolBrownianBridge(const QuantLib::ext::shared_ptr< StochasticProcess > &, const TimeGrid &, SobolBrownianGenerator::Ordering ordering=SobolBrownianGenerator::Steps, BigNatural seed=0, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::JoeKuoD7)
const QuantLib::ext::shared_ptr< StochasticProcess > process_
SobolRsg::DirectionIntegers directionIntegers_
MultiPathGeneratorSobol(const QuantLib::ext::shared_ptr< StochasticProcess > &, const TimeGrid &, BigNatural seed=0, SobolRsg::DirectionIntegers directionIntegers=SobolRsg::JoeKuoD7)
QuantLib::ext::shared_ptr< MultiPathGenerator< LowDiscrepancy::rsg_type > > pg_
const Sample< MultiPath > & next() const override
QuantLib::ext::shared_ptr< PathGenerator< LowDiscrepancy::rsg_type > > pg1D_
base class for multi path generators
QuantLib::ext::shared_ptr< MultiPathGeneratorBase > makeMultiPathGenerator(const SequenceType s, const QuantLib::ext::shared_ptr< StochasticProcess > &process, const TimeGrid &timeGrid, const BigNatural seed, const SobolBrownianGenerator::Ordering ordering, const SobolRsg::DirectionIntegers directionIntegers)
Make function for path generators.
std::ostream & operator<<(std::ostream &out, EquityReturnType t)