24#include <ql/math/comparison.hpp>
25#include <ql/math/matrixutilities/choleskydecomposition.hpp>
26#include <ql/math/matrixutilities/pseudosqrt.hpp>
27#include <ql/math/matrixutilities/symmetricschurdecomposition.hpp>
35 const std::string& index,
const std::string& indexCurrency,
36 const Handle<BlackScholesModelWrapper>& model,
const McParams& mcParams,
38 const std::string& calibration,
const std::vector<Real>& calibrationStrikes)
39 :
BlackScholes(paths, {currency}, {curve}, {}, {}, {}, {index}, {indexCurrency}, model, {}, mcParams,
40 simulationDates, iborFallbackConfig, calibration, {{index, calibrationStrikes}}) {}
43 const Size paths,
const std::vector<std::string>& currencies,
const std::vector<Handle<YieldTermStructure>>& curves,
44 const std::vector<Handle<Quote>>& fxSpots,
45 const std::vector<std::pair<std::string, QuantLib::ext::shared_ptr<InterestRateIndex>>>& irIndices,
46 const std::vector<std::pair<std::string, QuantLib::ext::shared_ptr<ZeroInflationIndex>>>& infIndices,
47 const std::vector<std::string>& indices,
const std::vector<std::string>& indexCurrencies,
48 const Handle<BlackScholesModelWrapper>& model,
49 const std::map<std::pair<std::string, std::string>, Handle<QuantExt::CorrelationTermStructure>>& correlations,
51 const std::string& calibration,
const std::map<std::string, std::vector<Real>>& calibrationStrikes)
52 :
BlackScholesBase(paths, currencies, curves, fxSpots, irIndices, infIndices, indices, indexCurrencies, model,
53 correlations, mcParams, simulationDates, iborFallbackConfig),
80 std::vector<Real> calibrationStrikes;
82 calibrationStrikes.resize(
indices_.size(), Null<Real>());
84 for (Size i = 0; i <
indices_.size(); ++i) {
87 calibrationStrikes.push_back(f->second[0]);
88 TLOG(
"calibration strike for index '" <<
indices_[i] <<
"' is " << f->second[0]);
90 calibrationStrikes.push_back(Null<Real>());
91 TLOG(
"calibration strike for index '" <<
indices_[i] <<
"' is ATMF");
95 QL_FAIL(
"BlackScholes: calibration '" <<
calibration_ <<
"' not supported, expected ATM, Deal");
100 for (Size l = 0; l <
indices_.size(); ++l) {
114 std::vector<Size> forCcyDaIndex(
indices_.size(), Null<Size>());
115 for (Size j = 0; j <
indices_.size(); ++j) {
118 for (Size jj = 0; jj <
indices_.size(); ++jj) {
121 forCcyDaIndex[j] = jj;
128 std::vector<Matrix> sqrtCov;
140 for (Size j = 0; j <
indices_.size(); ++j) {
141 Real tmp =
model_->processes()[j]->blackVolatility()->blackVariance(
143 calibrationStrikes[j] == Null<Real>()
146 : calibrationStrikes[j]);
147 d_variance[j] = std::max(tmp -
variance[j], 1E-20);
150 for (Size j = 0; j <
indices_.size(); ++j) {
152 for (Size k = 0; k < j; ++k) {
153 Real tmp = correlation[k][j] * std::sqrt(d_variance[j] * d_variance[k]);
163 SymmetricSchurDecomposition jd(
covariance_[i - 1]);
165 bool needsSalvaging =
false;
166 for (Size k = 0; k <
covariance_[i - 1].rows(); ++k) {
167 if (jd.eigenvalues()[k] < -1E-16)
168 needsSalvaging =
true;
171 if (needsSalvaging) {
173 for (Size k = 0; k < jd.eigenvalues().
size(); ++k) {
174 diagonal[k][k] = std::sqrt(std::max<Real>(jd.eigenvalues()[k], 0.0));
176 covariance_[i - 1] = jd.eigenvectors() * diagonal * diagonal * transpose(jd.eigenvectors());
181 sqrtCov.push_back(CholeskyDecomposition(
covariance_[i - 1],
true));
186 for (Size j = 0; j <
indices_.size(); ++j) {
187 Real tmp =
model_->processes()[j]->riskFreeRate()->discount(d) /
188 model_->processes()[j]->dividendYield()->discount(d);
189 drift[i - 1][j] = -std::log(tmp / discountRatio[j]) - 0.5 *
covariance_[i - 1][j][j];
190 discountRatio[j] = tmp;
193 if (forCcyDaIndex[j] != Null<Size>()) {
194 drift[i - 1][j] -=
covariance_[i - 1][forCcyDaIndex[j]][j];
217 for (Size i = 0; i <
indices_.size(); ++i) {
218 for (Size j = 0; j < i; ++j) {
224 for (Size i = 0; i < calibrationStrikes.size(); ++i) {
226 (calibrationStrikes[i] == Null<Real>() ?
"ATMF" : std::to_string(calibrationStrikes[i]));
229 for (Size i = 0; i <
indices_.size(); ++i) {
234 model_->processes()[i]->dividendYield(), t);
236 Real volatility =
model_->processes()[i]->blackVolatility()->blackVol(
237 t, calibrationStrikes[i] == Null<Real>() ? forward : calibrationStrikes[i]);
248 const QuantLib::ext::shared_ptr<MultiPathVariateGeneratorBase>& gen,
249 const std::vector<Array>& drift,
const std::vector<Matrix>& sqrtCov)
const {
251 std::vector<std::vector<RandomVariable*>> rvs(
indices_.size(),
256 for (Size j = 0; j <
indices_.size(); ++j) {
257 rvs[j][i] = &paths[*date][j];
263 for (Size j = 0; j <
indices_.size(); ++j) {
264 logState0[j] = std::log(
model_->processes()[j]->x0());
267 for (Size path = 0; path < nSamples; ++path) {
268 auto seq = gen->next();
269 logState = logState0;
271 for (Size j = 0; j <
indices_.size(); ++j) {
272 for (Size k = 0; k <
indices_.size(); ++k)
273 logState[j] += sqrtCov[i][j][k] * seq.value[i][k];
275 logState += drift[i];
276 for (Size j = 0; j <
indices_.size(); ++j)
277 rvs[j][i]->
data()[path] = std::exp(logState[j]);
284 comp(
const std::string& indexInput) :
indexInput_(indexInput) {}
285 template <
typename T>
bool operator()(
const std::pair<
IndexInfo, QuantLib::ext::shared_ptr<T>>& p)
const {
304 barrierHit = barrierHit || v1 >= barrier;
305 barrierHit = barrierHit || v2 >= barrier;
307 barrierHit = barrierHit || v1 <= barrier;
308 barrierHit = barrierHit || v2 <= barrier;
317 Date d = obsdate1 + 1;
318 while (d < obsdate2) {
326 barrierHit = barrierHit || res >= barrier;
328 barrierHit = barrierHit || res <= barrier;
351 v1 =
eval(index, obsdate1, Null<Date>(),
false,
true);
359 if (indexInfo.
isFx())
360 indexInfo =
IndexInfo(
"FX-GENERIC-" + indexInfo.
fx()->sourceCurrency().code() +
"-" +
361 indexInfo.
fx()->targetCurrency().code());
370 Size ind1 = Null<Size>(), ind2 = Null<Size>();
375 ind1 = std::distance(
indices_.begin(), i);
379 QL_REQUIRE(indexInfo.
isFx(),
"BlackScholes::getFutureBarrierProb(): index " << index <<
" not handled");
381 if (indexInfo.
fx()->sourceCurrency() == indexInfo.
fx()->targetCurrency()) {
385 QL_REQUIRE(indexInfo.
isFx(),
"BlackScholes::getFutureBarrierProb(): index " << index <<
" not handled");
386 if (indexInfo.
fx()->sourceCurrency() == indexInfo.
fx()->targetCurrency()) {
410 if (obsdate1 <= d1 && d2 <= obsdate2) {
411 if (ind1 != Null<Size>()) {
414 if (ind2 != Null<Size>()) {
417 if (ind1 != Null<Size>() && ind2 != Null<Size>()) {
426 if (!QuantLib::close_enough(
variance, 0.0)) {
429 log(v2 /
max(barrier, eps)));
const std::string indexInput_
black scholes model for n underlyings (fx, equity or commodity)
const std::vector< Real > calibrationStrikes_
RandomVariable getInfIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
void performCalculations() const override
Size size() const override
RandomVariable getIrIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
const Date & referenceDate() const override
std::map< Date, std::vector< RandomVariable > > underlyingPathsTraining_
std::map< Date, std::vector< RandomVariable > > underlyingPaths_
std::set< Date > effectiveSimulationDates_
const Handle< BlackScholesModelWrapper > model_
Size trainingSamples() const override
std::vector< Size > positionInTimeGrid_
Matrix getCorrelation() const
void performCalculations() const override
RandomVariable getFutureBarrierProb(const std::string &index, const Date &obsdate1, const Date &obsdate2, const RandomVariable &barrier, const bool above) const override
void populatePathValues(const Size nSamples, std::map< Date, std::vector< RandomVariable > > &paths, const QuantLib::ext::shared_ptr< MultiPathVariateGeneratorBase > &gen, const std::vector< Array > &drift, const std::vector< Matrix > &sqrtCov) const
std::vector< Matrix > covariance_
const std::map< std::string, std::vector< Real > > calibrationStrikes_
const std::string calibration_
BlackScholes(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 Handle< BlackScholesModelWrapper > &model, const std::map< std::pair< std::string, std::string >, Handle< QuantExt::CorrelationTermStructure > > &correlations, const McParams &mcParams, const std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), const std::string &calibration="ATM", const std::map< std::string, std::vector< Real > > &calibrationStrikes={})
QuantLib::ext::shared_ptr< FxIndex > fx() const
std::map< std::string, boost::any > additionalResults_
std::vector< std::pair< IndexInfo, QuantLib::ext::shared_ptr< ZeroInflationIndex > > > infIndices_
std::vector< IndexInfo > indices_
RandomVariable eval(const std::string &index, const Date &obsdate, const Date &fwddate, const bool returnMissingMissingAsNull=false, const bool ignoreTodaysFixing=false) const override
std::vector< std::pair< IndexInfo, QuantLib::ext::shared_ptr< InterestRateIndex > > > irIndices_
const std::vector< std::string > indexCurrencies_
#define TLOG(text)
Logging Macro (Level = Data)
Shared utilities for model building and calibration.
RandomVariable max(RandomVariable x, const RandomVariable &y)
RandomVariable exp(RandomVariable x)
RandomVariable variance(const RandomVariable &r)
RandomVariable log(RandomVariable x)
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 applyInverseFilter(RandomVariable x, const Filter &f)
Real atmForward(const Real s0, const Handle< YieldTermStructure > &r, const Handle< YieldTermStructure > &q, const Real t)
helper function that computes the atm forward
std::string to_string(const LocationInfo &l)
Serializable Credit Default Swap.
QuantExt::SequenceType sequenceType
QuantLib::SobolBrownianGenerator::Ordering sobolOrdering
QuantExt::SequenceType trainingSequenceType
QuantLib::SobolRsg::DirectionIntegers sobolDirectionIntegers
string conversion utilities