Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
crossassetmodel.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
24
25#include <ql/experimental/math/piecewiseintegral.hpp>
26#include <ql/math/integrals/simpsonintegral.hpp>
27#include <ql/math/matrixutilities/symmetricschurdecomposition.hpp>
28#include <ql/processes/eulerdiscretization.hpp>
29
30using namespace QuantExt::CrossAssetAnalytics;
31using std::map;
32using std::vector;
33
34namespace QuantExt {
35
36std::ostream& operator<<(std::ostream& out, const CrossAssetModel::AssetType& type) {
37 switch (type) {
39 return out << "IR";
41 return out << "FX";
43 return out << "INF";
45 return out << "CR";
47 return out << "EQ";
49 return out << "COM";
51 return out << "CrState";
52 default:
53 QL_FAIL("Did not recognise cross asset model type " << static_cast<int>(type) << ".");
54 }
55}
56
57namespace {
58
59/* derive marginal model discretizations from cam discretization
60 - "cam / Euler" should always map to "marginal model / Euler"
61 - "cam / Exact" should always map to "marginal model / Exact" which is only possible for a subset of models
62 - "cam / BestMarginalDiscretization" is to combine a global Euler scheme with the "best" marginal
63 scheme that is available, e.g. QuadraticExponentialMartingale for a Heston component */
64
65HwModel::Discretization getHwDiscretization(CrossAssetModel::Discretization discretization) {
66 if (discretization == CrossAssetModel::Discretization::Euler)
68 else
70}
71
73 if (discretization == CrossAssetModel::Discretization::Euler)
75 else
77}
78
79CommoditySchwartzModel::Discretization getComSchwartzDiscretization(CrossAssetModel::Discretization discretization) {
80 if (discretization == CrossAssetModel::Discretization::Euler)
82 else
84}
85} // namespace
86
87CrossAssetModel::CrossAssetModel(const std::vector<QuantLib::ext::shared_ptr<Parametrization>>& parametrizations,
88 const Matrix& correlation, const SalvagingAlgorithm::Type salvaging,
89 const IrModel::Measure measure, const Discretization discretization)
90 : LinkableCalibratedModel(), p_(parametrizations), rho_(correlation), salvaging_(salvaging), measure_(measure),
91 discretization_(discretization) {
92 initialize();
93}
94
95CrossAssetModel::CrossAssetModel(const std::vector<QuantLib::ext::shared_ptr<IrModel>>& currencyModels,
96 const std::vector<QuantLib::ext::shared_ptr<FxBsParametrization>>& fxParametrizations,
97 const Matrix& correlation, const SalvagingAlgorithm::Type salvaging,
98 const IrModel::Measure measure, const Discretization discretization)
99 : LinkableCalibratedModel(), irModels_(currencyModels), rho_(correlation), salvaging_(salvaging), measure_(measure),
100 discretization_(discretization) {
101 for (Size i = 0; i < currencyModels.size(); ++i) {
102 p_.push_back(currencyModels[i]->parametrizationBase());
103 }
104 for (Size i = 0; i < fxParametrizations.size(); ++i) {
105 p_.push_back(fxParametrizations[i]);
106 }
107 initialize();
108}
109
110QuantLib::ext::shared_ptr<CrossAssetStateProcess> CrossAssetModel::stateProcess() const {
111 if (stateProcess_ == nullptr) {
112 stateProcess_ = QuantLib::ext::make_shared<CrossAssetStateProcess>(shared_from_this());
113 }
114 return stateProcess_;
115}
116
117Size CrossAssetModel::components(const AssetType t) const { return components_[(Size)t]; }
118
119Size CrossAssetModel::ccyIndex(const Currency& ccy) const {
120 Size i = 0;
121 while (i < components(CrossAssetModel::AssetType::IR) && ir(i)->currency() != ccy)
122 ++i;
124 "currency " << ccy.code() << " not present in cross asset model");
125 return i;
126}
127
128Size CrossAssetModel::eqIndex(const std::string& name) const {
129 Size i = 0;
130 while (i < components(CrossAssetModel::AssetType::EQ) && eq(i)->name() != name)
131 ++i;
133 "equity name " << name << " not present in cross asset model");
134 return i;
135}
136
137Size CrossAssetModel::comIndex(const std::string& name) const {
138 Size i = 0;
139 while (i < components(CrossAssetModel::AssetType::COM) && com(i)->name() != name)
140 ++i;
142 "commodity name " << name << " not present in cross asset model");
143 return i;
144}
145
146Size CrossAssetModel::infIndex(const std::string& index) const {
147 Size i = 0;
148 while (i < components(CrossAssetModel::AssetType::INF) && inf(i)->name() != index)
149 ++i;
151 "inflation index " << index << " not present in cross asset model");
152 return i;
153}
154
155Size CrossAssetModel::crName(const std::string& name) const {
156 Size i = 0;
157 while (i < components(CrossAssetModel::AssetType::CR) && cr(i)->name() != name)
158 ++i;
160 "credit name " << name << " not present in cross asset model");
161 return i;
162}
163
165 cache_crlgm1fS_.clear();
166 cache_infdkI_.clear();
167 for (Size i = 0; i < p_.size(); ++i) {
168 p_[i]->update();
169 }
170 stateProcess()->resetCache(0); // disable cache
171 notifyObservers();
172}
173
175
176Size CrossAssetModel::brownians(const AssetType t, const Size i) const {
177 QL_REQUIRE(brownians_[(Size)t].size() > i,
178 "CrossAssetModel::brownians(): asset class " << t << ", component " << i << " not known.");
179 return brownians_[(Size)t][i];
180}
181
182Size CrossAssetModel::auxBrownians(const AssetType t, const Size i) const {
183 QL_REQUIRE(auxBrownians_[(Size)t].size() > i,
184 "CrossAssetModel::auxBrownians(): asset class " << t << ", component " << i << " not known.");
185 return auxBrownians_[(Size)t][i];
186}
187
188Size CrossAssetModel::stateVariables(const AssetType t, const Size i) const {
189 QL_REQUIRE(stateVariables_[(Size)t].size() > i,
190 "CrossAssetModel::stateVariables(): asset class " << t << ", component " << i << " not known.");
191 return stateVariables_[(Size)t][i];
192}
193
194Size CrossAssetModel::arguments(const AssetType t, const Size i) const {
195 QL_REQUIRE(numArguments_[(Size)t].size() > i,
196 "CrossAssetModel::arguments(): asset class " << t << ", component " << i << " not known.");
197 return numArguments_[(Size)t][i];
198}
199
201 QL_REQUIRE(modelType_[(Size)t].size() > i,
202 "CrossAssetModel::modelType(): asset class " << t << ", component " << i << " not known.");
203 return modelType_[(Size)t][i];
204}
205
206Size CrossAssetModel::idx(const AssetType t, const Size i) const {
207 QL_REQUIRE(idx_[(Size)t].size() > i,
208 "CrossAssetModel::idx(): asset class " << t << ", component " << i << " not known.");
209 return idx_[(Size)t][i];
210}
211
212Size CrossAssetModel::cIdx(const AssetType t, const Size i, const Size offset) const {
213 QL_REQUIRE(offset < brownians(t, i), "c-offset (" << offset << ") for asset class " << t << " and index " << i
214 << " must be in 0..." << brownians(t, i) - 1);
215 QL_REQUIRE(cIdx_[(Size)t].size() > i,
216 "CrossAssetModel::cIdx(): asset class " << t << ", component " << i << " not known.");
217 return cIdx_[(Size)t][i] + offset;
218}
219
220Size CrossAssetModel::wIdx(const AssetType t, const Size i, const Size offset) const {
221 QL_REQUIRE(offset < brownians(t, i) + auxBrownians(t, i), "c-offset (" << offset << ") for asset class " << t
222 << " and index " << i << " must be in 0..."
223 << brownians(t, i) + auxBrownians(t, i) - 1);
224 QL_REQUIRE(wIdx_[(Size)t].size() > i,
225 "CrossAssetModel::wIdx(): asset class " << t << ", component " << i << " not known.");
226 return wIdx_[(Size)t][i] + offset;
227}
228
229Size CrossAssetModel::pIdx(const AssetType t, const Size i, const Size offset) const {
230 QL_REQUIRE(offset < stateVariables(t, i), "p-offset (" << offset << ") for asset class " << t << " and index " << i
231 << " must be in 0..." << stateVariables(t, i) - 1);
232 QL_REQUIRE(pIdx_[(Size)t].size() > i,
233 "CrossAssetModel::pIdx(): asset class " << t << ", component " << i << " not known.");
234 return pIdx_[(Size)t][i] + offset;
235}
236
237Size CrossAssetModel::aIdx(const AssetType t, const Size i, const Size offset) const {
238 QL_REQUIRE(offset < arguments(t, i), "a-offset (" << offset << ") for asset class " << t << " and index " << i
239 << " must be in 0..." << arguments(t, i) - 1);
240 QL_REQUIRE(aIdx_[(Size)t].size() > i,
241 "CrossAssetModel::aIdx(): asset class " << t << ", component " << i << " not known.");
242 return aIdx_[(Size)t][i];
243}
244
245Real CrossAssetModel::correlation(const AssetType s, const Size i, const AssetType t, const Size j, const Size iOffset,
246 const Size jOffset) const {
247 return rho_(cIdx(s, i, iOffset), cIdx(t, j, jOffset));
248}
249
250void CrossAssetModel::setCorrelation(const AssetType s, const Size i, const AssetType t, const Size j, const Real value,
251 const Size iOffset, const Size jOffset) {
252 Size row = cIdx(s, i, iOffset);
253 Size column = cIdx(t, j, jOffset);
254 QL_REQUIRE(row != column || close_enough(value, 1.0), "correlation must be 1 at (" << row << "," << column << ")");
255 QL_REQUIRE(value >= -1.0 && value <= 1.0, "correlation must be in [-1,1] at (" << row << "," << column << ")");
256 // we can not check for non-negative eigenvalues, since we do not
257 // know when the correlation matrix setup is finished, but this
258 // is effectively one in the state process later on anyway and
259 // the user can also use checkCorrelationMatrix() to verify this
260 rho_(row, column) = rho_(column, row) = value;
261 update();
262}
263
271}
272
274 setIntegrationPolicy(QuantLib::ext::make_shared<SimpsonIntegral>(1.0E-8, 100), true);
275}
276
277void CrossAssetModel::setIntegrationPolicy(const QuantLib::ext::shared_ptr<Integrator> integrator,
278 const bool usePiecewiseIntegration) const {
279
280 if (!usePiecewiseIntegration) {
282 return;
283 }
284
285 // collect relevant times from parametrizations, we don't have to sort them or make them unique,
286 // this is all done in PiecewiseIntegral for us
287
288 std::vector<Time> allTimes;
289 for (Size i = 0; i < p_.size(); ++i) {
290 for (Size j = 0; j < getNumberOfParameters(i); ++j)
291 allTimes.insert(allTimes.end(), p_[i]->parameterTimes(j).begin(), p_[i]->parameterTimes(j).end());
292 }
293
294 // use piecewise integrator avoiding the step points
295 integrator_ = QuantLib::ext::make_shared<PiecewiseIntegral>(integrator, allTimes, true);
296}
297
298std::pair<CrossAssetModel::AssetType, CrossAssetModel::ModelType>
300 if (QuantLib::ext::dynamic_pointer_cast<IrHwParametrization>(p_[i]))
302 if (QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(p_[i]))
304 if (QuantLib::ext::dynamic_pointer_cast<FxBsParametrization>(p_[i]))
306 if (QuantLib::ext::dynamic_pointer_cast<InfDkParametrization>(p_[i]))
308 if (QuantLib::ext::dynamic_pointer_cast<InfJyParameterization>(p_[i]))
310 if (QuantLib::ext::dynamic_pointer_cast<CrLgm1fParametrization>(p_[i]))
312 if (QuantLib::ext::dynamic_pointer_cast<CrCirppParametrization>(p_[i]))
314 if (QuantLib::ext::dynamic_pointer_cast<EqBsParametrization>(p_[i]))
316 if (QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzParametrization>(p_[i]))
318 if (QuantLib::ext::dynamic_pointer_cast<CrStateParametrization>(p_[i]))
320 QL_FAIL("parametrization " << i << " has unknown type");
321}
322
323Size CrossAssetModel::getNumberOfParameters(const Size i) const { return p_[i]->numberOfParameters(); }
324
326 if (auto p = QuantLib::ext::dynamic_pointer_cast<IrHwParametrization>(p_[i])) {
327 return p->m();
328 }
329 if (QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(p_[i])) {
330 return 1;
331 }
332 if (QuantLib::ext::dynamic_pointer_cast<FxBsParametrization>(p_[i]))
333 return 1;
334 if (QuantLib::ext::dynamic_pointer_cast<InfDkParametrization>(p_[i]))
335 return 1;
336 if (QuantLib::ext::dynamic_pointer_cast<InfJyParameterization>(p_[i]))
337 return 2;
338 if (QuantLib::ext::dynamic_pointer_cast<CrLgm1fParametrization>(p_[i]))
339 return 1;
340 if (QuantLib::ext::dynamic_pointer_cast<CrCirppParametrization>(p_[i]))
341 return 1;
342 if (QuantLib::ext::dynamic_pointer_cast<EqBsParametrization>(p_[i]))
343 return 1;
344 if (QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzParametrization>(p_[i]))
345 return 1;
346 if (QuantLib::ext::dynamic_pointer_cast<CrStateParametrization>(p_[i]))
347 return 1;
348 QL_FAIL("parametrization " << i << " has unknown type");
349}
350
352 if (auto p = QuantLib::ext::dynamic_pointer_cast<IrHwParametrization>(p_[i])) {
353 return HwModel(p, measure_, getHwDiscretization(discretization_), i == 0).m_aux();
354 }
355 if (auto p = QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(p_[i])) {
356 return LGM(p, measure_, getLgm1fDiscretization(discretization_), i == 0).m_aux();
357 }
358 if (QuantLib::ext::dynamic_pointer_cast<FxBsParametrization>(p_[i]))
359 return 0;
360 if (QuantLib::ext::dynamic_pointer_cast<InfDkParametrization>(p_[i]))
361 return discretization_ == Discretization::Exact ? 1 : 0;
362 if (QuantLib::ext::dynamic_pointer_cast<InfJyParameterization>(p_[i]))
363 return 0;
364 if (QuantLib::ext::dynamic_pointer_cast<CrLgm1fParametrization>(p_[i]))
365 return discretization_ == Discretization::Exact ? 1 : 0;
366 if (QuantLib::ext::dynamic_pointer_cast<CrCirppParametrization>(p_[i]))
367 return 0;
368 if (QuantLib::ext::dynamic_pointer_cast<EqBsParametrization>(p_[i]))
369 return 0;
370 if (QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzParametrization>(p_[i]))
371 return 0;
372 if (QuantLib::ext::dynamic_pointer_cast<CrStateParametrization>(p_[i]))
373 return 0;
374 QL_FAIL("parametrization " << i << " has unknown type");
375}
376
378 if (auto p = QuantLib::ext::dynamic_pointer_cast<IrHwParametrization>(p_[i])) {
379 HwModel m(p, measure_, getHwDiscretization(discretization_), i == 0);
380 return m.n() + m.n_aux();
381 }
382 if (auto p = QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(p_[i])) {
383 LGM m(p, measure_, getLgm1fDiscretization(discretization_), i == 0);
384 return m.n() + m.n_aux();
385 }
386 if (QuantLib::ext::dynamic_pointer_cast<FxBsParametrization>(p_[i]))
387 return 1;
388 if (QuantLib::ext::dynamic_pointer_cast<InfDkParametrization>(p_[i]))
389 return 2;
390 if (QuantLib::ext::dynamic_pointer_cast<InfJyParameterization>(p_[i]))
391 return 2;
392 if (QuantLib::ext::dynamic_pointer_cast<CrLgm1fParametrization>(p_[i]))
393 return 2;
394 if (QuantLib::ext::dynamic_pointer_cast<CrCirppParametrization>(p_[i]))
395 return 2;
396 if (QuantLib::ext::dynamic_pointer_cast<EqBsParametrization>(p_[i]))
397 return 1;
398 if (QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzParametrization>(p_[i]))
399 return 1;
400 if (QuantLib::ext::dynamic_pointer_cast<CrStateParametrization>(p_[i]))
401 return 1;
402 QL_FAIL("parametrization " << i << " has unknown type");
403}
404
405void CrossAssetModel::updateIndices(const AssetType& t, const Size i, const Size cIdx, const Size wIdx, const Size pIdx,
406 const Size aIdx) {
407 idx_[(Size)t].push_back(i);
408 modelType_[(Size)t].push_back(getComponentType(i).second);
409 brownians_[(Size)t].push_back(getNumberOfBrownians(i));
410 auxBrownians_[(Size)t].push_back(getNumberOfAuxBrownians(i));
411 stateVariables_[(Size)t].push_back(getNumberOfStateVariables(i));
412 numArguments_[(Size)t].push_back(getNumberOfParameters(i));
413 cIdx_[(Size)t].push_back(cIdx);
414 wIdx_[(Size)t].push_back(wIdx);
415 pIdx_[(Size)t].push_back(pIdx);
416 aIdx_[(Size)t].push_back(aIdx);
418 QL_REQUIRE(wIdx_[(Size)t].back() == cIdx_[(Size)t].back(),
419 "CrossAssetModel::updateIndices(): assertion error, wIdx ("
420 << wIdx_[(Size)t].back() << ") != cIdx (" << cIdx_[(Size)t].back() << ") for asset type " << t
421 << " at index " << wIdx_[(Size)t].size() << " for Euler discretization");
422 } else {
423 QL_REQUIRE(wIdx_[(Size)t].back() == pIdx_[(Size)t].back(),
424 "CrossAssetModel::updateIndices(): assertion error, wIdx ("
425 << wIdx_[(Size)t].back() << ") != pIdx (" << pIdx_[(Size)t].back() << ") for asset type " << t
426 << " at index " << wIdx_[(Size)t].size() << " for Exact discretization");
427 }
428}
429
431
432 // count the parametrizations and check their order and their support
433
434 Size i = 0, j;
435 Size cIdxTmp = 0, wIdxTmp = 0, pIdxTmp = 0, aIdxTmp = 0;
437 idx_.resize(numberOfAssetTypes);
447
448 // IR parametrizations
449
450 bool genericCtor = irModels_.empty();
451 j = 0;
452 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::IR) {
453 QL_REQUIRE(j == 0 || getComponentType(i).second == getComponentType(0).second,
454 "All IR models must be of the same type (HW, LGM can not be mixed)");
455 // initialize ir model, if generic constructor was used
456 // evaluate bank account for j = 0 (domestic process
457 if (genericCtor) {
458 if (getComponentType(i).second == ModelType::LGM1F) {
459 irModels_.push_back(QuantLib::ext::make_shared<LinearGaussMarkovModel>(
460 QuantLib::ext::dynamic_pointer_cast<IrLgm1fParametrization>(p_[i]), measure_,
461 getLgm1fDiscretization(discretization_), j == 0));
462 } else if (getComponentType(i).second == ModelType::HW) {
463 irModels_.push_back(QuantLib::ext::make_shared<HwModel>(QuantLib::ext::dynamic_pointer_cast<IrHwParametrization>(p_[i]),
464 measure_, getHwDiscretization(discretization_),
465 j == 0));
466 } else {
467 irModels_.push_back(nullptr);
468 }
469 }
470 updateIndices(CrossAssetModel::AssetType::IR, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
471 cIdxTmp += getNumberOfBrownians(i);
473 pIdxTmp += getNumberOfStateVariables(i);
474 aIdxTmp += getNumberOfParameters(i);
475 ++j;
476 ++i;
477 }
479
480 // FX parametrizations
481
482 j = 0;
483 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::FX) {
484 fxModels_.push_back(QuantLib::ext::make_shared<FxBsModel>(QuantLib::ext::dynamic_pointer_cast<FxBsParametrization>(p_[i])));
485 updateIndices(CrossAssetModel::AssetType::FX, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
486 cIdxTmp += getNumberOfBrownians(i);
488 pIdxTmp += getNumberOfStateVariables(i);
489 aIdxTmp += getNumberOfParameters(i);
490 ++j;
491 ++i;
492 }
494
495 QL_REQUIRE(components_[(Size)CrossAssetModel::AssetType::IR] > 0, "at least one ir parametrization must be given");
496
499 "there must be n-1 fx "
500 "for n ir parametrizations, found "
501 << components_[(Size)CrossAssetModel::AssetType::IR] << " ir and "
502 << components_[(Size)CrossAssetModel::AssetType::FX] << " fx parametrizations");
503
504 // check currencies
505
506 // without an order or a hash function on Currency this seems hard
507 // to do in a simpler way ...
508 Size uniqueCurrencies = 0;
509 std::vector<Currency> currencies;
510 for (Size i = 0; i < components_[(Size)CrossAssetModel::AssetType::IR]; ++i) {
511 Size tmp = 1;
512 for (Size j = 0; j < i; ++j) {
513 if (ir(i)->currency() == currencies[j])
514 tmp = 0;
515 }
516 uniqueCurrencies += tmp;
517 currencies.push_back(ir(i)->currency());
518 }
519 QL_REQUIRE(uniqueCurrencies == components_[(Size)CrossAssetModel::AssetType::IR], "there are duplicate currencies "
520 "in the set of ir "
521 "parametrizations");
522 for (Size i = 0; i < components_[(Size)CrossAssetModel::AssetType::FX]; ++i) {
523 QL_REQUIRE(fx(i)->currency() == ir(i + 1)->currency(),
524 "fx parametrization #" << i << " must be for currency of ir parametrization #" << (i + 1)
525 << ", but they are " << fx(i)->currency() << " and " << ir(i + 1)->currency()
526 << " respectively");
527 }
528
529 // Inf parametrizations
530
531 j = 0;
532 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::INF) {
533 updateIndices(CrossAssetModel::AssetType::INF, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
534 cIdxTmp += getNumberOfBrownians(i);
536 pIdxTmp += getNumberOfStateVariables(i);
537 aIdxTmp += getNumberOfParameters(i);
538 ++j;
539 ++i;
540 // we do not check the currency, if not present among the model's
541 // currencies, it will throw below
542 }
544
545 // Cr parametrizations
546
547 j = 0;
548 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::CR) {
549
551 auto tmp = QuantLib::ext::dynamic_pointer_cast<CrCirppParametrization>(p_[i]);
552 QL_REQUIRE(tmp, "CrossAssetModelPlus::initializeParametrizations(): expected CrCirppParametrization");
553 crcirppModel_.push_back(QuantLib::ext::make_shared<CrCirpp>(tmp));
554 } else
555 crcirppModel_.push_back(QuantLib::ext::shared_ptr<CrCirpp>());
556
557 updateIndices(CrossAssetModel::AssetType::CR, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
558 cIdxTmp += getNumberOfBrownians(i);
560 pIdxTmp += getNumberOfStateVariables(i);
561 aIdxTmp += getNumberOfParameters(i);
562 ++j;
563 ++i;
564 // we do not check the currency, if not present among the model's
565 // currencies, it will throw below
566 }
568
569 // Eq parametrizations
570
571 j = 0;
572 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::EQ) {
573 updateIndices(CrossAssetModel::AssetType::EQ, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
574 cIdxTmp += getNumberOfBrownians(i);
576 pIdxTmp += getNumberOfStateVariables(i);
577 aIdxTmp += getNumberOfParameters(i);
578 ++j;
579 ++i;
580 }
582
583 // check the equity currencies to ensure they are covered by CrossAssetModel
584 for (Size i = 0; i < components(CrossAssetModel::AssetType::EQ); ++i) {
585 Currency eqCcy = eq(i)->currency();
586 try {
587 Size eqCcyIdx = ccyIndex(eqCcy);
588 QL_REQUIRE(eqCcyIdx < components_[(Size)CrossAssetModel::AssetType::IR],
589 "Invalid currency for equity " << eqbs(i)->name());
590 } catch (...) {
591 QL_FAIL("Invalid currency (" << eqCcy.code() << ") for equity " << eqbs(i)->name());
592 }
593 }
594
595 // COM parametrizations
596
597 j = 0;
598 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::COM) {
599 QuantLib::ext::shared_ptr<CommoditySchwartzParametrization> csp =
600 QuantLib::ext::dynamic_pointer_cast<CommoditySchwartzParametrization>(p_[i]);
601 QuantLib::ext::shared_ptr<CommoditySchwartzModel> csm =
602 csp ? QuantLib::ext::make_shared<CommoditySchwartzModel>(csp, getComSchwartzDiscretization(discretization_))
603 : nullptr;
604 comModels_.push_back(csm);
605 updateIndices(CrossAssetModel::AssetType::COM, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
606 cIdxTmp += getNumberOfBrownians(i);
608 pIdxTmp += getNumberOfStateVariables(i);
609 aIdxTmp += getNumberOfParameters(i);
610 ++j;
611 ++i;
612 }
614
615 // CrState parametrizations
616
617 j = 0;
618 while (i < p_.size() && getComponentType(i).first == CrossAssetModel::AssetType::CrState) {
619 updateIndices(CrossAssetModel::AssetType::CrState, i, cIdxTmp, wIdxTmp, pIdxTmp, aIdxTmp);
620 cIdxTmp += getNumberOfBrownians(i);
622 pIdxTmp += getNumberOfStateVariables(i);
623 aIdxTmp += getNumberOfParameters(i);
624 ++j;
625 ++i;
626 }
628
629 // check the equity currencies to ensure they are covered by CrossAssetModel
630 for (Size i = 0; i < components(CrossAssetModel::AssetType::COM); ++i) {
631 Currency comCcy = com(i)->currency();
632 try {
633 Size comCcyIdx = ccyIndex(comCcy);
634 QL_REQUIRE(comCcyIdx < components_[(Size)CrossAssetModel::AssetType::IR],
635 "Invalid currency for commodity " << combs(i)->name());
636 } catch (...) {
637 QL_FAIL("Invalid currency (" << comCcy.code() << ") for commodity " << combs(i)->name());
638 }
639 }
640
641 // Summary statistics
642
643 totalDimension_ = pIdxTmp;
644 totalNumberOfBrownians_ = cIdxTmp;
645 totalNumberOfAuxBrownians_ = wIdxTmp - cIdxTmp;
646
647} // initParametrizations
648
650 Size n = brownians();
651 if (rho_.empty()) {
652 rho_ = Matrix(n, n, 0.0);
653 for (Size i = 0; i < n; ++i)
654 rho_(i, i) = 1.0;
655 return;
656 }
657 QL_REQUIRE(rho_.rows() == n && rho_.columns() == n, "correlation matrix is " << rho_.rows() << " x "
658 << rho_.columns() << " but should be "
659 << n << " x " << n);
661}
662
664 Size n = rho_.rows();
665 Size m = rho_.columns();
666 QL_REQUIRE(rho_.columns() == n, "correlation matrix (" << n << " x " << m << " must be square");
667 for (Size i = 0; i < n; ++i) {
668 for (Size j = 0; j < m; ++j) {
669 QL_REQUIRE(close_enough(rho_[i][j], rho_[j][i]), "correlation matrix is not symmetric, for (i,j)=("
670 << i << "," << j << ") rho(i,j)=" << rho_[i][j]
671 << " but rho(j,i)=" << rho_[j][i]);
672 QL_REQUIRE(close_enough(std::abs(rho_[i][j]), 1.0) || (rho_[i][j] > -1.0 && rho_[i][j] < 1.0),
673 "correlation matrix has invalid entry at (i,j)=(" << i << "," << j << ") equal to "
674 << rho_[i][j]);
675 }
676 QL_REQUIRE(close_enough(rho_[i][i], 1.0), "correlation matrix must have unit diagonal elements, "
677 "but rho(i,i)="
678 << rho_[i][i] << " for i=" << i);
679 }
680
681 // if we salvage the matrix there is no point in checking for negative eigenvalues prior to that
682 if (salvaging_ == SalvagingAlgorithm::None) {
683 SymmetricSchurDecomposition ssd(rho_);
684 for (Size i = 0; i < ssd.eigenvalues().size(); ++i) {
685 QL_REQUIRE(ssd.eigenvalues()[i] >= 0.0,
686 "correlation matrix has negative eigenvalue at " << i << " (" << ssd.eigenvalues()[i] << ")");
687 }
688 }
689}
690
692 for (Size i = 0; i < p_.size(); ++i) {
693 for (Size k = 0; k < getNumberOfParameters(i); ++k) {
694 arguments_.push_back(p_[i]->parameter(k));
695 }
696 }
697}
698
701 for (Size i = 0; i < arguments_.size(); ++i) {
702 QL_REQUIRE(arguments_[i] != NULL, "unexpected error: argument " << i << " is null");
704 }
705}
706
708 QL_REQUIRE(components(CrossAssetModel::AssetType::IR) > 0, "at least one IR component must be given");
709 QL_REQUIRE(
714 p_.size(),
715 "the parametrizations must be given in the following order: ir, "
716 "fx, inf, cr, eq, com, found "
718 << " bs, " << components(CrossAssetModel::AssetType::INF) << " inf, "
720 << " eq, " << components(CrossAssetModel::AssetType::COM) << " com, "
721 << components(CrossAssetModel::AssetType::CrState) << "but there are " << p_.size()
722 << " parametrizations given in total");
723}
724
726 const Size ccy, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
727 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
728 lgm(ccy)->calibrateVolatilitiesIterative(helpers, method, endCriteria, constraint, weights);
729 update();
730}
731
733 const Size ccy, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
734 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
735 lgm(ccy)->calibrateReversionsIterative(helpers, method, endCriteria, constraint, weights);
736 update();
737}
738
740 const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
741 OptimizationMethod& method, const EndCriteria& endCriteria,
742 const Constraint& constraint, const std::vector<Real>& weights) {
743 lgm(ccy)->calibrate(helpers, method, endCriteria, constraint, weights);
744 update();
745}
746
748 const AssetType& assetType, const Size idx, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
749 OptimizationMethod& method, const EndCriteria& endCriteria, const Constraint& constraint,
750 const std::vector<Real>& weights) {
751 QL_REQUIRE(assetType == CrossAssetModel::AssetType::FX || assetType == CrossAssetModel::AssetType::EQ,
752 "Unsupported AssetType for BS calibration");
753 for (Size i = 0; i < helpers.size(); ++i) {
754 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
755 calibrate(h, method, endCriteria, constraint, weights, MoveParameter(assetType, 0, idx, i));
756 }
757 update();
758}
759
761 const AssetType& assetType, const Size aIdx, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers,
762 OptimizationMethod& method, const EndCriteria& endCriteria, const Constraint& constraint,
763 const std::vector<Real>& weights) {
764 QL_REQUIRE(assetType == CrossAssetModel::AssetType::FX || assetType == CrossAssetModel::AssetType::EQ,
765 "Unsupported AssetType for BS calibration");
766 calibrate(helpers, method, endCriteria, constraint, weights, MoveParameter(assetType, 0, aIdx, Null<Size>()));
767 update();
768}
769
771 const Size index, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
772 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
773 for (Size i = 0; i < helpers.size(); ++i) {
774 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
775 calibrate(h, method, endCriteria, constraint, weights,
777 }
778 update();
779}
780
782 const Size index, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
783 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
784 for (Size i = 0; i < helpers.size(); ++i) {
785 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
786 calibrate(h, method, endCriteria, constraint, weights,
788 }
789 update();
790}
791
793 const Size index, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
794 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
795 calibrate(helpers, method, endCriteria, constraint, weights,
796 MoveParameter(CrossAssetModel::AssetType::INF, 0, index, Null<Size>()));
797 update();
798}
799
801 const Size index, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
802 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
803 calibrate(helpers, method, endCriteria, constraint, weights,
804 MoveParameter(CrossAssetModel::AssetType::INF, 1, index, Null<Size>()));
805 update();
806}
807
808void CrossAssetModel::calibrateInfJyGlobal(Size index, const vector<QuantLib::ext::shared_ptr<CalibrationHelper>>& helpers,
809 OptimizationMethod& method, const EndCriteria& endCriteria,
810 const map<Size, bool>& toCalibrate, const Constraint& constraint,
811 const vector<Real>& weights) {
812
813 // Initialise the parameters to move first to get the size.
814 vector<bool> fixedParams = MoveParameter(CrossAssetModel::AssetType::INF, 0, index, Null<Size>());
815 std::fill(fixedParams.begin(), fixedParams.end(), true);
816
817 // Update fixedParams with parameters that need to be calibrated.
818 for (const auto& kv : toCalibrate) {
819 if (kv.second) {
820 vector<bool> tmp = MoveParameter(CrossAssetModel::AssetType::INF, kv.first, index, Null<Size>());
821 std::transform(fixedParams.begin(), fixedParams.end(), tmp.begin(), fixedParams.begin(),
822 std::logical_and<bool>());
823 }
824 }
825
826 // Perform the calibration
827 calibrate(helpers, method, endCriteria, constraint, weights, fixedParams);
828
829 update();
830}
831
833 const vector<QuantLib::ext::shared_ptr<CalibrationHelper>>& helpers,
834 OptimizationMethod& method, const EndCriteria& endCriteria,
835 const Constraint& constraint, const vector<Real>& weights) {
836
837 for (Size i = 0; i < helpers.size(); ++i) {
838 vector<QuantLib::ext::shared_ptr<CalibrationHelper>> h(1, helpers[i]);
839 calibrate(h, method, endCriteria, constraint, weights,
841 }
842
843 update();
844}
845
847 const Size index, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
848 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
849 for (Size i = 0; i < helpers.size(); ++i) {
850 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
851 calibrate(h, method, endCriteria, constraint, weights,
853 }
854 update();
855}
856
858 const Size index, const std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>>& helpers, OptimizationMethod& method,
859 const EndCriteria& endCriteria, const Constraint& constraint, const std::vector<Real>& weights) {
860 for (Size i = 0; i < helpers.size(); ++i) {
861 std::vector<QuantLib::ext::shared_ptr<BlackCalibrationHelper>> h(1, helpers[i]);
862 calibrate(h, method, endCriteria, constraint, weights,
864 }
865 update();
866}
867
868std::pair<Real, Real> CrossAssetModel::infdkV(const Size i, const Time t, const Time T) {
869 Size ccy = ccyIndex(infdk(i)->currency());
870 cache_key k = {i, ccy, t, T};
871 boost::unordered_map<cache_key, std::pair<Real, Real>>::const_iterator it = cache_infdkI_.find(k);
872 Real V0, V_tilde;
873
874 if (it == cache_infdkI_.end()) {
875 V0 = infV(i, ccy, 0, t);
876 V_tilde = infV(i, ccy, t, T) - infV(i, ccy, 0, T) + infV(i, ccy, 0, t);
877 cache_infdkI_.insert(std::make_pair(k, std::make_pair(V0, V_tilde)));
878 } else {
879 // take V0 and V_tilde from cache
880 V0 = it->second.first;
881 V_tilde = it->second.second;
882 }
883 return std::make_pair(V0, V_tilde);
884}
885
886std::pair<Real, Real> CrossAssetModel::infdkI(const Size i, const Time t, const Time T, const Real z, const Real y) {
887 QL_REQUIRE(t < T || close_enough(t, T), "infdkI: t (" << t << ") <= T (" << T << ") required");
888 Real V0, V_tilde;
889 std::pair<Real, Real> Vs = infdkV(i, t, T);
890 V0 = Vs.first;
891 V_tilde = Vs.second;
892 Real Hyt = Hy(i).eval(*this, t);
893 Real HyT = Hy(i).eval(*this, T);
894
895 // TODO account for seasonality ...
896 // compute final results depending on z and y
897 const auto& zts = infdk(i)->termStructure();
898 auto dc = irlgm1f(0)->termStructure()->dayCounter();
899 bool indexIsInterpolated = true; // FIXME, though in line with the comment below
900 Real growth_t = inflationGrowth(zts, t, dc, indexIsInterpolated);
901 Real It = growth_t * std::exp(Hyt * z - y - V0);
902 Real Itilde_t_T = inflationGrowth(zts, T, dc, indexIsInterpolated) / growth_t * std::exp((HyT - Hyt) * z + V_tilde);
903 // concerning interpolation there is an inaccuracy here: if the index
904 // is not interpolated, we still simulate the index value as of t
905 // (and T), although we should go back to t, T which corresponds to
906 // the last actual publication time of the index => is the approximation
907 // here in this sense good enough that we can tolerate this?
908 return std::make_pair(It, Itilde_t_T);
909}
910
911Real CrossAssetModel::infdkYY(const Size i, const Time t, const Time S, const Time T, const Real z, const Real y,
912 const Real irz) {
913 Size ccy = ccyIndex(infdk(i)->currency());
914
915 // Set Convexity adjustment set to 1.
916 // TODO: Add calculation for DK convexity adjustment
917 Real C_tilde = 1;
918
919 Real I_tildeS = infdkI(i, t, S, z, y).second;
920 Real I_tildeT = infdkI(i, t, T, z, y).second;
921 Real Pn_t_T = lgm(ccy)->discountBond(t, T, irz);
922
923 Real yySwaplet = (I_tildeT / I_tildeS) * Pn_t_T * C_tilde - Pn_t_T;
924
925 return yySwaplet;
926}
927
928std::pair<Real, Real> CrossAssetModel::crlgm1fS(const Size i, const Size ccy, const Time t, const Time T, const Real z,
929 const Real y) const {
931 "ccy index (" << ccy << ") must be in 0..." << (components(CrossAssetModel::AssetType::IR) - 1));
932 QL_REQUIRE(t < T || close_enough(t, T), "crlgm1fS: t (" << t << ") <= T (" << T << ") required");
934 "model at " << i << " is not CR-LGM1F");
935 cache_key k = {i, ccy, t, T};
936 boost::unordered_map<cache_key, std::pair<Real, Real>>::const_iterator it = cache_crlgm1fS_.find(k);
937 Real V0, V_tilde;
938 Real Hlt = Hl(i).eval(*this, t);
939 Real HlT = Hl(i).eval(*this, T);
940
941 if (it == cache_crlgm1fS_.end()) {
942 // compute V0 and V_tilde
943 if (ccy == 0) {
944 // domestic credit
945 Real Hzt = Hz(0).eval(*this, t);
946 Real HzT = Hz(0).eval(*this, T);
947 Real zetal0 = zetal(i).eval(*this, t);
948 Real zetal1 = integral(*this, P(Hl(i), al(i), al(i)), 0.0, t);
949 Real zetal2 = integral(*this, P(Hl(i), Hl(i), al(i), al(i)), 0.0, t);
950 Real zetanl0 = integral(*this, P(rzl(0, i), az(0), al(i)), 0.0, t);
951 Real zetanl1 = integral(*this, P(rzl(0, i), Hl(i), az(0), al(i)), 0.0, t);
952 // opposite signs for last two terms in the book
953 V0 = 0.5 * Hlt * Hlt * zetal0 - Hlt * zetal1 + 0.5 * zetal2 + Hzt * Hlt * zetanl0 - Hzt * zetanl1;
954 V_tilde = -0.5 * (HlT * HlT - Hlt * Hlt) * zetal0 + (HlT - Hlt) * zetal1 -
955 (HzT * HlT - Hzt * Hlt) * zetanl0 + (HzT - Hzt) * zetanl1;
956 } else {
957 // foreign credit
958 V0 = crV(i, ccy, 0, t);
959 V_tilde = crV(i, ccy, t, T) - crV(i, ccy, 0, T) + crV(i, ccy, 0, t);
960 }
961 cache_crlgm1fS_.insert(std::make_pair(k, std::make_pair(V0, V_tilde)));
962 } else {
963 // take V0 and V_tilde from cache
964 V0 = it->second.first;
965 V_tilde = it->second.second;
966 }
967 // compute final results depending on z and y
968 // opposite sign for V0 in the book
969 Real St = crlgm1f(i)->termStructure()->survivalProbability(t) * std::exp(-Hlt * z + y - V0);
970 Real Stilde_t_T = crlgm1f(i)->termStructure()->survivalProbability(T) /
971 crlgm1f(i)->termStructure()->survivalProbability(t) * std::exp(-(HlT - Hlt) * z + V_tilde);
972 return std::make_pair(St, Stilde_t_T);
973}
974
975std::pair<Real, Real> CrossAssetModel::crcirppS(const Size i, const Time t, const Time T, const Real y,
976 const Real s) const {
978 "model at " << i << " is not CR-CIR");
979 if (close_enough(t, T))
980 return std::make_pair(s, 1.0);
981 else
982 return std::make_pair(s, crcirppModel_[i]->survivalProbability(t, T, y));
983}
984
985Real CrossAssetModel::infV(const Size i, const Size ccy, const Time t, const Time T) const {
986 Real HyT = Hy(i).eval(*this, T);
987 Real HdT = irlgm1f(0)->H(T);
989 Real V;
990 if (ccy == 0) {
991 V = 0.5 * (HyT * HyT * (zetay(i).eval(*this, T) - zetay(i).eval(*this, t)) -
992 2.0 * HyT * integral(*this, P(Hy(i), ay(i), ay(i)), t, T) +
993 integral(*this, P(Hy(i), Hy(i), ay(i), ay(i)), t, T)) -
994 rhody * HdT *
995 (HyT * integral(*this, P(az(0), ay(i)), t, T) - integral(*this, P(az(0), Hy(i), ay(i)), t, T));
996 } else {
997 Real HfT = irlgm1f(ccy)->H(T);
1000 V = 0.5 * (HyT * HyT * (zetay(i).eval(*this, T) - zetay(i).eval(*this, t)) -
1001 2.0 * HyT * integral(*this, P(Hy(i), ay(i), ay(i)), t, T) +
1002 integral(*this, P(Hy(i), Hy(i), ay(i), ay(i)), t, T)) -
1003 rhody * (HyT * integral(*this, P(Hz(0), az(0), ay(i)), t, T) -
1004 integral(*this, P(Hz(0), az(0), Hy(i), ay(i)), t, T)) -
1005 rhofy * (HfT * HyT * integral(*this, P(az(ccy), ay(i)), t, T) -
1006 HfT * integral(*this, P(az(ccy), Hy(i), ay(i)), t, T) -
1007 HyT * integral(*this, P(Hz(ccy), az(ccy), ay(i)), t, T) +
1008 integral(*this, P(Hz(ccy), az(ccy), Hy(i), ay(i)), t, T)) +
1009 rhoxy * (HyT * integral(*this, P(sx(ccy - 1), ay(i)), t, T) -
1010 integral(*this, P(sx(ccy - 1), Hy(i), ay(i)), t, T));
1011 }
1012 return V;
1013}
1014
1015Real CrossAssetModel::crV(const Size i, const Size ccy, const Time t, const Time T) const {
1016 Real HlT = Hl(i).eval(*this, T);
1017 Real HfT = Hz(ccy).eval(*this, T);
1021 return 0.5 * (HlT * HlT * (zetal(i).eval(*this, T) - zetal(i).eval(*this, t)) -
1022 2.0 * HlT * integral(*this, P(Hl(i), al(i), al(i)), t, T) +
1023 integral(*this, P(Hl(i), Hl(i), al(i), al(i)), t, T)) +
1024 rhodl * (HlT * integral(*this, P(Hz(0), az(0), al(i)), t, T) -
1025 integral(*this, P(Hz(0), az(0), Hl(i), al(i)), t, T)) +
1026 rhofl * (HfT * HlT * integral(*this, P(az(ccy), al(i)), t, T) -
1027 HfT * integral(*this, P(az(ccy), Hl(i), al(i)), t, T) -
1028 HlT * integral(*this, P(Hz(ccy), az(ccy), al(i)), t, T) +
1029 integral(*this, P(Hz(ccy), az(ccy), Hl(i), al(i)), t, T)) -
1030 rhoxl * (HlT * integral(*this, P(sx(ccy - 1), al(i)), t, T) -
1031 integral(*this, P(sx(ccy - 1), Hl(i), al(i)), t, T));
1032}
1033
1034Handle<ZeroInflationTermStructure> inflationTermStructure(const QuantLib::ext::shared_ptr<CrossAssetModel>& model, Size index) {
1035
1036 if (model->modelType(CrossAssetModel::AssetType::INF, index) == CrossAssetModel::ModelType::DK) {
1037 return model->infdk(index)->termStructure();
1038 } else if (model->modelType(CrossAssetModel::AssetType::INF, index) == CrossAssetModel::ModelType::JY) {
1039 return model->infjy(index)->realRate()->termStructure();
1040 } else {
1041 QL_FAIL("Expected inflation model to be either DK or JY.");
1042 }
1043}
1044
1046 const Size index, const Size i, std::vector<bool>& res) {
1047 for (Size j = 0; j < components(t); ++j) {
1048 for (Size k = 0; k < arguments(t, j); ++k) {
1049 std::vector<bool> tmp1(p_[idx(t, j)]->parameter(k)->size(), true);
1050 if ((param == Null<Size>() || k == param) && t == v && index == j) {
1051 for (Size ii = 0; ii < tmp1.size(); ++ii) {
1052 if (i == Null<Size>() || i == ii) {
1053 tmp1[ii] = false;
1054 }
1055 }
1056 }
1057 res.insert(res.end(), tmp1.begin(), tmp1.end());
1058 }
1059 }
1060}
1061
1062std::vector<bool> CrossAssetModel::MoveParameter(const AssetType t, const Size param, const Size index, const Size i) {
1063 QL_REQUIRE(param == Null<Size>() || param < arguments(t, index), "parameter for " << t << " at " << index << " ("
1064 << param << ") out of bounds 0..."
1065 << arguments(t, index) - 1);
1066 std::vector<bool> res(0);
1073 return res;
1074}
1075
1076} // namespace QuantExt
virtual void initializeParametrizations()
const QuantLib::ext::shared_ptr< Parametrization > eq(const Size i) const
virtual void checkModelConsistency() const
Size pIdx(const AssetType t, const Size i, const Size offset=0) const
std::vector< std::vector< Size > > auxBrownians_
const QuantLib::ext::shared_ptr< InfDkParametrization > infdk(const Size i) const
static constexpr Size numberOfAssetTypes
virtual Size getNumberOfStateVariables(const Size i) const
Size cIdx(const AssetType t, const Size i, const Size offset=0) const
const QuantLib::ext::shared_ptr< Parametrization > com(const Size i) const
Size comIndex(const std::string &comName) const
Size arguments(const AssetType t, const Size i) const
std::vector< std::vector< Size > > numArguments_
void setCorrelation(const AssetType s, const Size i, const AssetType t, const Size j, const Real value, const Size iOffset=0, const Size jOffset=0)
void calibrateInfDkVolatilitiesIterative(const Size index, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
void calibrateInfDkReversionsGlobal(const Size index, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
void calibrateInfJyGlobal(QuantLib::Size index, const std::vector< QuantLib::ext::shared_ptr< QuantLib::CalibrationHelper > > &helpers, QuantLib::OptimizationMethod &method, const QuantLib::EndCriteria &endCriteria, const std::map< QuantLib::Size, bool > &toCalibrate, const QuantLib::Constraint &constraint=QuantLib::Constraint(), const std::vector< QuantLib::Real > &weights=std::vector< QuantLib::Real >())
virtual Size getNumberOfAuxBrownians(const Size i) const
std::vector< std::vector< Size > > cIdx_
std::pair< Real, Real > infdkV(const Size i, const Time t, const Time T)
virtual Size getNumberOfBrownians(const Size i) const
const QuantLib::ext::shared_ptr< Integrator > integrator() const
QuantLib::ext::shared_ptr< CrossAssetStateProcess > stateProcess() const
const QuantLib::ext::shared_ptr< IrLgm1fParametrization > irlgm1f(const Size ccy) const
const QuantLib::ext::shared_ptr< EqBsParametrization > eqbs(const Size ccy) const
void calibrateBsVolatilitiesIterative(const AssetType &assetType, const Size aIdx, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
virtual void initializeCorrelation()
Size crName(const std::string &name) const
void calibrateIrLgm1fVolatilitiesIterative(const Size ccy, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
void calibrateInfDkVolatilitiesGlobal(const Size index, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
void calibrateCrLgm1fReversionsIterative(const Size index, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Size infIndex(const std::string &index) const
std::pair< Real, Real > crlgm1fS(const Size i, const Size ccy, const Time t, const Time T, const Real z, const Real y) const
void setIntegrationPolicy(const QuantLib::ext::shared_ptr< Integrator > integrator, const bool usePiecewiseIntegration=true) const
Size ccyIndex(const Currency &ccy) const
virtual Size getNumberOfParameters(const Size i) const
std::vector< std::vector< ModelType > > modelType_
std::pair< Real, Real > crcirppS(const Size i, const Time t, const Time T, const Real y, const Real s) const
virtual void initializeArguments()
QuantLib::ext::shared_ptr< CrossAssetStateProcess > stateProcess_
boost::unordered_map< cache_key, std::pair< Real, Real >, cache_hasher > cache_crlgm1fS_
const QuantLib::ext::shared_ptr< CrLgm1fParametrization > crlgm1f(const Size i) const
virtual std::pair< AssetType, ModelType > getComponentType(const Size i) const
void generateArguments() override
std::vector< std::vector< Size > > pIdx_
std::vector< bool > MoveParameter(const AssetType t, const Size param, const Size index, const Size i)
virtual void initDefaultIntegrator()
Real infdkYY(const Size i, const Time t, const Time S, const Time T, const Real z, const Real y, const Real irz)
std::vector< Size > components_
std::vector< QuantLib::ext::shared_ptr< Parametrization > > p_
std::vector< QuantLib::ext::shared_ptr< CrCirpp > > crcirppModel_
const QuantLib::ext::shared_ptr< Parametrization > fx(const Size ccy) const
void calibrateCrLgm1fVolatilitiesIterative(const Size index, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Size eqIndex(const std::string &eqName) const
SalvagingAlgorithm::Type salvaging_
std::vector< QuantLib::ext::shared_ptr< IrModel > > irModels_
std::pair< Real, Real > infdkI(const Size i, const Time t, const Time T, const Real z, const Real y)
void updateIndices(const AssetType &t, const Size i, const Size cIdx, const Size wIdx, const Size pIdx, const Size aIdx)
const QuantLib::ext::shared_ptr< CommoditySchwartzParametrization > combs(const Size ccy) const
Real infV(const Size idx, const Size ccy, const Time t, const Time T) const
std::vector< std::vector< Size > > brownians_
void calibrateInfDkReversionsIterative(const Size index, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Size aIdx(const AssetType t, const Size i, const Size offset=0) const
std::vector< std::vector< Size > > idx_
Size wIdx(const AssetType t, const Size i, const Size offset=0) const
void calibrateIrLgm1fReversionsIterative(const Size ccy, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
void calibrateInfJyIterative(QuantLib::Size inflationModelIndex, QuantLib::Size parameterIndex, const std::vector< QuantLib::ext::shared_ptr< QuantLib::CalibrationHelper > > &helpers, QuantLib::OptimizationMethod &method, const QuantLib::EndCriteria &endCriteria, const QuantLib::Constraint &constraint=QuantLib::Constraint(), const std::vector< QuantLib::Real > &weights=std::vector< QuantLib::Real >())
Real crV(const Size idx, const Size ccy, const Time t, const Time T) const
Size idx(const AssetType t, const Size i) const
boost::unordered_map< cache_key, std::pair< Real, Real >, cache_hasher > cache_infdkI_
void calibrateBsVolatilitiesGlobal(const AssetType &assetType, const Size aIdx, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
QuantLib::ext::shared_ptr< Integrator > integrator_
ModelType modelType(const AssetType t, const Size i) const
std::vector< QuantLib::ext::shared_ptr< FxModel > > fxModels_
std::vector< std::vector< Size > > stateVariables_
void appendToFixedParameterVector(const AssetType t, const AssetType v, const Size param, const Size index, const Size i, std::vector< bool > &res)
const QuantLib::ext::shared_ptr< Parametrization > cr(const Size i) const
std::vector< std::vector< Size > > aIdx_
Size components(const AssetType t) const
Size stateVariables(const AssetType t, const Size i) const
std::vector< QuantLib::ext::shared_ptr< CommodityModel > > comModels_
std::vector< std::vector< Size > > wIdx_
const QuantLib::ext::shared_ptr< LinearGaussMarkovModel > lgm(const Size ccy) const
CrossAssetModel(const std::vector< QuantLib::ext::shared_ptr< Parametrization > > &parametrizations, const Matrix &correlation=Matrix(), const SalvagingAlgorithm::Type salvaging=SalvagingAlgorithm::None, const IrModel::Measure measure=IrModel::Measure::LGM, const Discretization discretization=Discretization::Exact)
const QuantLib::ext::shared_ptr< Parametrization > inf(const Size i) const
const QuantLib::ext::shared_ptr< Parametrization > ir(const Size ccy) const
const Matrix & correlation() const
void calibrateIrLgm1fGlobal(const Size ccy, const std::vector< QuantLib::ext::shared_ptr< BlackCalibrationHelper > > &helpers, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >())
Size n() const override
Definition: hwmodel.cpp:69
Size n_aux() const override
Definition: hwmodel.cpp:71
Size m_aux() const override
Definition: hwmodel.cpp:72
Linear Gauss Morkov Model.
Definition: lgm.hpp:46
Size n() const override
Definition: lgm.cpp:58
Size n_aux() const override
Definition: lgm.cpp:60
Size m_aux() const override
Definition: lgm.cpp:61
Calibrated model class with linkable parameters.
const QuantLib::ext::shared_ptr< Constraint > & constraint() const
EndCriteria::Type endCriteria() const
Returns end criteria result.
virtual void calibrate(const std::vector< QuantLib::ext::shared_ptr< CalibrationHelper > > &, OptimizationMethod &method, const EndCriteria &endCriteria, const Constraint &constraint=Constraint(), const std::vector< Real > &weights=std::vector< Real >(), const std::vector< bool > &fixParameters=std::vector< bool >())
Calibrate to a set of market instruments (usually caps/swaptions)
std::vector< QuantLib::ext::shared_ptr< Parameter > > arguments_
Real value(const Array &params, const std::vector< QuantLib::ext::shared_ptr< CalibrationHelper > > &)
analytics for the cross asset model
cross asset model
Real integral(const CrossAssetModel &model, const E &e, const Real a, const Real b)
const P2_< E1, E2 > P(const E1 &e1, const E2 &e2)
hull white n Factor model class
some inflation related utilities.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::ostream & operator<<(std::ostream &out, EquityReturnType t)
LinearGaussMarkovModel LGM
Definition: lgm.hpp:164
Handle< ZeroInflationTermStructure > inflationTermStructure(const QuantLib::ext::shared_ptr< CrossAssetModel > &model, Size index)
Real inflationGrowth(const QuantLib::ext::shared_ptr< CrossAssetModel > &model, Size index, Time S, Time T, Real irState, Real rrState, bool indexIsInterpolated)
parameter giving access to calibration machinery
Real eval(const CrossAssetModel &x, const Real t) const
INF H component. May relate to real rate portion of JY model or z component of DK model.
QuantLib::Real eval(const CrossAssetModel &x, const QuantLib::Real t) const
Real eval(const CrossAssetModel &x, const Real t) const
INF alpha component. May relate to real rate portion of JY model or z component of DK model.
Real eval(const CrossAssetModel &x, const Real t) const
INF zeta component. May relate to real rate portion of JY model or z component of DK model.
Real eval(const CrossAssetModel &x, const Real t) const