21#include <ql/math/comparison.hpp>
22#include <ql/math/distributions/normaldistribution.hpp>
23#include <ql/math/randomnumbers/mt19937uniformrng.hpp>
30RandomVariable createNewVariate(
const Size p,
const MersenneTwisterUniformRng& mt) {
31 InverseCumulativeNormal icn;
33 for (Size i = 0; i < p; ++i) {
34 r.set(i, icn(mt.nextReal()));
41 std::vector<std::vector<QuantExt::RandomVariable>>& variates,
46 for (Size i = 1; i < times.size(); ++i) {
47 QL_REQUIRE(times[i] > times[i - 1] && !QuantLib::close_enough(times[i], times[i - 1]),
48 "interpolateVariatesWithBrownianBridge():: times must be ascending, got "
49 << times[i - 1] <<
" at " << i - 1 <<
" and " << times[i] <<
" at " << i);
52 QL_REQUIRE(variates.size() == times.size(),
"interpolateVariatesWithBrownianBridge(): variates vector size ("
53 << variates.size() <<
") must match times vector size ("
54 << times.size() <<
")");
56 Size d = Null<Size>(), p = Null<Size>();
57 for (Size i = 0; i < times.size(); ++i) {
58 if (variates[i].empty())
60 if (d == Null<Size>()) {
61 d = variates[i].size();
62 p = variates[i].front().size();
64 "interpolatedVariatesWithBrownianBridge(): found RandomVariable of size 0 at time step " << i);
66 QL_REQUIRE(variates[i].size() == d,
67 "interpolateVariatesWithBrownianBridge(): variates dimension at time step "
68 << i <<
" (" << variates[i].size() <<
") is expected to be " << d);
69 for (Size j = 0; j < d; ++j) {
70 QL_REQUIRE(variates[i][j].size() == p,
"interpolateVariatesWithBrownianBridge(): variate at time step "
71 << i <<
" dimension " << j <<
" has "
72 << variates[i][j].size() <<
" paths, expected " << p);
77 QL_REQUIRE(d != Null<Size>(),
78 "interpolateVariatesWithBrownianBridge(): expected at least one time step with non-empty variate");
83 std::vector<std::vector<QuantExt::RandomVariable>> paths(times.size(), std::vector<QuantExt::RandomVariable>(d));
84 std::vector<Real> standardisedTimes(times.size(), Null<Real>());
87 Size lastTimeStep = Null<Size>();
89 std::vector<bool> initialised(times.size(),
false);
90 for (Size i = 0; i < times.size(); ++i) {
91 if (variates[i].empty())
93 standardisedTimes[i] =
static_cast<Real
>(++counter);
94 for (Size j = 0; j < d; ++j) {
95 paths[i][j] = lastTimeStep == Null<Size>() ? variates[i][j] : paths[lastTimeStep][j] + variates[i][j];
98 initialised[i] =
true;
104 MersenneTwisterUniformRng mt(seed);
106 for (Size i = 0; i < times.size(); ++i) {
110 Size l = i + 1, r = i;
111 while (l > 0 && variates[--l].empty())
113 while (r < variates.size() - 1 && variates[++r].empty())
115 if (variates[r].empty()) {
117 QL_REQUIRE(!variates[l].empty(),
118 "interpolateVariatesWithBrownianBridge(): internal error, expected variates["
119 << l <<
"] to be non-empty");
120 for (Size k = l + 1; k <= r; ++k) {
121 for (Size j = 0; j < d; ++j) {
122 paths[k][j] = paths[k - 1][j] + createNewVariate(p, mt);
124 standardisedTimes[k] = standardisedTimes[k - 1] + 1.0;
125 initialised[k] =
true;
132 if (variates[l].empty()) {
133 QL_REQUIRE(l == 0,
"interpolateVariatesWithBrownianBridge(): internal error, expected l==0, got " << l);
134 for (Size k = l; k < r; ++k) {
135 standardisedTimes[k] = times[k] / times[r];
138 for (Size k = l; k < r; ++k) {
139 standardisedTimes[k] = standardisedTimes[l] + (times[k] - times[l]) / (times[r] - times[l]);
143 for (Size k = l; k < r; ++k) {
144 if (variates[l].empty() && k == l) {
150 t =
RandomVariable(p, standardisedTimes[k] - standardisedTimes[k - 1]);
151 T =
RandomVariable(p, standardisedTimes[r] - standardisedTimes[k - 1]);
157 for (Size j = 0; j < d; ++j) {
159 ((T - t) * (k == l ?
RandomVariable(p, 0.0) : paths[k - 1][j]) + t * paths[r][j]) / T;
160 paths[k][j] = expectedValue + stdDev * createNewVariate(p, mt);
162 initialised[k] =
true;
170 for (Size i = 0; i < times.size(); ++i) {
171 RandomVariable scaling(p, std::sqrt(1.0 / (standardisedTimes[i] - (i == 0 ? 0.0 : standardisedTimes[i - 1]))));
172 if (variates[i].empty())
174 for (Size j = 0; j < d; ++j) {
175 variates[i][j] = (i == 0 ? paths[i][j] : paths[i][j] - paths[i - 1][j]) * scaling;
brownian bridge path interpolator
void interpolateVariatesWithBrownianBridge(const std::vector< QuantLib::Real > ×, std::vector< std::vector< QuantExt::RandomVariable > > &variates, const Size seed)
RandomVariable sqrt(RandomVariable x)