Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
crossassetstateprocess.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
21
22#include <ql/math/matrixutilities/pseudosqrt.hpp>
23#include <ql/processes/eulerdiscretization.hpp>
24
25#include <boost/make_shared.hpp>
26
27#include <iostream>
28
29namespace QuantExt {
30
31using namespace CrossAssetAnalytics;
32using namespace QuantLib;
33
34namespace {
35
36inline void setValue(Matrix& m, const Real& value, const QuantLib::ext::shared_ptr<const QuantExt::CrossAssetModel>& model,
37 const QuantExt::CrossAssetModel::AssetType& t1, const Size& i1,
38 const QuantExt::CrossAssetModel::AssetType& t2, const Size& i2, const Size& offset1 = 0,
39 const Size& offset2 = 0) {
40 Size i = model->pIdx(t1, i1, offset1);
41 Size j = model->pIdx(t2, i2, offset2);
42 m[i][j] = m[j][i] = value;
43}
44
45inline void setValue2(Matrix& m, const Real& value, const QuantLib::ext::shared_ptr<const QuantExt::CrossAssetModel>& model,
46 const QuantExt::CrossAssetModel::AssetType& t1, const Size& i1,
47 const QuantExt::CrossAssetModel::AssetType& t2, const Size& i2, const Size& offset1 = 0,
48 const Size& offset2 = 0) {
49 Size i = model->pIdx(t1, i1, offset1);
50 Size j = model->wIdx(t2, i2, offset2);
51 m[i][j] = value;
52}
53} // anonymous namespace
54
55CrossAssetStateProcess::CrossAssetStateProcess(QuantLib::ext::shared_ptr<const CrossAssetModel> model)
56 : StochasticProcess(), model_(std::move(model)), cirppCount_(0) {
57
58 if (model_->discretization() == CrossAssetModel::Discretization::Euler) {
59 discretization_ = QuantLib::ext::make_shared<EulerDiscretization>();
60 } else {
61 discretization_ =
62 QuantLib::ext::make_shared<CrossAssetStateProcess::ExactDiscretization>(model_, model_->salvagingAlgorithm());
63 }
64
66
67 // set up CR CIR++ processes, defer the euler discretisation check to evolve()
68 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::CR); ++i) {
70 crCirpp_.push_back(model_->crcirppModel(i)->stateProcess());
72 } else {
73 crCirpp_.push_back(QuantLib::ext::shared_ptr<CrCirppStateProcess>());
74 }
75 }
76}
77
78Size CrossAssetStateProcess::size() const { return model_->dimension(); }
79
80Size CrossAssetStateProcess::factors() const { return model_->brownians() + model_->auxBrownians(); }
81
82void CrossAssetStateProcess::resetCache(const Size timeSteps) const {
86 cache_m_.clear();
87 cache_d_.clear();
88 if (auto tmp = QuantLib::ext::dynamic_pointer_cast<CrossAssetStateProcess::ExactDiscretization>(discretization_))
89 tmp->resetCache(timeSteps);
91}
92
94 if (model_->discretization() != CrossAssetModel::Discretization::Euler)
95 return;
96 sqrtCorrelation_ = pseudoSqrt(model_->correlation(), model_->salvagingAlgorithm());
97}
98
100 Array res(model_->dimension(), 0.0);
101 /* irlgm1f / irhw processes have initial value 0 */
102 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::FX); ++i) {
103 /* fxbs processes are in log spot */
104 res[model_->pIdx(CrossAssetModel::AssetType::FX, i, 0)] = std::log(model_->fxbs(i)->fxSpotToday()->value());
105 }
106 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::EQ); ++i) {
107 /* eqbs processes are in log spot */
108 res[model_->pIdx(CrossAssetModel::AssetType::EQ, i, 0)] = std::log(model_->eqbs(i)->eqSpotToday()->value());
109 }
110 // CR CIR++ components
111 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::CR); ++i) {
113 continue;
114 QL_REQUIRE(crCirpp_[i], "crcirpp is null!");
115 Array r = crCirpp_[i]->initialValues();
116 res[model_->pIdx(CrossAssetModel::AssetType::CR, i, 0)] = r[0]; // y0
117 res[model_->pIdx(CrossAssetModel::AssetType::CR, i, 1)] = r[1]; // S(0,0) = 1
118 }
119
120 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::INF); ++i) {
121 // Second component of JY model is the inflation index process.
123 res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 1)] =
124 std::log(model_->infjy(i)->index()->fxSpotToday()->value());
125 }
126 }
127 /* infdk, crlgm1f, commodity, crstate processes have initial value 0 */
128 return res;
129}
130
131Array CrossAssetStateProcess::drift(Time t, const Array& x) const {
132 Array res(model_->dimension(), 0.0);
133 Size n = model_->components(CrossAssetModel::AssetType::IR);
134 Size n_eq = model_->components(CrossAssetModel::AssetType::EQ);
135 Real H0 = model_->irlgm1f(0)->H(t);
136 Real Hprime0 = model_->irlgm1f(0)->Hprime(t);
137 Real alpha0 = model_->irlgm1f(0)->alpha(t);
138 Real zeta0 = model_->irlgm1f(0)->zeta(t);
139 if (cacheNotReady_m_) {
140 /* z0 has drift 0 in the LGM measure but non-zero drift in the bank account measure, so start loop at i = 0 */
141 for (Size i = 0; i < n; ++i) {
142 Real Hi = model_->irlgm1f(i)->H(t);
143 Real alphai = model_->irlgm1f(i)->alpha(t);
144 if (i == 0 && model_->measure() == IrModel::Measure::BA) {
145 // ADD z0 drift in the BA measure
146 res[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] = -Hi * alphai * alphai;
147 // the auxiliary state variable is drift-free
148 res[model_->pIdx(CrossAssetModel::AssetType::IR, i, 1)] = 0.0;
149 }
150 if (i > 0) {
151 Real sigmai = model_->fxbs(i - 1)->sigma(t);
152 // ir-ir
153 Real rhozz0i =
155 // ir-fx
156 Real rhozx0i =
158 Real rhozxii =
160 // ir drifts
161 res[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] =
162 -Hi * alphai * alphai + H0 * alpha0 * alphai * rhozz0i - sigmai * alphai * rhozxii;
163 // log spot fx drifts (z0, zi independent parts)
164 res[model_->pIdx(CrossAssetModel::AssetType::FX, i - 1, 0)] =
165 H0 * alpha0 * sigmai * rhozx0i +
166 model_->irlgm1f(0)->termStructure()->forwardRate(t, t, Continuous) -
167 model_->irlgm1f(i)->termStructure()->forwardRate(t, t, Continuous) - 0.5 * sigmai * sigmai;
168 if (model_->measure() == IrModel::Measure::BA) {
169 // REMOVE the LGM measure drift contributions above
170 res[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] -= H0 * alpha0 * alphai * rhozz0i;
171 res[model_->pIdx(CrossAssetModel::AssetType::FX, i - 1, 0)] -= H0 * alpha0 * sigmai * rhozx0i;
172 }
173 }
174 }
175 /* log equity spot drifts (the cache-able parts) */
176 for (Size k = 0; k < n_eq; ++k) {
177 Size i = model_->ccyIndex(model_->eqbs(k)->currency());
178 // ir params (for equity currency)
179 Real eps_ccy = (i == 0) ? 0.0 : 1.0;
180 // Real Hi = model_->irlgm1f(i)->H(t);
181 // Real alphai = model_->irlgm1f(i)->alpha(t);
182 // eq vol
183 Real sigmask = model_->eqbs(k)->sigma(t);
184 // fx vol (eq ccy / base ccy)
185 Real sigmaxi = (i == 0) ? 0.0 : model_->fxbs(i - 1)->sigma(t);
186 // ir-eq corr
187 // Real rhozsik = model_->correlation(EQ, k, CrossAssetModel::AssetType::IR, i); // eq cur
188 Real rhozs0k =
190 // fx-eq corr
191 Real rhoxsik =
192 (i == 0) ? 0.0 : // no fx process for base-ccy
194 // ir instantaneous forward rate (from curve used for eq forward projection)
195 Real fr_i = model_->eqbs(k)->equityIrCurveToday()->forwardRate(t, t, Continuous);
196 // div yield instantaneous forward rate
197 Real fq_k = model_->eqbs(k)->equityDivYieldCurveToday()->forwardRate(t, t, Continuous);
198 res[model_->pIdx(CrossAssetModel::AssetType::EQ, k, 0)] = fr_i - fq_k + (rhozs0k * H0 * alpha0 * sigmask) -
199 (eps_ccy * rhoxsik * sigmaxi * sigmask) -
200 (0.5 * sigmask * sigmask);
201 }
202
203 // State independent pieces of JY inflation model, if there is a CAM JY component.
204 for (Size j = 0; j < model_->components(CrossAssetModel::AssetType::INF); ++j) {
205
207
208 auto p = model_->infjy(j);
209 Size i_j = model_->ccyIndex(p->currency());
210
211 // JY inflation parameter values.
212 Real H_y_j = p->realRate()->H(t);
213 Real Hp_y_j = p->realRate()->Hprime(t);
214 Real zeta_y_j = p->realRate()->zeta(t);
215 Real alpha_y_j = p->realRate()->alpha(t);
216 Real sigma_c_j = p->index()->sigma(t);
217
218 // Inflation nominal currency parameter values
219 Real H_i_j = model_->irlgm1f(i_j)->H(t);
220 Real Hp_i_j = model_->irlgm1f(i_j)->Hprime(t);
221 Real zeta_i_j = model_->irlgm1f(i_j)->zeta(t);
222
223 // Correlations
224 Real rho_zy_0j =
226 Real rho_yc_ij =
228 Real rho_zc_0j =
230
231 // JY real rate drift. It is state independent
232 auto rrDrift = -alpha_y_j * alpha_y_j * H_y_j + rho_zy_0j * alpha0 * alpha_y_j * H_y_j -
233 rho_yc_ij * alpha_y_j * sigma_c_j;
234
235 if (i_j > 0) {
236 Real sigma_x_i_j = model_->fxbs(i_j - 1)->sigma(t);
237 Real rho_yx_j_i_j = model_->correlation(CrossAssetModel::AssetType::INF, j,
238 CrossAssetModel::AssetType::FX, i_j - 1, 0, 0);
239 rrDrift -= rho_yx_j_i_j * alpha_y_j * sigma_x_i_j;
240 }
241
242 res[model_->pIdx(CrossAssetModel::AssetType::INF, j, 0)] = rrDrift;
243
244 // JY log inflation index drift (state independent piece).
245 auto indexDrift = rho_zc_0j * alpha0 * sigma_c_j * H0 - 0.5 * sigma_c_j * sigma_c_j +
246 zeta_i_j * Hp_i_j * H_i_j - zeta_y_j * Hp_y_j * H_y_j;
247
248 // Add on the f_n(0, t) - f_r(0, t) piece using the initial zero inflation term structure.
249 // Use the same dt below that is used in yield forward rate calculations.
250 auto ts = p->realRate()->termStructure();
251 Time dt = 0.0001;
252 Time t1 = std::max(t - dt / 2.0, 0.0);
253 Time t2 = t1 + dt;
254 auto z_t = ts->zeroRate(t);
255 auto z_t1 = ts->zeroRate(t1);
256 auto z_t2 = ts->zeroRate(t2);
257 indexDrift += std::log(1 + z_t) + (t / (1 + z_t)) * ((z_t2 - z_t1) / dt);
258
259 if (i_j > 0) {
260 Real sigma_x_i_j = model_->fxbs(i_j - 1)->sigma(t);
261 Real rho_cx_j_i_j = model_->correlation(CrossAssetModel::AssetType::INF, j,
262 CrossAssetModel::AssetType::FX, i_j - 1, 1, 0);
263 indexDrift -= rho_cx_j_i_j * sigma_c_j * sigma_x_i_j;
264 }
265
266 res[model_->pIdx(CrossAssetModel::AssetType::INF, j, 1)] = indexDrift;
267 }
268 }
269
270 if (timeStepsToCache_m_ > 0) {
271 cache_m_.push_back(res);
272 if (cache_m_.size() == timeStepsToCache_m_)
273 cacheNotReady_m_ = false;
274 }
275 } else {
276 res = cache_m_[timeStepCache_m_++];
279 }
280 // non-cacheable sections of drifts
281 for (Size i = 1; i < n; ++i) {
282 // log spot fx drifts (z0, zi dependent parts)
283 Real Hi = model_->irlgm1f(i)->H(t);
284 Real Hprimei = model_->irlgm1f(i)->Hprime(t);
285 Real zetai = model_->irlgm1f(i)->zeta(t);
286 res[model_->pIdx(CrossAssetModel::AssetType::FX, i - 1, 0)] +=
287 x[model_->pIdx(CrossAssetModel::AssetType::IR, 0, 0)] * Hprime0 + zeta0 * Hprime0 * H0 -
288 x[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] * Hprimei - zetai * Hprimei * Hi;
289 }
290 for (Size k = 0; k < n_eq; ++k) {
291 // log equity spot drifts (path-dependent parts)
292 // notice the assumption in below that dividend yield curve is static
293 Size i = model_->ccyIndex(model_->eqbs(k)->currency());
294 // ir params (for equity currency)
295 Real Hi = model_->irlgm1f(i)->H(t);
296 Real Hprimei = model_->irlgm1f(i)->Hprime(t);
297 Real zetai = model_->irlgm1f(i)->zeta(t);
298 res[model_->pIdx(CrossAssetModel::AssetType::EQ, k, 0)] +=
299 (x[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] * Hprimei) + (zetai * Hprimei * Hi);
300 }
301
302 // Non-cacheable portion of inflation JY drift, if there is a CAM JY component.
303 for (Size j = 0; j < model_->components(CrossAssetModel::AssetType::INF); ++j) {
305
306 auto p = model_->infjy(j);
307 Size i_j = model_->ccyIndex(p->currency());
308
309 // JY inflation parameter values.
310 Real Hp_y_j = p->realRate()->Hprime(t);
311
312 // Inflation nominal currency parameter values
313 Real Hp_i_j = model_->irlgm1f(i_j)->Hprime(t);
314
315 res[model_->pIdx(CrossAssetModel::AssetType::INF, j, 1)] +=
316 x[model_->pIdx(CrossAssetModel::AssetType::IR, i_j, 0)] * Hp_i_j -
317 x[model_->pIdx(CrossAssetModel::AssetType::INF, j, 0)] * Hp_y_j;
318 }
319 }
320
321 // COM drift
322 Size n_com = model_->components(CrossAssetModel::AssetType::COM);
323 for (Size k = 0; k < n_com; ++k) {
324 auto cm = QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzModel>(model_->comModel(k));
325 QL_REQUIRE(cm, "CommoditySchwartzModel not set");
326 if (!cm->parametrization()->driftFreeState()) {
327 // Ornstein-Uhlenbeck drift
328 Real kap = cm->parametrization()->kappaParameter();
329 res[model_->pIdx(CrossAssetModel::AssetType::COM, k, 0)] -=
330 kap * x[model_->pIdx(CrossAssetModel::AssetType::COM, k, 0)];
331 } else {
332 // zero drift
333 }
334 }
335
336 /* no drift for infdk, crlgm1f, crstate components */
337 return res;
338}
339
340Matrix CrossAssetStateProcess::diffusion(Time t, const Array& x) const {
342}
343
344Matrix CrossAssetStateProcess::diffusionOnCorrelatedBrownians(Time t, const Array& x) const {
345 if (cacheNotReady_d_) {
346 Matrix tmp = diffusionOnCorrelatedBrowniansImpl(t, x);
347 if (timeStepsToCache_d_ > 0) {
348 cache_d_.push_back(tmp);
349 if (cache_d_.size() == timeStepsToCache_d_)
350 cacheNotReady_d_ = false;
351 }
352 return tmp;
353 } else {
354 Matrix tmp = cache_d_[timeStepCache_d_++];
357 return tmp;
358 }
359}
360
362 Matrix res(model_->dimension(), model_->brownians(), 0.0);
363 Size n = model_->components(CrossAssetModel::AssetType::IR);
364 Size m = model_->components(CrossAssetModel::AssetType::FX);
365 Size d = model_->components(CrossAssetModel::AssetType::INF);
366 Size c = model_->components(CrossAssetModel::AssetType::CR);
367 Size e = model_->components(CrossAssetModel::AssetType::EQ);
368 Size com = model_->components(CrossAssetModel::AssetType::COM);
369 Size crstates = model_->components(CrossAssetModel::AssetType::CrState);
370 // ir-ir
371 for (Size i = 0; i < n; ++i) {
372 Real alphai = model_->irlgm1f(i)->alpha(t);
373 setValue2(res, alphai, model_, CrossAssetModel::AssetType::IR, i, CrossAssetModel::AssetType::IR, i, 0, 0);
374 }
375 // fx-fx
376 for (Size i = 0; i < m; ++i) {
377 Real sigmai = model_->fxbs(i)->sigma(t);
378 setValue2(res, sigmai, model_, CrossAssetModel::AssetType::FX, i, CrossAssetModel::AssetType::FX, i, 0, 0);
379 }
380 // inf-inf
381 for (Size i = 0; i < d; ++i) {
383 Real alphai = model_->infdk(i)->alpha(t);
384 Real Hi = model_->infdk(i)->H(t);
385 // DK z diffusion coefficient
387 0);
388 // DK y diffusion coefficient
390 1, 0);
391 } else {
392 auto p = model_->infjy(i);
393 // JY z diffusion coefficient
394 setValue2(res, p->realRate()->alpha(t), model_, CrossAssetModel::AssetType::INF, i,
396 // JY I diffusion coefficient
397 setValue2(res, p->index()->sigma(t), model_, CrossAssetModel::AssetType::INF, i,
399 }
400 }
401 for (Size i = 0; i < c; ++i) {
402 // Skip CR components that are not LGM
404 continue;
405 Real alphai = model_->crlgm1f(i)->alpha(t);
406 Real Hi = model_->crlgm1f(i)->H(t);
407 // crz-crz
408 setValue2(res, alphai, model_, CrossAssetModel::AssetType::CR, i, CrossAssetModel::AssetType::CR, i, 0, 0);
409 // cry-cry
410 setValue2(res, alphai * Hi, model_, CrossAssetModel::AssetType::CR, i, CrossAssetModel::AssetType::CR, i, 1, 0);
411 }
412 // eq-eq
413 for (Size i = 0; i < e; ++i) {
414 Real sigmai = model_->eqbs(i)->sigma(t);
415 setValue2(res, sigmai, model_, CrossAssetModel::AssetType::EQ, i, CrossAssetModel::AssetType::EQ, i, 0, 0);
416 }
417 // com-com
418 for (Size i = 0; i < com; ++i) {
419 Real sigmai = model_->combs(i)->sigma(t);
420 setValue2(res, sigmai, model_, CrossAssetModel::AssetType::COM, i, CrossAssetModel::AssetType::COM, i, 0, 0);
421 }
422 // creditstate-creditstate
423 for (Size i = 0; i < crstates; ++i) {
425 0);
426 }
427
428 if (model_->measure() == IrModel::Measure::BA) {
429 // aux-aux
430 Real H0 = model_->irlgm1f(0)->H(t);
431 Real alpha0 = model_->irlgm1f(0)->alpha(t);
432 setValue2(res, alpha0 * H0, model_, CrossAssetModel::AssetType::IR, 0, CrossAssetModel::AssetType::IR, 0, 1, 0);
433 }
434
435 return res;
436}
437
438namespace {
439Array getProjectedArray(const Array& source, Size start, Size length) {
440 QL_REQUIRE(source.size() >= start + length, "getProjectedArray(): internal errors: source size "
441 << source.size() << ", start" << start << ", length " << length);
442 return Array(std::next(source.begin(), start), std::next(source.begin(), start + length));
443}
444
445void applyFxDriftAdjustment(Array& state, const QuantLib::ext::shared_ptr<const CrossAssetModel>& model, Size i, Time t0,
446 Time dt) {
447
448 // the specifics depend on the ir and fx model types and their discretizations
449
452
453 QL_REQUIRE(model->discretization() == CrossAssetModel::Discretization::Euler,
454 "applyFxDrifAdjustment(): can only handle discretization Euler at the moment.");
455 Matrix corrTmp(model->irModel(i)->m(), 1);
456 for (Size k = 0; k < model->irModel(i)->m(); ++k) {
457 corrTmp(k, 0) =
458 model->correlation(CrossAssetModel::AssetType::IR, i, CrossAssetModel::AssetType::FX, i - 1, k, 0);
459 }
460 Matrix driftAdj = dt * model->fxbs(i - 1)->sigma(t0) * (transpose(model->irhw(i)->sigma_x(t0)) * corrTmp);
461 auto s = std::next(state.begin(), model->pIdx(CrossAssetModel::AssetType::IR, i, 0));
462 for (auto c = driftAdj.column_begin(0); c != driftAdj.column_end(0); ++c, ++s) {
463 *s += *c;
464 }
465
466 } else {
467 QL_FAIL("applyFxDriftAdjustment(): can only handle ir model type HW and fx model type BS currently.");
468 }
469}
470} // namespace
471
472Array CrossAssetStateProcess::evolve(Time t0, const Array& x0, Time dt, const Array& dw) const {
473
474 Array res;
475
476 // handle HW based model
477
479
480 QL_REQUIRE(model_->discretization() == CrossAssetModel::Discretization::Euler,
481 "CrossAssetStateProcess::evolve(): hw-based model only supports Euler discretization.");
482
483 const Array dz = sqrtCorrelation_ * dw;
484
485 res = Array(model_->dimension());
486
487 // eolve ir processes and store current short rates which are needed to evolve the fx components below
488
489 Array shortRates(model_->components(CrossAssetModel::AssetType::IR));
490 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::IR); ++i) {
491 auto p = model_->irModel(i)->stateProcess();
492 auto r = p->evolve(t0,
493 getProjectedArray(x0, model_->pIdx(CrossAssetModel::AssetType::IR, i, 0),
494 model_->irModel(i)->n() + model_->irModel(i)->n_aux()),
495 dt,
496 getProjectedArray(dz, model_->wIdx(CrossAssetModel::AssetType::IR, i, 0),
497 model_->irModel(i)->m() + model_->irModel(i)->m_aux()));
498 std::copy(r.begin(), r.end(), std::next(res.begin(), model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)));
499 shortRates[i] = model_->irModel(i)->shortRate(
500 t0, getProjectedArray(x0, model_->pIdx(CrossAssetModel::AssetType::IR, i, 0), model_->irModel(i)->n()));
501 }
502
503 // apply drift adjustment to ir processes in non-domestic currency
504
505 for (Size i = 1; i < model_->components(CrossAssetModel::AssetType::IR); ++i) {
506 applyFxDriftAdjustment(res, model_, i, t0, dt);
507 }
508
509 // eolve fx processes
510
511 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::FX); ++i) {
512 auto r = model_->fxModel(i)->eulerStep(
513 t0, getProjectedArray(x0, model_->pIdx(CrossAssetModel::AssetType::FX, i, 0), model_->fxModel(i)->n()),
514 dt, getProjectedArray(dz, model_->wIdx(CrossAssetModel::AssetType::FX, i, 0), model_->fxModel(i)->m()),
515 shortRates[0], shortRates[i + 1]);
516 std::copy(r.begin(), r.end(), std::next(res.begin(), model_->pIdx(CrossAssetModel::AssetType::FX, i, 0)));
517 }
518
519 // evolve com processes
520
521 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::COM); ++i) {
522 auto p = model_->comModel(i)->stateProcess();
523 auto r = p->evolve(
524 t0,
525 getProjectedArray(x0, model_->pIdx(CrossAssetModel::AssetType::COM, i, 0), model_->comModel(i)->n()),
526 dt,
527 getProjectedArray(dz, model_->wIdx(CrossAssetModel::AssetType::COM, i, 0), model_->comModel(i)->m()));
528 std::copy(r.begin(), r.end(), std::next(res.begin(), model_->pIdx(CrossAssetModel::AssetType::COM, i, 0)));
529 }
530
531 // TODO other components ...
532 QL_REQUIRE(model_->components(CrossAssetModel::AssetType::IR) +
535 model_->parametrizations().size(),
536 "CrossAssetStateProcess::evolve(): currently only IR, FX, COM supported.");
537
538 return res;
539 }
540
541 // handle LGM1F based model
542
543 if (model_->discretization() == CrossAssetModel::Discretization::Euler) {
544 const Array dz = sqrtCorrelation_ * dw;
545 const Matrix df = diffusionOnCorrelatedBrownians(t0, x0);
546 res = apply(expectation(t0, x0, dt), df * dz * std::sqrt(dt));
547
548 // CR CIRPP components
549 if (cirppCount_ > 0) {
550 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::CR); ++i) {
551 if (!crCirpp_[i])
552 continue; // ignore non-cir cr model
553 Size idx1 = model_->pIdx(CrossAssetModel::AssetType::CR, i, 0);
554 Size idx2 = model_->pIdx(CrossAssetModel::AssetType::CR, i, 1);
555 Size idxw = model_->wIdx(CrossAssetModel::AssetType::CR, i, 0);
556 Array x0Tmp(2), dwTmp(2);
557 x0Tmp[0] = x0[idx1];
558 x0Tmp[1] = x0[idx2];
559 dwTmp[0] = dz[idxw];
560 dwTmp[1] = 0.0; // not used
561 // evolve original process
562 auto r = crCirpp_[i]->evolve(t0, x0Tmp, dt, dwTmp);
563
564 // set result
565 res[idx1] = r[0]; // y
566 res[idx2] = r[1]; // S(0,T)
567 }
568 }
569 } else {
570 QL_REQUIRE(cirppCount_ == 0, "only euler discretization is supported for CIR++");
571 res = StochasticProcess::evolve(t0, x0, dt, dw);
572 }
573
574 return res;
575}
576
577CrossAssetStateProcess::ExactDiscretization::ExactDiscretization(QuantLib::ext::shared_ptr<const CrossAssetModel> model,
578 SalvagingAlgorithm::Type salvaging)
579 : model_(std::move(model)), salvaging_(salvaging) {
580
582 "CrossAssetStateProces::ExactDiscretization is only supported by LGM1F IR model types.");
583}
584
586 Time dt) const {
587 Array res;
588 if (cacheNotReady_m_) {
589 res = driftImpl1(p, t0, x0, dt);
590 if (timeStepsToCache_m_ > 0) {
591 cache_m_.push_back(res);
592 if (cache_m_.size() == timeStepsToCache_m_)
593 cacheNotReady_m_ = false;
594 }
595 } else {
596 res = cache_m_[timeStepCache_m_++];
599 }
600 Array res2 = driftImpl2(p, t0, x0, dt);
601 for (Size i = 0; i < res.size(); ++i) {
602 res[i] += res2[i];
603 }
604 return res - x0;
605}
606
608 Time dt) const {
609 if (cacheNotReady_d_) {
610 Matrix res = pseudoSqrt(covariance(p, t0, x0, dt), salvaging_);
611 // note that covariance actually does not depend on x0
612 if (timeStepsToCache_d_ > 0) {
613 cache_d_.push_back(res);
614 if (cache_d_.size() == timeStepsToCache_d_)
615 cacheNotReady_d_ = false;
616 }
617 return res;
618 } else {
619 Matrix res = cache_d_[timeStepCache_d_++];
622 return res;
623 }
624}
625
627 Time dt) const {
628 if (cacheNotReady_v_) {
629 Matrix res = covarianceImpl(p, t0, x0, dt);
630 if (timeStepsToCache_v_ > 0) {
631 cache_v_.push_back(res);
632 if (cache_v_.size() == timeStepsToCache_v_)
633 cacheNotReady_v_ = false;
634 }
635 return res;
636 } else {
637 Matrix res = cache_v_[timeStepCache_v_++];
638 if (timeStepCache_v_ == timeStepsToCache_v_)
639 timeStepCache_v_ = 0;
640 return res;
641 }
642}
643
645 Time dt) const {
646 Size n = model_->components(CrossAssetModel::AssetType::IR);
647 Size m = model_->components(CrossAssetModel::AssetType::FX);
648 Size e = model_->components(CrossAssetModel::AssetType::EQ);
649 Array res(model_->dimension(), 0.0);
650 for (Size i = 0; i < n; ++i) {
651 res[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] = ir_expectation_1(*model_, i, t0, dt);
652 }
653 for (Size j = 0; j < m; ++j) {
654 res[model_->pIdx(CrossAssetModel::AssetType::FX, j, 0)] = fx_expectation_1(*model_, j, t0, dt);
655 }
656 for (Size k = 0; k < e; ++k) {
657 res[model_->pIdx(CrossAssetModel::AssetType::EQ, k, 0)] = eq_expectation_1(*model_, k, t0, dt);
658 }
659
660 // If inflation is JY, need to take account of the drift.
661 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::INF); ++i) {
663 std::tie(res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 0)],
664 res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 1)]) =
665 inf_jy_expectation_1(*model_, i, t0, dt);
666 }
667 }
668
669 /* no COM driftImpl1 contribution for one-factor non mean-reverting commodity case,
670 no crstate contribution */
671
672 return res;
673}
674
676 Time dt) const {
677 Size n = model_->components(CrossAssetModel::AssetType::IR);
678 Size m = model_->components(CrossAssetModel::AssetType::FX);
679 Size e = model_->components(CrossAssetModel::AssetType::EQ);
680 Array res(model_->dimension(), 0.0);
681
682 if (model_->measure() == IrModel::Measure::BA) {
683 // zero AUX state drift, i.e. conditional expectation equal to the previous level as for z_i
684 res[model_->pIdx(CrossAssetModel::AssetType::IR, 0, 1)] +=
685 x0[model_->pIdx(CrossAssetModel::AssetType::IR, 0, 1)];
686 }
687
688 for (Size i = 0; i < n; ++i) {
689 res[model_->pIdx(CrossAssetModel::AssetType::IR, i, 0)] +=
691 }
692 for (Size j = 0; j < m; ++j) {
693 res[model_->pIdx(CrossAssetModel::AssetType::FX, j, 0)] +=
695 x0[model_->pIdx(CrossAssetModel::AssetType::IR, j + 1, 0)],
696 x0[model_->pIdx(CrossAssetModel::AssetType::IR, 0, 0)], dt);
697 }
698 for (Size k = 0; k < e; ++k) {
699 Size eqCcyIdx = model_->ccyIndex(model_->eqbs(k)->currency());
700 res[model_->pIdx(CrossAssetModel::AssetType::EQ, k, 0)] +=
702 x0[model_->pIdx(CrossAssetModel::AssetType::IR, eqCcyIdx, 0)], dt);
703 }
704
705 // Inflation: JY is state dependent. DK is not. Even for DK, still need to return the conditional expected value.
706 for (Size i = 0; i < model_->components(CrossAssetModel::AssetType::INF); ++i) {
708 auto i_i = model_->ccyIndex(model_->infjy(i)->currency());
709 auto zi_i_0 = x0[model_->pIdx(CrossAssetModel::AssetType::IR, i_i, 0)];
710 auto state_0 = std::make_pair(x0[model_->pIdx(CrossAssetModel::AssetType::INF, i, 0)],
711 x0[model_->pIdx(CrossAssetModel::AssetType::INF, i, 1)]);
712 std::tie(res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 0)],
713 res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 1)]) =
714 inf_jy_expectation_2(*model_, i, t0, state_0, zi_i_0, dt);
715 } else {
716 res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 0)] =
718 res[model_->pIdx(CrossAssetModel::AssetType::INF, i, 1)] =
720 }
721 }
722
723 /*! cr components have integrated drift 0, we have to return the conditional
724 expected value though, since x0 is subtracted later */
725 Size c = model_->components(CrossAssetModel::AssetType::CR);
726 for (Size i = 0; i < c; ++i) {
727 res[model_->pIdx(CrossAssetModel::AssetType::CR, i, 0)] =
728 x0[model_->pIdx(CrossAssetModel::AssetType::CR, i, 0)];
729 res[model_->pIdx(CrossAssetModel::AssetType::CR, i, 1)] =
730 x0[model_->pIdx(CrossAssetModel::AssetType::CR, i, 1)];
731 }
732
733 /* commodity components are drift-free in the one-factor non mean-reverting case */
734 Size com = model_->components(CrossAssetModel::AssetType::COM);
735 for (Size i = 0; i < com; ++i) {
736 // res[model_->pIdx(CrossAssetModel::AssetType::COM, i, 0)] =
737 // x0[model_->pIdx(CrossAssetModel::AssetType::COM, i, 0)];
738 auto cm = QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzModel>(model_->comModel(i));
739 QL_REQUIRE(cm, "CommoditySchwartzModel not set");
740 Real com0 = x0[model_->pIdx(CrossAssetModel::AssetType::COM, i, 0)];
741 if (cm->parametrization()->driftFreeState()) {
742 res[model_->pIdx(CrossAssetModel::AssetType::COM, i, 0)] = com0;
743 } else {
744 Real kap = cm->parametrization()->kappaParameter();
745 res[model_->pIdx(CrossAssetModel::AssetType::COM, i, 0)] = com0 * std::exp(-kap * dt);
746 }
747 }
748
749 for (Size j = 0; j < model_->components(CrossAssetModel::AssetType::CrState); ++j) {
750 Size idx = model_->pIdx(CrossAssetModel::AssetType::CrState, j, 0);
751 res[idx] += x0[idx]; // drift free
752 }
753
754 return res;
755}
756
758 Time dt) const {
759 Matrix res(model_->dimension(), model_->dimension(), 0.0);
760 Size n = model_->components(CrossAssetModel::AssetType::IR);
761 Size m = model_->components(CrossAssetModel::AssetType::FX);
762 Size d = model_->components(CrossAssetModel::AssetType::INF);
763 Size c = model_->components(CrossAssetModel::AssetType::CR);
764 Size e = model_->components(CrossAssetModel::AssetType::EQ);
765 Size com = model_->components(CrossAssetModel::AssetType::COM);
766 Size u = model_->components(CrossAssetModel::AssetType::CrState);
767
768 if (model_->measure() == IrModel::Measure::BA) {
769 // aux-aux
772 // aux-ir
773 for (Size j = 0; j < n; ++j) {
774 setValue(res, aux_ir_covariance(*model_, j, t0, dt), model_, CrossAssetModel::AssetType::IR, 0,
776 }
777 // aux-fx
778 for (Size j = 0; j < m; ++j) {
779 setValue(res, aux_fx_covariance(*model_, j, t0, dt), model_, CrossAssetModel::AssetType::IR, 0,
781 }
782 }
783 // ir-ir
784 for (Size i = 0; i < n; ++i) {
785 for (Size j = 0; j <= i; ++j) {
786 setValue(res, ir_ir_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
788 }
789 }
790 // ir-fx
791 for (Size i = 0; i < n; ++i) {
792 for (Size j = 0; j < m; ++j) {
793 setValue(res, ir_fx_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
795 }
796 }
797 // fx-fx
798 for (Size i = 0; i < m; ++i) {
799 for (Size j = 0; j <= i; ++j) {
800 setValue(res, fx_fx_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
802 }
803 }
804 // ir,fx,inf - inf
805 for (Size j = 0; j < d; ++j) {
806 for (Size i = 0; i <= j; ++i) {
807 // infz-infz
808 setValue(res, infz_infz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
810 // infz-infy
811 setValue(res, infz_infy_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
813 setValue(res, infz_infy_covariance(*model_, j, i, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
815 // infy-infy
816 setValue(res, infy_infy_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
818 }
819 for (Size i = 0; i < n; ++i) {
820 // ir-inf
821 setValue(res, ir_infz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
823 setValue(res, ir_infy_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
825 }
826 for (Size i = 0; i < (n - 1); ++i) {
827 // fx-inf
828 setValue(res, fx_infz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
830 setValue(res, fx_infy_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
832 }
833 }
834 // ir,fx,inf,cr - cr
835 for (Size j = 0; j < c; ++j) {
836 // Skip CR components that are not LGM
838 continue;
839 for (Size i = 0; i <= j; ++i) {
840 // Skip CR components that are not LGM
842 continue;
843 // crz-crz
844 setValue(res, crz_crz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
846 // crz-cry
847 setValue(res, crz_cry_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
849 setValue(res, crz_cry_covariance(*model_, j, i, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
851 // cry-cry
852 setValue(res, cry_cry_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
854 }
855 for (Size i = 0; i < n; ++i) {
856 // ir-cr
857 setValue(res, ir_crz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
859 setValue(res, ir_cry_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
861 }
862 for (Size i = 0; i < (n - 1); ++i) {
863 // fx-cr
864 setValue(res, fx_crz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
866 setValue(res, fx_cry_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
868 }
869 for (Size i = 0; i < d; ++i) {
870 // inf-cr
871 setValue(res, infz_crz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
873 setValue(res, infy_crz_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
875 setValue(res, infz_cry_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
877 setValue(res, infy_cry_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
879 }
880 }
881
882 // ir,fx,inf,cr,eq - eq
883 for (Size j = 0; j < e; ++j) {
884 for (Size i = 0; i <= j; ++i) {
885 // eq-eq
886 setValue(res, eq_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::EQ, i,
888 }
889 for (Size i = 0; i < n; ++i) {
890 // ir-eq
891 setValue(res, ir_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
893 }
894 for (Size i = 0; i < (n - 1); ++i) {
895 // fx-eq
896 setValue(res, fx_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
898 }
899 for (Size i = 0; i < d; ++i) {
900 // inf-eq
901 setValue(res, infz_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
903 setValue(res, infy_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
905 }
906 for (Size i = 0; i < c; ++i) {
907 // Skip CR components that are not LGM
909 continue;
910 // cr-eq
911 setValue(res, crz_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
913 setValue(res, cry_eq_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
915 }
916 }
917
918 // ir,fx,inf,cr,eq, com - com
919 for (Size j = 0; j < com; ++j) {
920 for (Size i = 0; i <= j; ++i) {
921 // com-com
922 setValue(res, com_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::COM, i,
924 }
925 for (Size i = 0; i < n; ++i) {
926 // ir-com
927 setValue(res, ir_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
929 }
930 for (Size i = 0; i < (n - 1); ++i) {
931 // fx-com
932 setValue(res, fx_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
934 }
935 for (Size i = 0; i < d; ++i) {
936 // inf-com
937 setValue(res, infz_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
939 setValue(res, infy_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::INF, i,
941 }
942 for (Size i = 0; i < c; ++i) {
943 // Skip CR components that are not LGM
945 continue;
946 // cr-com
947 setValue(res, crz_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
949 setValue(res, cry_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::CR, i,
951 }
952 for (Size i = 0; i < e; ++i) {
953 // eq-com
954 setValue(res, eq_com_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::EQ, i,
956 }
957 }
958
959 // ir, fx, creditstate - creditstate
960 for (Size i = 0; i < n; ++i) {
961 for (Size j = 0; j < u; ++j) {
962 setValue(res, ir_crstate_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::IR, i,
964 }
965 }
966 for (Size i = 0; i < m; ++i) {
967 for (Size j = 0; j < u; ++j) {
968 setValue(res, fx_crstate_covariance(*model_, i, j, t0, dt), model_, CrossAssetModel::AssetType::FX, i,
970 }
971 }
972 for (Size i = 0; i < u; ++i) {
973 for (Size j = 0; j <= i; ++j) {
974 setValue(res, crstate_crstate_covariance(*model_, i, j, t0, dt), model_,
976 }
977 }
978
979 return res;
980}
981
983 cacheNotReady_m_ = cacheNotReady_d_ = cacheNotReady_v_ = true;
984 timeStepsToCache_m_ = timeStepsToCache_d_ = timeStepsToCache_v_ = timeSteps;
985 timeStepCache_m_ = timeStepCache_d_ = timeStepCache_v_ = 0;
986 cache_m_.clear();
987 cache_v_.clear();
988 cache_d_.clear();
989}
990
991} // namespace QuantExt
virtual Matrix diffusion(const StochasticProcess &, Time t0, const Array &x0, Time dt) const override
virtual Matrix covariance(const StochasticProcess &, Time t0, const Array &x0, Time dt) const override
virtual Array driftImpl2(const StochasticProcess &, Time t0, const Array &x0, Time dt) const
virtual Matrix covarianceImpl(const StochasticProcess &, Time t0, const Array &x0, Time dt) const
virtual Array drift(const StochasticProcess &, Time t0, const Array &x0, Time dt) const override
QuantLib::ext::shared_ptr< const CrossAssetModel > model_
ExactDiscretization(QuantLib::ext::shared_ptr< const CrossAssetModel > model, SalvagingAlgorithm::Type salvaging=SalvagingAlgorithm::Spectral)
virtual Array driftImpl1(const StochasticProcess &, Time t0, const Array &x0, Time dt) const
std::vector< QuantLib::ext::shared_ptr< StochasticProcess > > crCirpp_
Array drift(Time t, const Array &x) const override
Array evolve(Time t0, const Array &x0, Time dt, const Array &dw) const override
virtual Matrix diffusionOnCorrelatedBrowniansImpl(Time t, const Array &x) const
Matrix diffusion(Time t, const Array &x) const override
virtual Matrix diffusionOnCorrelatedBrownians(Time t, const Array &x) const
CrossAssetStateProcess(QuantLib::ext::shared_ptr< const CrossAssetModel > model)
QuantLib::ext::shared_ptr< const CrossAssetModel > model_
void resetCache(const Size timeSteps) const
analytics for the cross asset model
cross asset model
Real ir_expectation_2(const CrossAssetModel &, const Size, const Real zi_0)
Real com_com_covariance(const CrossAssetModel &x, const Size k, const Size l, const Time t0, const Time dt)
Real fx_fx_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_fx_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real fx_infy_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real infy_infy_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real cry_eq_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real ir_cry_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_infy_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real fx_cry_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_eq_covariance(const CrossAssetModel &x, const Size j, const Size k, const Time t0, const Time dt)
Real infz_infy_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real fx_infz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real infy_crz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_expectation_1(const CrossAssetModel &x, const Size i, const Time t0, const Real dt)
Real ir_crz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real infz_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real eq_expectation_1(const CrossAssetModel &x, const Size k, const Time t0, const Real dt)
Real fx_crz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real crz_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real aux_fx_covariance(const CrossAssetModel &x, const Size j, const Time t0, const Time dt)
Real eq_expectation_2(const CrossAssetModel &x, const Size k, const Time t0, const Real sk_0, const Real zi_0, const Real dt)
Real infz_infz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real cry_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real infz_eq_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real infy_cry_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real crz_cry_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real eq_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real fx_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real infz_crz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real fx_expectation_2(const CrossAssetModel &x, const Size i, const Time t0, const Real xi_0, const Real zi_0, const Real z0_0, const Real dt)
Real infy_com_covariance(const CrossAssetModel &model, const Size i, const Size j, const Time t0, const Time dt)
Real ir_ir_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_infz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real aux_ir_covariance(const CrossAssetModel &x, const Size j, const Time t0, const Time dt)
Real aux_aux_covariance(const CrossAssetModel &x, const Time t0, const Time dt)
Real crstate_crstate_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real fx_eq_covariance(const CrossAssetModel &x, const Size j, const Size k, const Time t0, const Time dt)
Real cry_cry_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real crz_eq_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real ir_crstate_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real fx_crstate_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real infz_cry_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real infy_eq_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real crz_crz_covariance(const CrossAssetModel &x, const Size i, const Size j, const Time t0, const Time dt)
Real eq_eq_covariance(const CrossAssetModel &x, const Size k, const Size l, const Time t0, const Time dt)
Real fx_expectation_1(const CrossAssetModel &x, const Size i, const Time t0, const Real dt)
pair< Real, Real > inf_jy_expectation_1(const CrossAssetModel &x, Size i, Time t0, Real dt)
pair< Real, Real > inf_jy_expectation_2(const CrossAssetModel &x, Size i, Time t0, const pair< Real, Real > &state_0, Real zi_i_0, Real dt)
RandomVariable covariance(const RandomVariable &r, const RandomVariable &s)
RandomVariable expectation(const RandomVariable &r)