hasquant-0.8.0.0: cbits/qlPricingEngineAux.cpp
#include "qlCheckedFdEngine.h"
// this file intentionally does not contain any references to wrappers, only vanilla QuantLib is used here
#include <ql/pricingengines/all.hpp>
#include <ql/pricingengines/vanilla/binomialengine.hpp>
#include <ql/pricingengines/barrier/binomialbarrierengine.hpp>
#include <ql/experimental/barrieroption/binomialdoublebarrierengine.hpp>
#include <ql/experimental/barrieroption/mcdoublebarrierengine.hpp>
#include <ql/experimental/callablebonds/blackcallablebondengine.hpp>
#include <ql/experimental/callablebonds/treecallablebondengine.hpp>
#include <ql/pricingengines/bond/binomialconvertibleengine.hpp>
#include <ql/experimental/lattices/extendedbinomialtree.hpp>
#include <ql/experimental/math/zigguratrng.hpp>
#include <ql/methods/finitedifferences/expliciteuler.hpp>
#include <ql/methods/finitedifferences/impliciteuler.hpp>
#include <ql/pricingengines/vanilla/fdblackscholesvanillaengine.hpp>
#include <ql/instruments/dividendschedule.hpp>
#include <ql/methods/montecarlo/pathgenerator.hpp>
#include <ql/methods/montecarlo/multipathgenerator.hpp>
#include <ql/experimental/exoticoptions/mchimalayaengine.hpp>
#include <ql/experimental/exoticoptions/mcpagodaengine.hpp>
#include <ql/experimental/exoticoptions/mceverestengine.hpp>
#include <ql/pricingengines/forward/mcforwardeuropeanbsengine.hpp>
#include <ql/pricingengines/forward/mcforwardeuropeanhestonengine.hpp>
#include <ql/pricingengines/basket/mceuropeanbasketengine.hpp>
#include <ql/pricingengines/basket/mcamericanbasketengine.hpp>
#include <ql/pricingengines/asian/mc_discr_arith_av_price_heston.hpp>
#include <ql/math/statistics/incrementalstatistics.hpp>
namespace hasquant {
#include "qlEnumObjects.h"
}
using QuantLib::ext::shared_ptr;
#include "qlStdCompat.h"
#include "qlPricingEngineAux.h"
using namespace QuantLib;
// ---------------------------------------------------------------------------------------------
// Trait dispatchers.
//
// Each engine is selected by one or two runtime traits. Dispatchers call a generic lambda with
// an empty `Tag<T>` per axis, so each constructor is written once and recovers types through
// `typename decltype(r)::type`.
//
// Use an explicit result type: a decltype probe can prevent clang from emitting the selected
// engine's vtable.
template <class T> struct Tag { using type = T; };
template <class Ret, class F>
Ret dispatchTree(int tree, F&& make) {
switch (tree) {
case hasquant::JarrowRudd: return make(Tag<JarrowRudd>());
case hasquant::CoxRossRubinstein: return make(Tag<CoxRossRubinstein>());
case hasquant::AdditiveEQPBinomialTree: return make(Tag<AdditiveEQPBinomialTree>());
case hasquant::Trigeorgis: return make(Tag<Trigeorgis>());
case hasquant::Tian: return make(Tag<Tian>());
case hasquant::LeisenReimer: return make(Tag<LeisenReimer>());
case hasquant::Joshi4: return make(Tag<Joshi4>());
case hasquant::ExtendedJarrowRudd: return make(Tag<ExtendedJarrowRudd>());
case hasquant::ExtendedCoxRossRubinstein: return make(Tag<ExtendedCoxRossRubinstein>());
case hasquant::ExtendedAdditiveEQPBinomialTree: return make(Tag<ExtendedAdditiveEQPBinomialTree>());
case hasquant::ExtendedTrigeorgis: return make(Tag<ExtendedTrigeorgis>());
case hasquant::ExtendedTian: return make(Tag<ExtendedTian>());
case hasquant::ExtendedLeisenReimer: return make(Tag<ExtendedLeisenReimer>());
case hasquant::ExtendedJoshi4: return make(Tag<ExtendedJoshi4>());
}
QL_FAIL("Unknown Binomial Tree "<< tree);
}
template <class Ret, class F>
Ret dispatchRng(int rngtrait, F&& make) {
switch (rngtrait) {
case hasquant::PseudoRandom: return make(Tag<PseudoRandom>());
case hasquant::PoissonPseudoRandom: return make(Tag<PoissonPseudoRandom>());
case hasquant::LowDiscrepancy: return make(Tag<LowDiscrepancy>());
case hasquant::Ziggurat: return make(Tag<Ziggurat>());
}
QL_FAIL("Unknown RNG "<< rngtrait);
}
template <class Ret, class F>
Ret dispatchStat(int stattrait, F&& make) {
switch (stattrait) {
case hasquant::Statistics: return make(Tag<QuantLib::Statistics>());
case hasquant::GaussianStatistics: return make(Tag<QuantLib::GaussianStatistics>());
case hasquant::GeneralStatistics: return make(Tag<QuantLib::GeneralStatistics>());
case hasquant::IncrementalStatistics: return make(Tag<QuantLib::IncrementalStatistics>());
}
QL_FAIL("Unknown Statistics "<< stattrait);
}
// The shared RNG x Statistics dispatch used by every templated Monte Carlo engine in this file.
template <class Ret, class F>
Ret dispatchRngStat(int rngtrait, int stattrait, F&& make) {
return dispatchRng<Ret>(rngtrait, [&](auto r) {
return dispatchStat<Ret>(stattrait, [&](auto st) { return make(r, st); });
});
}
// ---------------------------------------------------------------------------------------------
PricingEngine* qlBinomialVanillaEngineAux(int tree, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps) {
return dispatchTree<PricingEngine*>(tree, [&](auto t) {
return new BinomialVanillaEngine<typename decltype(t)::type>(process, timeSteps);
});
}
PricingEngine* qlBinomialConvertibleEngineAux(int tree, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, const Handle<Quote>& cs, DividendSchedule d) {
return dispatchTree<PricingEngine*>(tree, [&](auto t) {
return new BinomialConvertibleEngine<typename decltype(t)::type>(process, timeSteps, cs, d);
});
}
PricingEngine* qlBinomialBarrierEngineAux(int tree, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned maxTimeSteps) {
return dispatchTree<PricingEngine*>(tree, [&](auto t) {
return new BinomialBarrierEngine<typename decltype(t)::type, DiscretizedBarrierOption>(process, timeSteps, maxTimeSteps);
});
}
PricingEngine* qlBinomialDoubleBarrierEngineAux(int tree, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps) {
return dispatchTree<PricingEngine*>(tree, [&](auto t) {
return new BinomialDoubleBarrierEngine<typename decltype(t)::type>(process, timeSteps);
});
}
PricingEngine* qlMCDoubleBarrierEngineAux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDoubleBarrierEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCVarianceSwapEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCVarianceSwapEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCHestonHullWhiteEngine1Aux(int rngtrait, int stattrait, const shared_ptr<HybridHestonHullWhiteProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int antitheticVariate, int controlVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCHestonHullWhiteEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, antitheticVariate, controlVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCAmericanEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int antitheticVariate, int controlVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, unsigned polynomOrder, LsmBasisSystem::PolynomialType polynomType, unsigned nCalibrationSamples, optional<bool> antitheticVariateCalibration, unsigned seedCalibration) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCAmericanEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, antitheticVariate, controlVariate, requiredSamples, requiredTolerance, maxSamples, seed, polynomOrder, polynomType, nCalibrationSamples, antitheticVariateCalibration, seedCalibration);
});
}
PricingEngine* qlMCBarrierEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, int isBiased, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCBarrierEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, isBiased, seed);
});
}
PricingEngine* qlMCDigitalEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> x0, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDigitalEngine<typename decltype(r)::type, typename decltype(st)::type>(x0, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCForwardEuropeanBSEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCForwardEuropeanBSEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCForwardEuropeanHestonEngine1Aux(int rngtrait, int stattrait, const shared_ptr<HestonProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, int controlVariate) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCForwardEuropeanHestonEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed, controlVariate);
});
}
PricingEngine* qlMCDiscreteArithmeticAPEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, int controlVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDiscreteArithmeticAPEngine<typename decltype(r)::type, typename decltype(st)::type>(process, brownianBridge, antitheticVariate, controlVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCDiscreteArithmeticASEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDiscreteArithmeticASEngine<typename decltype(r)::type, typename decltype(st)::type>(process, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCDiscreteGeometricAPEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDiscreteGeometricAPEngine<typename decltype(r)::type, typename decltype(st)::type>(process, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCDiscreteArithmeticAPHestonEngine1Aux(int rngtrait, int stattrait, const shared_ptr<HestonProcess> process, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, unsigned timeSteps, unsigned timeStepsPerYear, int controlVariate) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDiscreteArithmeticAPHestonEngine<typename decltype(r)::type, typename decltype(st)::type>(process, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed, timeSteps, timeStepsPerYear, controlVariate);
});
}
PricingEngine* qlMCDiscreteGeometricAPHestonEngine1Aux(int rngtrait, int stattrait, const shared_ptr<HestonProcess> process, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, unsigned timeSteps, unsigned timeStepsPerYear) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCDiscreteGeometricAPHestonEngine<typename decltype(r)::type, typename decltype(st)::type>(process, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed, timeSteps, timeStepsPerYear);
});
}
PricingEngine* qlMCEuropeanEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCEuropeanEngine<typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCEuropeanGJRGARCHEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GJRGARCHProcess> x0, unsigned timeSteps, unsigned timeStepsPerYear, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCEuropeanGJRGARCHEngine<typename decltype(r)::type, typename decltype(st)::type>(x0, timeSteps, timeStepsPerYear, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCEuropeanHestonEngine1Aux(int rngtrait, int stattrait, const shared_ptr<HestonProcess> x0, unsigned timeSteps, unsigned timeStepsPerYear, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCEuropeanHestonEngine<typename decltype(r)::type, typename decltype(st)::type>(x0, timeSteps, timeStepsPerYear, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCHullWhiteCapFloorEngine1Aux(int rngtrait, int stattrait, shared_ptr<HullWhite> model, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCHullWhiteCapFloorEngine<typename decltype(r)::type, typename decltype(st)::type>(model, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCHimalayaEngine1Aux(int rngtrait, int stattrait, const shared_ptr<StochasticProcessArray> processes, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCHimalayaEngine<typename decltype(r)::type, typename decltype(st)::type>(processes, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCPagodaEngine1Aux(int rngtrait, int stattrait, const shared_ptr<StochasticProcessArray> processes, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCPagodaEngine<typename decltype(r)::type, typename decltype(st)::type>(processes, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCEverestEngine1Aux(int rngtrait, int stattrait, const shared_ptr<StochasticProcessArray> processes, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCEverestEngine<typename decltype(r)::type, typename decltype(st)::type>(processes, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCEuropeanBasketEngine1Aux(int rngtrait, int stattrait, const shared_ptr<StochasticProcessArray> processes, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCEuropeanBasketEngine<typename decltype(r)::type, typename decltype(st)::type>(processes, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCPerformanceEngine1Aux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCPerformanceEngine<typename decltype(r)::type, typename decltype(st)::type>(process, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
// MCLookbackEngine<I,RNG,S> is templated over the lookback option type I as well as RNG/S -- I is
// not a runtime "trait" (it fixes the whole option/engine-base pair, not a policy struct chosen
// among siblings), so each of the four already-bound lookback option types gets its own dispatcher
// over the RNG x Statistics axes only, mirroring the four separate analytic lookback engine shims.
PricingEngine* qlMCLookbackFixedEngineAux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCLookbackEngine<ContinuousFixedLookbackOption, typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCLookbackFloatingEngineAux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCLookbackEngine<ContinuousFloatingLookbackOption, typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCLookbackPartialFixedEngineAux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCLookbackEngine<ContinuousPartialFixedLookbackOption, typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
PricingEngine* qlMCLookbackPartialFloatingEngineAux(int rngtrait, int stattrait, const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed) {
return dispatchRngStat<PricingEngine*>(rngtrait, stattrait, [&](auto r, auto st) {
return new MCLookbackEngine<ContinuousPartialFloatingLookbackOption, typename decltype(r)::type, typename decltype(st)::type>(process, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed);
});
}
// Upstream MCAmericanBasketEngine has only an RNG template parameter; it has no statistics axis.
PricingEngine* qlMCAmericanBasketEngine1Aux(int rngtrait, const shared_ptr<StochasticProcessArray> processes, unsigned timeSteps, unsigned timeStepsPerYear, int brownianBridge, int antitheticVariate, unsigned requiredSamples, double requiredTolerance, unsigned maxSamples, unsigned seed, unsigned nCalibrationSamples, unsigned polynomialOrder, LsmBasisSystem::PolynomialType polynomialType) {
return dispatchRng<PricingEngine*>(rngtrait, [&](auto r) {
return new MCAmericanBasketEngine<typename decltype(r)::type>(processes, timeSteps, timeStepsPerYear, brownianBridge, antitheticVariate, requiredSamples, requiredTolerance, maxSamples, seed, nCalibrationSamples, polynomialOrder, polynomialType);
});
}
PricingEngine* qlFdBlackScholesVanillaEngineAux(const shared_ptr<GeneralizedBlackScholesProcess> process, unsigned tGrid, unsigned xGrid, unsigned dampingSteps, const FdmSchemeDesc &fdScheme, bool localVol, double illegalLocalVolOverwrite, int cashDividendModel) {return new hasquant::CheckedFdEngine<FdBlackScholesVanillaEngine>(process, tGrid, xGrid, dampingSteps, fdScheme, localVol, illegalLocalVolOverwrite, (FdBlackScholesVanillaEngine::CashDividendModel)cashDividendModel);}
class PolymorphicPathGenerator {
private:
template <class Rsg> struct SequenceSource {
using sample_type = typename Rsg::sample_type;
shared_ptr<Rsg> source;
unsigned dimension() const {return source->dimension();}
const Sample<std::vector<Real>>& nextSequence() const {return source->nextSequence();}
const Sample<std::vector<Real>>& lastSequence() const {return source->lastSequence();}
};
public:
PolymorphicPathGenerator(int rngtrait, const shared_ptr<StochasticProcess> p, const TimeGrid &t, unsigned seed, unsigned dim, bool brownianBridge) {
init(rngtrait, p, t, seed, dim, brownianBridge, SobolRsg::Jaeckel);
}
PolymorphicPathGenerator(SobolRsg::DirectionIntegers dir, const shared_ptr<StochasticProcess> p, const TimeGrid &t, unsigned seed, unsigned dim, bool brownianBridge) {
init(hasquant::LowDiscrepancy, p, t, seed, dim, brownianBridge, dir);
}
const Sample<MultiPath>& next() const {const auto& s = _next(); drawn_ = true; return s;}
const Sample<MultiPath>& antithetic() const {return _antithetic();}
const Sample<std::vector<Real>>& sequence() const {
QL_REQUIRE(drawn_, "no path has been drawn");
return _sequence();
}
private:
template <class Rsg> void install(const shared_ptr<StochasticProcess>& p, const TimeGrid& t, Rsg rsg, bool brownianBridge) {
auto source = shared_ptr<Rsg>(new Rsg(std::move(rsg)));
using Generator = MultiPathGenerator<SequenceSource<Rsg>>;
auto gen = shared_ptr<Generator>(new Generator(p, t, SequenceSource<Rsg>{source}, brownianBridge));
_next = [gen]() -> const Sample<MultiPath>& {return gen->next();};
_antithetic = [gen]() -> const Sample<MultiPath>& {return gen->antithetic();};
_sequence = [source]() -> const Sample<std::vector<Real>>& {return source->lastSequence();};
}
void init(int rngtrait, const shared_ptr<StochasticProcess> p, const TimeGrid &t, unsigned seed, unsigned dim, bool brownianBridge, SobolRsg::DirectionIntegers dir) {
switch (rngtrait) {
case hasquant::PseudoRandom:
install(p, t, PseudoRandom::rsg_type(PseudoRandom::ursg_type(dim, PseudoRandom::urng_type(seed))), brownianBridge);
break;
case hasquant::PoissonPseudoRandom:
install(p, t, PoissonPseudoRandom::rsg_type(PoissonPseudoRandom::ursg_type(dim, PoissonPseudoRandom::urng_type(seed))), brownianBridge);
break;
case hasquant::LowDiscrepancy:
install(p, t, LowDiscrepancy::rsg_type(SobolRsg(dim, seed, dir)), brownianBridge);
break;
case hasquant::Ziggurat:
install(p, t, Ziggurat::rsg_type(dim, ZigguratRng(seed)), brownianBridge);
break;
default:
QL_FAIL("Unknown RNG "<< rngtrait);
}
}
std::function<const Sample<MultiPath>& ()> _next;
std::function<const Sample<MultiPath>& ()> _antithetic;
std::function<const Sample<std::vector<Real>>& ()> _sequence;
mutable bool drawn_ = false;
};
PolymorphicPathGenerator* qlPathGeneratorAux(int rngtrait, const shared_ptr<StochasticProcess> p, const TimeGrid &grid, unsigned seed, unsigned dim, bool brownianBridge) {
return new PolymorphicPathGenerator(rngtrait, p, grid, seed, dim, brownianBridge);
}
PolymorphicPathGenerator* qlSobolPathGeneratorAux(SobolRsg::DirectionIntegers dir, const shared_ptr<StochasticProcess> p, const TimeGrid &grid, unsigned seed, unsigned dim, bool brownianBridge) {
return new PolymorphicPathGenerator(dir, p, grid, seed, dim, brownianBridge);
}
// Expose the gaussian sequence generator so Haskell can evolve paths without a hot-loop callback.
// Match PolymorphicPathGenerator's RNG and Sobol dispatch for draw-for-draw comparisons.
class PolymorphicGaussianRsg {
private:
using PseudoRandomRsg = PseudoRandom::rsg_type;
using SobolRsgType = LowDiscrepancy::rsg_type;
using PoissonRsg = PoissonPseudoRandom::rsg_type;
using ZigguratRsg = Ziggurat::rsg_type;
public:
PolymorphicGaussianRsg(int rngtrait, unsigned dim, unsigned seed) {
init(rngtrait, dim, seed, SobolRsg::Jaeckel);
}
PolymorphicGaussianRsg(SobolRsg::DirectionIntegers dir, unsigned dim, unsigned seed) {
init(hasquant::LowDiscrepancy, dim, seed, dir);
}
const Sample<std::vector<Real> >& nextSequence() const {return _next();}
const Sample<std::vector<Real> >& lastSequence() const {return _last();}
unsigned dimension() const {return _dimension();}
private:
void init(int rngtrait, unsigned dim, unsigned seed, SobolRsg::DirectionIntegers dir) {
switch (rngtrait) {
case hasquant::PseudoRandom:
_pseudoRandom.reset(new PseudoRandomRsg(PseudoRandom::ursg_type(dim, PseudoRandom::urng_type(seed))));
bind(_pseudoRandom.get());
break;
case hasquant::PoissonPseudoRandom:
_poisson.reset(new PoissonRsg(PoissonPseudoRandom::ursg_type(dim, PoissonPseudoRandom::urng_type(seed))));
bind(_poisson.get());
break;
case hasquant::LowDiscrepancy:
_sobol.reset(new SobolRsgType(SobolRsg(dim, seed, dir)));
bind(_sobol.get());
break;
case hasquant::Ziggurat:
_ziggurat.reset(new ZigguratRsg(dim, ZigguratRng(seed)));
bind(_ziggurat.get());
break;
default:
QL_FAIL("Unknown RNG "<< rngtrait);
}
}
template <class Rsg> void bind(Rsg* r) {
_next = [r]() -> const Sample<std::vector<Real> >& {return r->nextSequence();};
_last = [r]() -> const Sample<std::vector<Real> >& {return r->lastSequence();};
_dimension = [r]() {return (unsigned)r->dimension();};
}
std::unique_ptr<PseudoRandomRsg> _pseudoRandom;
std::unique_ptr<SobolRsgType> _sobol;
std::unique_ptr<PoissonRsg> _poisson;
std::unique_ptr<ZigguratRsg> _ziggurat;
std::function<const Sample<std::vector<Real> >& ()> _next;
std::function<const Sample<std::vector<Real> >& ()> _last;
std::function<unsigned ()> _dimension;
};
PolymorphicGaussianRsg* qlGaussianRsgAux(int rngtrait, unsigned dimension, unsigned seed) {
return new PolymorphicGaussianRsg(rngtrait, dimension, seed);
}
PolymorphicGaussianRsg* qlSobolGaussianRsgAux(SobolRsg::DirectionIntegers dir, unsigned dimension, unsigned seed) {
return new PolymorphicGaussianRsg(dir, dimension, seed);
}
void qlFreePolymorphicGaussianRsgAux(PolymorphicGaussianRsg* g) {delete g;}
const Sample<std::vector<Real> >& qlGaussianRsgNextSequenceAux(PolymorphicGaussianRsg* g) {return g->nextSequence();}
const Sample<std::vector<Real> >& qlGaussianRsgLastSequenceAux(PolymorphicGaussianRsg* g) {return g->lastSequence();}
unsigned qlGaussianRsgDimensionAux(PolymorphicGaussianRsg* g) {return g->dimension();}
void qlFreePolymorphicPathGeneratorAux(PolymorphicPathGenerator *p) {delete p;}
const Sample<MultiPath>& qlPathGeneratorNextAux(PolymorphicPathGenerator *p) {return p->next();}
const Sample<MultiPath>& qlPathGeneratorAntitheticAux(PolymorphicPathGenerator *p) {return p->antithetic();}
/* vim: set ft=cpp ff=unix ts=8 sts=2 sw=2 et: */
const Sample<std::vector<Real>>& qlPathGeneratorSequenceAux(PolymorphicPathGenerator* g) {return g->sequence();}