38#include <ql/math/comparison.hpp>
39#include <ql/quotes/simplequote.hpp>
48 const std::vector<std::string>& currencies,
49 const std::vector<Handle<YieldTermStructure>>& curves,
50 const std::vector<Handle<Quote>>& fxSpots,
51 const std::vector<std::pair<std::string, QuantLib::ext::shared_ptr<InterestRateIndex>>>& irIndices,
52 const std::vector<std::pair<std::string, QuantLib::ext::shared_ptr<ZeroInflationIndex>>>& infIndices,
53 const std::vector<std::string>& indices,
const std::vector<std::string>& indexCurrencies,
54 const std::set<Date>& simulationDates,
const McParams& mcParams,
const Size timeStepsPerYear,
56 const std::vector<Size>& projectedStateProcessIndices,
57 const std::vector<std::string>& conditionalExpectationModelStates)
58 :
ModelImpl(curves.front()->dayCounter(), paths, currencies, irIndices, infIndices, indices, indexCurrencies,
59 simulationDates, iborFallbackConfig),
60 cam_(cam), curves_(curves), fxSpots_(fxSpots), mcParams_(mcParams), timeStepsPerYear_(timeStepsPerYear),
61 projectedStateProcessIndices_(projectedStateProcessIndices) {
65 QL_REQUIRE(!
cam_.empty(),
"model is empty");
79 conditionalExpectationModelStates.empty() ||
80 std::find(conditionalExpectationModelStates.begin(), conditionalExpectationModelStates.end(),
"IR") !=
81 conditionalExpectationModelStates.end();
83 conditionalExpectationModelStates.empty() ||
84 std::find(conditionalExpectationModelStates.begin(), conditionalExpectationModelStates.end(),
"INF") !=
85 conditionalExpectationModelStates.end();
87 conditionalExpectationModelStates.empty() ||
88 std::find(conditionalExpectationModelStates.begin(), conditionalExpectationModelStates.end(),
"Asset") !=
89 conditionalExpectationModelStates.end();
123 QL_REQUIRE(!
inTrainingPhase_,
"GaussianCam::performCalculations(): state inTrainingPhase should be false, this was "
124 "not resetted appropriately.");
137 std::vector<Real> times;
160 infStates_[d] = std::vector<std::pair<RandomVariable, RandomVariable>>(
187 for (Size i = 0; i <
irIndices_.size(); ++i) {
204 for (Size i = 0; i <
indices_.size(); ++i) {
208 QL_REQUIRE(ccyIdx > 0,
"fx index '" <<
indices_[i] <<
"' has unexpected for ccy = base ccy");
221 QL_FAIL(
"GuassianCam::performCalculations(): index '" <<
indices_[i].
name()
222 <<
"' expected to be FX, EQ, COMM");
236 std::map<Date, std::vector<RandomVariable>>& irStates,
237 std::map<Date, std::vector<std::pair<RandomVariable, RandomVariable>>>& infStates,
238 const std::vector<Real>& times,
const bool isTraining)
const {
241 auto process =
cam_->stateProcess();
246 for (Size k = 0; k <
indices_.size(); ++k) {
272 auto lgmProcess = QuantLib::ext::dynamic_pointer_cast<StochasticProcess1D>(
cam_->lgm(0)->stateProcess());
274 std::vector<Real> stdDevs(times.size() - 1);
275 for (Size i = 0; i < times.size() - 1; ++i) {
276 stdDevs[i] = lgmProcess->stdDeviation(times[i], 0.0, times[i + 1] - times[i]);
285 for (
auto s = std::next(irStates.begin(), 1); s != irStates.end(); ++s)
286 for (
auto& r : s->second)
289 for (Size path = 0; path < nSamples; ++path) {
290 auto p = gen->next();
293 for (Size i = 0; i < times.size() - 1; ++i) {
294 state += stdDevs[i] * p.value[i][0];
296 irStates[*date][0].data()[path] = state;
304 QuantLib::ext::shared_ptr<MultiPathGeneratorBase> pathGen;
309 std::vector<std::vector<std::vector<Real>>> pathValues(
311 std::vector<std::vector<Real>>(process->size(), std::vector<Real>(nSamples)));
317 if (
auto tmp = QuantLib::ext::dynamic_pointer_cast<CrossAssetStateProcess>(process)) {
325 for (Size i = 0; i < nSamples; ++i) {
326 MultiPath path = pathGen->next().value;
328 for (Size k = 0; k < process->size(); ++k) {
337 std::vector<Real> relevantPathTimes;
338 std::vector<Size> relevantPathIndices;
341 size_t pathIdx = (*injectedPathRelevantPathIndexes_)[j];
342 size_t timeIdx = (*injectedPathRelevantTimeIndexes_)[j];
344 relevantPathIndices.push_back(pathIdx);
346 Array y(relevantPathTimes.size());
347 auto pathInterpolator =
349 pathInterpolator.enableExtrapolation();
350 for (Size i = 0; i < nSamples; ++i) {
351 for (Size k = 0; k < process->size(); ++k) {
352 for (Size j = 0; j < relevantPathTimes.size(); ++j) {
355 pathInterpolator.update();
356 for (Size j = 0; j < times.size() - 1; ++j) {
357 pathValues[j][k][i] = pathInterpolator(times[j + 1]);
364 std::vector<std::vector<RandomVariable*>> rvs(
369 for (Size j = 0; j <
indices_.size(); ++j) {
370 rvs[j][i] = &paths[*date][j];
374 for (Size k = 0; k <
indices_.size(); ++k) {
376 for (Size i = 0; i < nSamples; ++i) {
383 std::vector<std::vector<RandomVariable*>> rvs2(
389 rvs2[j][i] = &irStates[*date2][j];
390 rvs2[j][i]->expand();
395 for (Size i = 0; i < nSamples; ++i) {
402 std::vector<std::vector<RandomVariable*>> rvs3a(
404 std::vector<std::vector<RandomVariable*>> rvs3b(
410 rvs3a[j][i] = &infStates[*date3][j].first;
411 rvs3b[j][i] = &infStates[*date3][j].second;
412 rvs3a[j][i]->expand();
413 rvs3b[j][i]->expand();
418 for (Size i = 0; i < nSamples; ++i) {
432 for (Size i = 0; i < tmp.
size(); ++i) {
435 Array(1, std::log(res[i]))));
438 }
else if (fwd != Null<Date>()) {
441 QL_REQUIRE(ccy !=
currencies_.end(),
"GaussianCam::getIndexValue(): can not get currency for index #"
442 << indexNo <<
"(" <<
indices_.at(indexNo) <<
")");
454 QL_FAIL(
"GaussianGam::getIndexValue(): did not recognise index #" << indexNo <<
"("
463 if (fwd != Null<Date>())
470 return cacheValue->second;
484 if (fwd != Null<Date>())
487 auto const& state =
infStates_.at(obsDate + lag).at(indexNo);
489 Real t =
infIndices_[indexNo].second->zeroInflationTermStructure()->timeFromReference(obsDate + lag);
490 Real T =
infIndices_[indexNo].second->zeroInflationTermStructure()->timeFromReference(
fixingDate + lag);
491 QL_DEPRECATED_DISABLE_WARNING
492 bool isInterpolated =
infIndices_[indexNo].second->interpolated();
493 QL_DEPRECATED_ENABLE_WARNING
495 infIndices_[indexNo].second->fixing(
infIndices_[indexNo].second->zeroInflationTermStructure()->baseDate());
498 if (
cam_->modelType(CrossAssetModel::AssetType::INF, camIndex) == CrossAssetModel::ModelType::DK) {
501 QL_REQUIRE(t < T ||
close_enough(t, T),
"infdkI: t (" << t <<
") <= T (" << T <<
") required");
502 auto dk = infdkv.
infdkI(camIndex, t, T, state.first, state.second, isInterpolated);
504 }
else if (
cam_->modelType(CrossAssetModel::AssetType::INF, camIndex) == CrossAssetModel::ModelType::JY) {
505 result =
exp(state.second);
510 for (Size p = 0; p <
size(); ++p) {
511 growthFactor.
data()[p] =
514 result *= growthFactor;
517 QL_FAIL(
"GaussianCam::getInfIndexValue(): unknown model type for inflation index "
524 const Date& start,
const Date& end,
const Real spread,
const Real gearing,
525 const Integer lookback,
const Natural rateCutoff,
const Natural fixingDays,
526 const bool includeSpread,
const Real cap,
const Real floor,
527 const bool nakedOption,
const bool localCapFloor)
const {
530 [&indexInput](
const std::pair<
IndexInfo, QuantLib::ext::shared_ptr<InterestRateIndex>>& p) {
531 return p.first.name() == indexInput;
534 "GaussianCam::fwdComp() ir index " << indexInput <<
" not found, this is unexpected");
537 auto on = QuantLib::ext::dynamic_pointer_cast<OvernightIndex>(ir->second);
538 QL_REQUIRE(on,
"GaussianCam::fwdCompAvg(): expected on index for " << indexInput);
540 auto coupon = QuantLib::ext::make_shared<QuantExt::OvernightIndexedCoupon>(
541 end, 1.0, start, end, on, gearing, spread, Date(), Date(), DayCounter(),
false, includeSpread, lookback * Days,
542 rateCutoff, fixingDays);
545 const auto& modelState =
irStates_.at(effobsdate)[irIndexPos];
548 return lgmv.
averagedOnRate(on, coupon->fixingDates(), coupon->valueDates(), coupon->dt(), rateCutoff,
549 includeSpread, spread, gearing, lookback * Days, cap, floor, localCapFloor,
550 nakedOption, modelTime, modelState);
552 return lgmv.
compoundedOnRate(on, coupon->fixingDates(), coupon->valueDates(), coupon->dt(), rateCutoff,
553 includeSpread, spread, gearing, lookback * Days, cap, floor, localCapFloor,
554 nakedOption, modelTime, modelState);
559 return getDiscount(idx, s, t, Handle<YieldTermStructure>());
563 const Handle<YieldTermStructure>& targetCurve)
const {
577 const boost::optional<long>& memSlot,
const RandomVariable& addRegressor1,
594 std::vector<const RandomVariable*> state;
603 for (
auto const& r :
irStates_.at(obsdate))
609 for (
auto const& r :
infStates_.at(obsdate)) {
610 state.push_back(&r.first);
611 state.push_back(&r.second);
615 Size nModelStates = state.size();
619 state.push_back(&addRegressor1);
621 state.push_back(&addRegressor2);
623 Size nAddReg = state.size() - nModelStates;
634 Matrix coordinateTransform;
638 bool haveStoredModel =
false;
642 coeff = std::get<0>(it->second);
643 coordinateTransform = std::get<2>(it->second);
644 QL_REQUIRE(std::get<1>(it->second) == state.size(),
645 "GaussianCam::npv(): stored regression coefficients at mem slot "
646 << *memSlot <<
" are for state size " << std::get<1>(it->second) <<
", actual state size is "
647 << state.size() <<
" (before possible coordinate transform).");
648 haveStoredModel =
true;
654 std::vector<RandomVariable> transformedState;
656 if(!haveStoredModel) {
662 transformedState = applyCoordinateTransform(state, coordinateTransform);
663 state = vec2vecptr(transformedState);
671 filter, RandomVariableRegressionMethod::QR);
673 <<
" (got model state size " << nModelStates <<
" and " << nAddReg
674 <<
" additional regressors, coordinate transform " << coordinateTransform.columns()
675 <<
" -> " << coordinateTransform.rows() <<
")");
687 if(!coordinateTransform.empty()) {
688 transformedState = applyCoordinateTransform(state, coordinateTransform);
689 state = vec2vecptr(transformedState);
712 const std::vector<std::vector<QuantExt::RandomVariable>>* paths,
713 const std::vector<size_t>* pathIndexes,
const std::vector<size_t>* timeIndexes) {
715 if (pathTimes ==
nullptr) {
724 QL_REQUIRE(!pathTimes->empty(),
"GaussianCam::injectPaths(): injected path times empty");
726 QL_REQUIRE(pathTimes->size() == paths->size(),
"GaussianCam::injectPaths(): path times ("
727 << pathTimes->size() <<
") must match path size ("
728 << paths->size() <<
")");
730 QL_REQUIRE(pathIndexes->size() == timeIndexes->size(),
731 "GaussianCam::injectPaths(): path indexes size (" << pathIndexes->size() <<
") must match time indexes size ("
732 << timeIndexes->size() <<
")");
735 "GaussianCam::injectPaths(): number of projected state process indices ("
738 Size maxProjectedStateProcessIndex =
741 for (
auto const& v : *paths) {
742 QL_REQUIRE(v.size() > maxProjectedStateProcessIndex,
"GaussianCam::injectPaths(): dimension of variates ("
744 <<
") must cover max projected state process index ("
745 << maxProjectedStateProcessIndex <<
")");
std::pair< RandomVariable, RandomVariable > infdkI(const Size i, const Time t, const Time T, const RandomVariable &z, const RandomVariable &y, bool indexIsInterpolated) const
RandomVariable discountBond(const Time t, const Time T, const RandomVariable &x, const Handle< YieldTermStructure > &discountCurve=Handle< YieldTermStructure >()) const
RandomVariable fixing(const boost::shared_ptr< InterestRateIndex > &index, const Date &fixingDate, const Time t, const RandomVariable &x) const
RandomVariable averagedOnRate(const boost::shared_ptr< OvernightIndex > &index, const std::vector< Date > &fixingDates, const std::vector< Date > &valueDates, const std::vector< Real > &dt, const Natural rateCutoff, const bool includeSpread, const Real spread, const Real gearing, const Period lookback, Real cap, Real floor, const bool localCapFloor, const bool nakedOption, const Time t, const RandomVariable &x) const
RandomVariable numeraire(const Time t, const RandomVariable &x, const Handle< YieldTermStructure > &discountCurve=Handle< YieldTermStructure >()) const
RandomVariable compoundedOnRate(const boost::shared_ptr< OvernightIndex > &index, const std::vector< Date > &fixingDates, const std::vector< Date > &valueDates, const std::vector< Real > &dt, const Natural rateCutoff, const bool includeSpread, const Real spread, const Real gearing, const Period lookback, Real cap, Real floor, const bool localCapFloor, const bool nakedOption, const Time t, const RandomVariable &x) const
Interpolation interpolate(const I1 &xBegin, const I1 &xEnd, const I2 &yBegin) const
GaussianCam(const Handle< CrossAssetModel > &cam, const Size paths, const std::vector< std::string > ¤cies, const std::vector< Handle< YieldTermStructure > > &curves, const std::vector< Handle< Quote > > &fxSpots, const std::vector< std::pair< std::string, QuantLib::ext::shared_ptr< InterestRateIndex > > > &irIndices, const std::vector< std::pair< std::string, QuantLib::ext::shared_ptr< ZeroInflationIndex > > > &infIndices, const std::vector< std::string > &indices, const std::vector< std::string > &indexCurrencies, const std::set< Date > &simulationDates, const McParams &mcParams, const Size timeStepsPerYear=1, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), const std::vector< Size > &projectedStateProcessIndices={}, const std::vector< std::string > &conditionalExpectationModelStates={})
RandomVariable getInfIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
void performCalculations() const override
void releaseMemory() override
std::map< Date, std::vector< std::pair< RandomVariable, RandomVariable > > > infStates_
const std::vector< size_t > * injectedPathRelevantPathIndexes_
Size size() const override
std::vector< Size > infIndexPositionInCam_
RandomVariable getIrIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
RandomVariable npv(const RandomVariable &amount, const Date &obsdate, const Filter &filter, const boost::optional< long > &memSlot, const RandomVariable &addRegressor1, const RandomVariable &addRegressor2) const override
Real getFxSpot(const Size idx) const override
std::map< std::tuple< Size, Date, Date >, RandomVariable > irIndexValueCache_
std::vector< Size > infIndexPositionInProcess_
std::vector< Size > indexPositionInProcess_
void populatePathValues(const Size nSamples, std::map< Date, std::vector< RandomVariable > > &paths, std::map< Date, std::vector< RandomVariable > > &irStates, std::map< Date, std::vector< std::pair< RandomVariable, RandomVariable > > > &infStates, const std::vector< Real > ×, const bool isTraining) const
std::vector< Size > eqIndexInCam_
const std::vector< std::vector< QuantExt::RandomVariable > > * injectedPaths_
const std::vector< QuantLib::Real > * injectedPathTimes_
const Date & referenceDate() const override
std::map< long, std::tuple< Array, Size, Matrix > > storedRegressionModel_
std::map< Date, std::vector< RandomVariable > > underlyingPathsTraining_
std::map< Date, std::vector< std::pair< RandomVariable, RandomVariable > > > infStatesTraining_
bool conditionalExpectationUseAsset_
std::vector< Size > currencyPositionInProcess_
std::vector< Size > comIndexInCam_
RandomVariable getNumeraire(const Date &s) const override
std::vector< Size > irIndexPositionInCam_
bool conditionalExpectationUseIr_
std::vector< Size > currencyPositionInCam_
const Handle< CrossAssetModel > cam_
std::map< Date, std::vector< RandomVariable > > underlyingPaths_
std::set< Date > effectiveSimulationDates_
std::map< Date, std::vector< RandomVariable > > irStates_
bool conditionalExpectationUseInf_
const std::vector< Handle< Quote > > fxSpots_
std::map< Date, std::vector< RandomVariable > > irStatesTraining_
RandomVariable getDiscount(const Size idx, const Date &s, const Date &t) const override
const std::vector< Size > projectedStateProcessIndices_
RandomVariable getIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
Size trainingSamples() const override
void resetNPVMem() override
const Size timeStepsPerYear_
void toggleTrainingPaths() const override
const std::vector< size_t > * injectedPathRelevantTimeIndexes_
void injectPaths(const std::vector< QuantLib::Real > *pathTimes, const std::vector< std::vector< QuantExt::RandomVariable > > *paths, const std::vector< size_t > *pathIndexes, const std::vector< size_t > *timeIndexes) override
RandomVariable fwdCompAvg(const bool isAvg, const std::string &index, const Date &obsdate, const Date &start, const Date &end, const Real spread, const Real gearing, const Integer lookback, const Natural rateCutoff, const Natural fixingDays, const bool includeSpread, const Real cap, const Real floor, const bool nakedOption, const bool localCapFloor) const override
const std::vector< Handle< YieldTermStructure > > curves_
std::vector< Size > positionInTimeGrid_
Real timeFromReference(const Date &d) const
virtual Size size() const
const std::vector< std::string > currencies_
std::vector< std::pair< IndexInfo, QuantLib::ext::shared_ptr< ZeroInflationIndex > > > infIndices_
std::vector< IndexInfo > indices_
std::vector< std::pair< IndexInfo, QuantLib::ext::shared_ptr< InterestRateIndex > > > irIndices_
const std::vector< std::string > indexCurrencies_
const std::set< Date > simulationDates_
SafeStack< Filter > filter
gaussian cross asset model for ir, fx, eq, com
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Map text representations to QuantLib/QuantExt types.
Classes and functions for log message handling.
#define DLOG(text)
Logging Macro (Level = Debug)
QuantLib::Date fixingDate(const QuantLib::Date &d, const QuantLib::Period obsLag, const QuantLib::Frequency freq, bool interpolated)
RandomVariable exp(RandomVariable x)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
boost::shared_ptr< MultiPathGeneratorBase > makeMultiPathGenerator(const SequenceType s, const boost::shared_ptr< StochasticProcess > &process, const TimeGrid &timeGrid, const BigNatural seed, const SobolBrownianGenerator::Ordering ordering=SobolBrownianGenerator::Steps, const SobolRsg::DirectionIntegers directionIntegers=SobolRsg::JoeKuoD7)
Real inflationGrowth(const boost::shared_ptr< CrossAssetModel > &model, Size index, Time S, Time T, Real irState, Real rrState, bool indexIsInterpolated)
Array regressionCoefficients(RandomVariable r, const std::vector< const RandomVariable * > ®ressor, const std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > &basisFn, const Filter &filter, const RandomVariableRegressionMethod regressionMethod, const std::string &debugLabel)
boost::shared_ptr< MultiPathVariateGeneratorBase > makeMultiPathVariateGenerator(const SequenceType s, const Size dimension, const Size timeSteps, const BigNatural seed, const SobolBrownianGenerator::Ordering ordering, const SobolRsg::DirectionIntegers directionIntegers)
RandomVariable expectation(const RandomVariable &r)
RandomVariable conditionalExpectation(const std::vector< const RandomVariable * > ®ressor, const std::vector< std::function< RandomVariable(const std::vector< const RandomVariable * > &)> > &basisFn, const Array &coefficients)
std::string to_string(const LocationInfo &l)
Size getInflationSimulationLag(const QuantLib::ext::shared_ptr< ZeroInflationIndex > &index)
Serializable Credit Default Swap.
Map text representations to QuantLib/QuantExt types.
bool deterministic() const
void set(const Size i, const Real v)
QuantExt::SequenceType sequenceType
QuantLib::SobolBrownianGenerator::Ordering sobolOrdering
QuantExt::SequenceType trainingSequenceType
QuantLib::SobolRsg::DirectionIntegers sobolDirectionIntegers
QuantLib::Real regressionVarianceCutoff
QuantLib::LsmBasisSystem::PolynomialType polynomType
std::vector< Size > steps
string conversion utilities