Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
BlackScholesCG Class Reference

#include <ored/scripting/models/blackscholescg.hpp>

+ Inheritance diagram for BlackScholesCG:
+ Collaboration diagram for BlackScholesCG:

Public Member Functions

 BlackScholesCG (const Size paths, const std::vector< std::string > &currencies, 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 std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), const std::string &calibration="ATM", const std::map< std::string, std::vector< Real > > &calibrationStrikes={})
 
 BlackScholesCG (const Size paths, const std::string &currency, const Handle< YieldTermStructure > &curve, const std::string &index, const std::string &indexCurrency, const Handle< BlackScholesModelWrapper > &model, const std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), const std::string &calibration="ATM", const std::vector< Real > &calibrationStrikes={})
 
- Public Member Functions inherited from BlackScholesCGBase
 BlackScholesCGBase (const Size paths, const std::vector< std::string > &currencies, 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 std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig)
 
 BlackScholesCGBase (const Size paths, const std::string &currency, const Handle< YieldTermStructure > &curve, const std::string &index, const std::string &indexCurrency, const Handle< BlackScholesModelWrapper > &model, const std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig)
 
Type type () const override
 
const Date & referenceDate () const override
 
std::size_t npv (const std::size_t amount, const Date &obsdate, const std::size_t filter, const boost::optional< long > &memSlot, const std::size_t addRegressor1, const std::size_t addRegressor2) const override
 
std::size_t fwdCompAvg (const bool isAvg, const std::string &indexInput, 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
 
Real getDirectFxSpotT0 (const std::string &forCcy, const std::string &domCcy) const override
 
Real getDirectDiscountT0 (const Date &paydate, const std::string &currency) const override
 
- Public Member Functions inherited from ModelCGImpl
 ModelCGImpl (const DayCounter &dayCounter, const Size size, const std::vector< std::string > &currencies, 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 IborFallbackConfig &iborFallbackConfig)
 
const std::string & baseCcy () const override
 
std::size_t dt (const Date &d1, const Date &d2) const override
 
std::size_t pay (const std::size_t amount, const Date &obsdate, const Date &paydate, const std::string &currency) const override
 
std::size_t discount (const Date &obsdate, const Date &paydate, const std::string &currency) const override
 
std::size_t eval (const std::string &index, const Date &obsdate, const Date &fwddate, const bool returnMissingMissingAsNull=false, const bool ignoreTodaysFixing=false) const override
 
std::size_t fxSpotT0 (const std::string &forCcy, const std::string &domCcy) const override
 
std::size_t barrierProbability (const std::string &index, const Date &obsdate1, const Date &obsdate2, const std::size_t barrier, const bool above) const override
 
Real extractT0Result (const RandomVariable &value) const override
 
std::size_t cgVersion () const override
 
const std::vector< std::vector< std::size_t > > & randomVariates () const override
 
std::vector< std::pair< std::size_t, double > > modelParameters () const override
 
std::vector< std::pair< std::size_t, std::function< double(void)> > > & modelParameterFunctors () const override
 
- Public Member Functions inherited from ModelCG
 ModelCG (const QuantLib::Size n)
 
virtual ~ModelCG ()
 
QuantLib::ext::shared_ptr< QuantExt::ComputationGraphcomputationGraph ()
 
virtual Type type () const =0
 
virtual QuantLib::Size size () const
 
virtual Size trainingSamples () const
 
virtual void toggleTrainingPaths () const
 
virtual const Date & referenceDate () const =0
 
virtual const std::string & baseCcy () const =0
 
virtual std::size_t dt (const Date &d1, const Date &d2) const
 
virtual std::size_t pay (const std::size_t amount, const Date &obsdate, const Date &paydate, const std::string &currency) const =0
 
virtual std::size_t discount (const Date &obsdate, const Date &paydate, const std::string &currency) const =0
 
virtual std::size_t npv (const std::size_t amount, const Date &obsdate, const std::size_t filter, const boost::optional< long > &memSlot, const std::size_t addRegressor1, const std::size_t addRegressor2) const =0
 
virtual std::size_t eval (const std::string &index, const Date &obsdate, const Date &fwddate, const bool returnMissingFixingAsNull=false, const bool ignoreTodaysFixing=false) const =0
 
virtual std::size_t 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 =0
 
virtual std::size_t barrierProbability (const std::string &index, const Date &obsdate1, const Date &obsdate2, const std::size_t barrier, const bool above) const =0
 
virtual std::size_t fxSpotT0 (const std::string &forCcy, const std::string &domCcy) const =0
 
virtual Real extractT0Result (const QuantExt::RandomVariable &value) const =0
 
virtual void resetNPVMem ()
 
const std::map< std::string, boost::any > & additionalResults () const
 
virtual std::size_t cgVersion () const =0
 
virtual const std::vector< std::vector< std::size_t > > & randomVariates () const =0
 
virtual std::vector< std::pair< std::size_t, double > > modelParameters () const =0
 
virtual std::vector< std::pair< std::size_t, std::function< double(void)> > > & modelParameterFunctors () const =0
 
virtual Real getDirectFxSpotT0 (const std::string &forCcy, const std::string &domCcy) const =0
 
virtual Real getDirectDiscountT0 (const Date &paydate, const std::string &currency) const =0
 
void calculate () const override
 

Private Member Functions

std::size_t getFutureBarrierProb (const std::string &index, const Date &obsdate1, const Date &obsdate2, const std::size_t barrier, const bool above) const override
 
void performCalculations () const override
 

Private Attributes

const std::string calibration_
 
const std::map< std::string, std::vector< Real > > calibrationStrikes_
 

Additional Inherited Members

- Public Types inherited from ModelCG
enum class  Type { MC , FD }
 
- Protected Member Functions inherited from BlackScholesCGBase
void performCalculations () const override
 
std::size_t getIndexValue (const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
 
std::size_t getIrIndexValue (const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
 
std::size_t getInfIndexValue (const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
 
std::size_t getDiscount (const Size idx, const Date &s, const Date &t) const override
 
std::size_t getNumeraire (const Date &s) const override
 
std::size_t getFxSpot (const Size idx) const override
 
- Protected Member Functions inherited from ModelCGImpl
virtual std::size_t getIndexValue (const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const =0
 
virtual std::size_t getIrIndexValue (const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const =0
 
virtual std::size_t getInfIndexValue (const Size indexNo, const Date &d, const Date &fwd) const =0
 
virtual std::size_t getDiscount (const Size idx, const Date &s, const Date &t) const =0
 
virtual std::size_t getNumeraire (const Date &s) const =0
 
virtual std::size_t getFxSpot (const Size idx) const =0
 
virtual std::size_t getFutureBarrierProb (const std::string &index, const Date &obsdate1, const Date &obsdate2, const std::size_t barrier, const bool above) const =0
 
std::size_t addModelParameter (const std::string &id, std::function< double(void)> f) const
 
void performCalculations () const override
 
- Protected Attributes inherited from BlackScholesCGBase
const std::vector< Handle< YieldTermStructure > > curves_
 
const std::vector< Handle< Quote > > fxSpots_
 
const Handle< BlackScholesModelWrappermodel_
 
const std::map< std::pair< std::string, std::string >, Handle< QuantExt::CorrelationTermStructure > > correlations_
 
const std::vector< Date > simulationDates_
 
Date referenceDate_
 
std::set< Date > effectiveSimulationDates_
 
TimeGrid timeGrid_
 
std::vector< Size > positionInTimeGrid_
 
std::map< Date, std::vector< std::size_t > > underlyingPaths_
 
std::size_t underlyingPathsCgVersion_ = 0
 
- Protected Attributes inherited from ModelCGImpl
const DayCounter dayCounter_
 
const std::vector< std::string > currencies_
 
const std::vector< std::string > indexCurrencies_
 
const std::set< Date > simulationDates_
 
const IborFallbackConfig iborFallbackConfig_
 
std::vector< std::pair< IndexInfo, QuantLib::ext::shared_ptr< InterestRateIndex > > > irIndices_
 
std::vector< std::pair< IndexInfo, QuantLib::ext::shared_ptr< ZeroInflationIndex > > > infIndices_
 
std::vector< IndexInfoindices_
 
std::vector< std::vector< size_t > > randomVariates_
 
std::vector< std::pair< std::size_t, std::function< double(void)> > > modelParameters_
 
- Protected Attributes inherited from ModelCG
std::map< std::string, boost::any > additionalResults_
 
QuantLib::ext::shared_ptr< QuantExt::ComputationGraphg_
 

Detailed Description

Definition at line 31 of file blackscholescg.hpp.

Constructor & Destructor Documentation

◆ BlackScholesCG() [1/2]

BlackScholesCG ( const Size  paths,
const std::vector< std::string > &  currencies,
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 std::set< Date > &  simulationDates,
const IborFallbackConfig iborFallbackConfig = IborFallbackConfig::defaultConfig(),
const std::string &  calibration = "ATM",
const std::map< std::string, std::vector< Real > > &  calibrationStrikes = {} 
)

Definition at line 45 of file blackscholescg.cpp.

55 : BlackScholesCGBase(paths, currencies, curves, fxSpots, irIndices, infIndices, indices, indexCurrencies, model,
56 correlations, simulationDates, iborFallbackConfig),
57 calibration_(calibration), calibrationStrikes_(calibrationStrikes) {}
BlackScholesCGBase(const Size paths, const std::vector< std::string > &currencies, 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 std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig)
const std::map< std::string, std::vector< Real > > calibrationStrikes_
const std::string calibration_

◆ BlackScholesCG() [2/2]

BlackScholesCG ( const Size  paths,
const std::string &  currency,
const Handle< YieldTermStructure > &  curve,
const std::string &  index,
const std::string &  indexCurrency,
const Handle< BlackScholesModelWrapper > &  model,
const std::set< Date > &  simulationDates,
const IborFallbackConfig iborFallbackConfig = IborFallbackConfig::defaultConfig(),
const std::string &  calibration = "ATM",
const std::vector< Real > &  calibrationStrikes = {} 
)

Definition at line 37 of file blackscholescg.cpp.

42 : BlackScholesCG(paths, {currency}, {curve}, {}, {}, {}, {index}, {indexCurrency}, model, {}, simulationDates,
43 iborFallbackConfig, calibration, {{index, calibrationStrikes}}) {}
BlackScholesCG(const Size paths, const std::vector< std::string > &currencies, 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 std::set< Date > &simulationDates, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig(), const std::string &calibration="ATM", const std::map< std::string, std::vector< Real > > &calibrationStrikes={})

Member Function Documentation

◆ getFutureBarrierProb()

std::size_t getFutureBarrierProb ( const std::string &  index,
const Date &  obsdate1,
const Date &  obsdate2,
const std::size_t  barrier,
const bool  above 
) const
overrideprivatevirtual

Implements ModelCGImpl.

Definition at line 423 of file blackscholescg.cpp.

424 {
425
426 // get the underlying values at the start and end points of the period
427
428 std::size_t v1 = eval(index, obsdate1, Null<Date>());
429 std::size_t v2 = eval(index, obsdate2, Null<Date>());
430
431 // check the barrier at the two endpoints
432
433 std::size_t barrierHit = cg_const(*g_, 0.0);
434 if (above) {
435 barrierHit = cg_min(*g_, cg_const(*g_, 1.0), cg_add(*g_, barrierHit, cg_indicatorGeq(*g_, v1, barrier)));
436 barrierHit = cg_min(*g_, cg_const(*g_, 1.0), cg_add(*g_, barrierHit, cg_indicatorGeq(*g_, v2, barrier)));
437 } else {
438 barrierHit =
439 cg_min(*g_, cg_const(*g_, 1.0),
440 cg_add(*g_, barrierHit, cg_subtract(*g_, cg_const(*g_, 1.0), cg_indicatorGt(*g_, v1, barrier))));
441 barrierHit =
442 cg_min(*g_, cg_const(*g_, 1.0),
443 cg_add(*g_, barrierHit, cg_subtract(*g_, cg_const(*g_, 1.0), cg_indicatorGt(*g_, v2, barrier))));
444 }
445
446 // for IR / INF indices we have to check each date, this is fast though, since the index values are deteministic
447 // here
448
449 auto ir = std::find_if(irIndices_.begin(), irIndices_.end(), comp(index));
450 auto inf = std::find_if(infIndices_.begin(), infIndices_.end(), comp(index));
451 if (ir != irIndices_.end() || inf != infIndices_.end()) {
452 Date d = obsdate1 + 1;
453 while (d < obsdate2) {
454 std::size_t res;
455 if (ir != irIndices_.end())
456 res = getIrIndexValue(std::distance(irIndices_.begin(), ir), d);
457 else
458 res = getInfIndexValue(std::distance(infIndices_.begin(), inf), d);
459
460 if (above) {
461 barrierHit =
462 cg_min(*g_, cg_const(*g_, 1.0), cg_add(*g_, barrierHit, cg_indicatorGeq(*g_, res, barrier)));
463 } else {
464 barrierHit = cg_min(
465 *g_, cg_const(*g_, 1.0),
466 cg_add(*g_, barrierHit, cg_subtract(*g_, cg_const(*g_, 1.0), cg_indicatorGt(*g_, res, barrier))));
467 }
468 ++d;
469 }
470 }
471
472 // return the result if we have an IR / INF index
473
474 if (ir != irIndices_.end() || inf != infIndices_.end())
475 return barrierHit;
476
477 // Now handle the dynamic indices in this model
478
479 // first make sure that v1 is not a historical fixing to avoid differences to a daily MC simulation where
480 // the process starts to evolve at the market data spot (only matters if the two values differ, which they
481 // should not too much anyway)
482
483 if (obsdate1 == referenceDate()) {
484 v1 = eval(index, obsdate1, Null<Date>(), false, true);
485 }
486
487 IndexInfo indexInfo(index);
488
489 // if we have an FX index, we "normalise" the tag by GENERIC (since it does not matter for projections), this
490 // is the same as in ModelImpl::eval()
491
492 if (indexInfo.isFx())
493 indexInfo = IndexInfo("FX-GENERIC-" + indexInfo.fx()->sourceCurrency().code() + "-" +
494 indexInfo.fx()->targetCurrency().code());
495
496 // get the average volatility over the period for the underlying, this is an approximation that could be refined
497 // by sampling more points in the interval and doing the below calculation for each subinterval - this would
498 // be slower though, so probably in the end we want this to be configurable in the model settings
499
500 // We might have one or two indices contributing to the desired volatility, since FX indices might require a
501 // triangulation. We look for the indices ind1 and ind2 so that the index is the quotient of the two.
502
503 Size ind1 = Null<Size>(), ind2 = Null<Size>();
504
505 auto i = std::find(indices_.begin(), indices_.end(), indexInfo);
506 if (i != indices_.end()) {
507 // we find the index directly in the index list
508 ind1 = std::distance(indices_.begin(), i);
509 } else {
510 // we can maybe triangulate an FX index (again, this is similar to ModelImpl::eval())
511 // if not, we can only try something else for FX indices
512 QL_REQUIRE(indexInfo.isFx(), "BlackScholes::getFutureBarrierProb(): index " << index << " not handled");
513 // is it a trivial fx index (CCY-CCY) or can we triangulate it?
514 if (indexInfo.fx()->sourceCurrency() == indexInfo.fx()->targetCurrency()) {
515 // pseudo FX index FX-GENERIC-CCY-CCY, leave ind1 and ind2 both set to zero
516 } else {
517 // if not, we can only try something else for FX indices
518 QL_REQUIRE(indexInfo.isFx(), "BlackScholes::getFutureBarrierProb(): index " << index << " not handled");
519 if (indexInfo.fx()->sourceCurrency() == indexInfo.fx()->targetCurrency()) {
520 // nothing to do, leave ind1 and ind2 = null
521 } else {
522 for (Size i = 0; i < indexCurrencies_.size(); ++i) {
523 if (indices_[i].isFx()) {
524 if (indexInfo.fx()->sourceCurrency().code() == indexCurrencies_[i])
525 ind1 = i;
526 if (indexInfo.fx()->targetCurrency().code() == indexCurrencies_[i])
527 ind2 = i;
528 }
529 }
530 }
531 }
532 }
533
534 // accumulate the variance contributions over [obsdate1, obsdate2]
535
536 std::size_t variance = cg_const(*g_, 0.0);
537
538 for (Size i = 1; i < effectiveSimulationDates_.size(); ++i) {
539
540 Date d1 = *std::next(effectiveSimulationDates_.begin(), i - 1);
541 Date d2 = *std::next(effectiveSimulationDates_.begin(), i);
542
543 if (obsdate1 <= d1 && d2 <= obsdate2) {
544 if (ind1 != Null<Size>()) {
545 std::string id =
546 "__cov_" + std::to_string(ind1) + "_" + std::to_string(ind1) + "_" + std::to_string(i - 1);
547 variance = cg_add(*g_, variance, cg_var(*g_, id));
548 }
549 if (ind2 != Null<Size>()) {
550 std::string id =
551 "__cov_" + std::to_string(ind2) + "_" + std::to_string(ind2) + "_" + std::to_string(i - 1);
552 variance = cg_add(*g_, variance, cg_var(*g_, id));
553 }
554 if (ind1 != Null<Size>() && ind2 != Null<Size>()) {
555 std::string id =
556 "__cov_" + std::to_string(ind1) + "_" + std::to_string(ind2) + "_" + std::to_string(i - 1);
557 variance = cg_subtract(*g_, variance, cg_mult(*g_, cg_const(*g_, 2.0), cg_var(*g_, id)));
558 }
559 }
560 }
561
562 // compute the hit probability
563 // see e.g. formulas 2, 4 in Emmanuel Gobet, Advanced Monte Carlo methods for barrier and related exotic options
564
565 std::size_t eps = cg_const(*g_, 1E-14);
566
567 variance = cg_max(*g_, variance, eps);
568 std::size_t adjBarrier = cg_max(*g_, barrier, eps);
569
570 std::size_t hitProb = cg_min(*g_, cg_const(*g_, 1.0),
571 cg_exp(*g_, cg_mult(*g_,
572 cg_mult(*g_, cg_div(*g_, cg_const(*g_, -2.0), variance),
573 cg_log(*g_, cg_div(*g_, v1, adjBarrier))),
574 cg_log(*g_, cg_div(*g_, v2, adjBarrier)))));
575
576 barrierHit = cg_add(*g_, barrierHit, cg_mult(*g_, cg_subtract(*g_, cg_const(*g_, 1.0), barrierHit), hitProb));
577
578 return barrierHit;
579} // getFutureBarrierProb()
std::size_t getInfIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
const Date & referenceDate() const override
std::size_t getIrIndexValue(const Size indexNo, const Date &d, const Date &fwd=Null< Date >()) const override
QuantLib::ext::shared_ptr< QuantExt::ComputationGraph > g_
Definition: modelcg.hpp:149
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_
std::size_t eval(const std::string &index, const Date &obsdate, const Date &fwddate, const bool returnMissingMissingAsNull=false, const bool ignoreTodaysFixing=false) const override
std::size_t cg_min(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
std::size_t cg_const(ComputationGraph &g, const double value)
std::size_t cg_indicatorGeq(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
std::size_t cg_subtract(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
RandomVariable variance(const RandomVariable &r)
std::size_t cg_max(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
std::size_t cg_exp(ComputationGraph &g, const std::size_t a, const std::string &label)
std::size_t cg_mult(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
std::size_t cg_add(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
std::size_t cg_var(ComputationGraph &g, const std::string &name, const bool createIfNotExists)
std::size_t cg_log(ComputationGraph &g, const std::size_t a, const std::string &label)
std::size_t cg_div(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
std::size_t cg_indicatorGt(ComputationGraph &g, const std::size_t a, const std::size_t b, const std::string &label)
+ Here is the call graph for this function:

◆ performCalculations()

void performCalculations ( ) const
overrideprivate

Definition at line 242 of file blackscholescg.cpp.

242 {
243
245
246 // nothing to do if we do not have any indices or if underlying paths are populated already
247
248 if (indices_.empty() || !underlyingPaths_.empty())
249 return;
250
251 // exit if there are no future simulation dates (i.e. only the reference date)
252
253 if (effectiveSimulationDates_.size() == 1)
254 return;
255
256 // init underlying path where we map a date to a randomvariable representing the path values
257
258 for (auto const& d : effectiveSimulationDates_) {
259 underlyingPaths_[d] = std::vector<std::size_t>(model_->processes().size(), ComputationGraph::nan);
260 }
261
262 // determine calibration strikes
263
264 std::vector<Real> calibrationStrikes;
265 if (calibration_ == "ATM") {
266 calibrationStrikes.resize(indices_.size(), Null<Real>());
267 } else if (calibration_ == "Deal") {
268 for (Size i = 0; i < indices_.size(); ++i) {
269 auto f = calibrationStrikes_.find(indices_[i].name());
270 if (f != calibrationStrikes_.end() && !f->second.empty()) {
271 calibrationStrikes.push_back(f->second[0]);
272 TLOG("calibration strike for index '" << indices_[i] << "' is " << f->second[0]);
273 } else {
274 calibrationStrikes.push_back(Null<Real>());
275 TLOG("calibration strike for index '" << indices_[i] << "' is ATMF");
276 }
277 }
278 } else {
279 QL_FAIL("BlackScholes: calibration '" << calibration_ << "' not supported, expected ATM, Deal");
280 }
281
282 // generate computation graph of underlying paths dependend on the drift and sqrtCov between simulation
283 // dates, which we treat as model parameters
284
285 auto sqrtCovCalc =
286 QuantLib::ext::make_shared<SqrtCovCalculator>(indices_, indexCurrencies_, correlations_, effectiveSimulationDates_,
287 timeGrid_, positionInTimeGrid_, model_, calibrationStrikes);
288
289 std::vector<std::vector<std::size_t>> drift(effectiveSimulationDates_.size() - 1,
290 std::vector<std::size_t>(indices_.size(), ComputationGraph::nan));
291 std::vector<std::vector<std::vector<std::size_t>>> sqrtCov(
292 effectiveSimulationDates_.size() - 1,
293 std::vector<std::vector<std::size_t>>(indices_.size(),
294 std::vector<std::size_t>(indices_.size(), ComputationGraph::nan)));
295 std::vector<std::vector<std::vector<std::size_t>>> cov(
296 effectiveSimulationDates_.size() - 1,
297 std::vector<std::vector<std::size_t>>(indices_.size(),
298 std::vector<std::size_t>(indices_.size(), ComputationGraph::nan)));
299
300 // precompute sqrtCov nodes and add model parameters for covariance (needed in futureBarrierProbability())
301
302 for (Size i = 0; i < effectiveSimulationDates_.size() - 1; ++i) {
303 for (Size j = 0; j < indices_.size(); ++j) {
304 for (Size k = 0; k < indices_.size(); ++k) {
305 std::string id = "__sqrtCov_" + std::to_string(j) + "_" + std::to_string(k) + "_" + std::to_string(i);
306 sqrtCov[i][j][k] =
307 addModelParameter(id, [sqrtCovCalc, i, j, k] { return sqrtCovCalc->sqrtCov(i, j, k); });
308 id = "__cov_" + std::to_string(j) + "_" + std::to_string(k) + "_" + std::to_string(i);
309 cov[i][j][k] = addModelParameter(id, [sqrtCovCalc, i, j, k] { return sqrtCovCalc->cov(i, j, k); });
310 }
311 }
312 }
313
314 // precompute drift nodes
315
316 std::vector<Size> forCcyDaIndex(indices_.size(), Null<Size>());
317 for (Size j = 0; j < indices_.size(); ++j) {
318 if (!indices_[j].isFx()) {
319 // do we have an fx index with the desired currency?
320 for (Size jj = 0; jj < indices_.size(); ++jj) {
321 if (indices_[jj].isFx()) {
323 forCcyDaIndex[j] = jj;
324 }
325 }
326 }
327 }
328
329 std::vector<std::size_t> discountRatio(indices_.size(), cg_const(*g_, 1.0));
330 auto date = effectiveSimulationDates_.begin();
331 for (Size i = 0; i < effectiveSimulationDates_.size() - 1; ++i) {
332 Date d = *(++date);
333 for (Size j = 0; j < indices_.size(); ++j) {
334 auto p = model_->processes().at(j);
335 std::string id = std::to_string(j) + "_" + ore::data::to_string(d);
336 std::size_t div= addModelParameter("__div_" + id, [p, d]() { return p->dividendYield()->discount(d); });
337 std::size_t rfr = addModelParameter("__rfr_" + id, [p, d]() { return p->riskFreeRate()->discount(d); });
338 std::size_t tmp = cg_div(*g_, rfr, div);
339 drift[i][j] = cg_subtract(*g_, cg_negative(*g_, cg_log(*g_, cg_div(*g_, tmp, discountRatio[j]))),
340 cg_mult(*g_, cg_const(*g_, 0.5), cov[i][j][j]));
341 discountRatio[j] = tmp;
342 if (forCcyDaIndex[j] != Null<Size>()) {
343 drift[i][j] = cg_subtract(*g_, drift[i][j], cov[i][forCcyDaIndex[j]][j]);
344 }
345 }
346 }
347
348 // set required random variates
349
350
351 randomVariates_ = std::vector<std::vector<std::size_t>>(
352 indices_.size(), std::vector<std::size_t>(effectiveSimulationDates_.size() - 1));
353
354 for (Size j = 0; j < indices_.size(); ++j) {
355 for (Size i = 0; i < effectiveSimulationDates_.size() - 1; ++i) {
356 randomVariates_[j][i] = cg_var(*g_, "__rv_" + std::to_string(j) + "_" + std::to_string(i),
357 ComputationGraph::VarDoesntExist::Create);
358 }
359 }
360
361 // evolve the process using correlated normal variates and set the underlying path values
362
363 std::vector<std::size_t> logState(indices_.size());
364 for (Size j = 0; j < indices_.size(); ++j) {
365 std::string id = "__x0_" + std::to_string(j);
366 auto p = model_->processes().at(j);
367 logState[j] = addModelParameter(id, [p] { return std::log(p->x0()); });
368 underlyingPaths_[*effectiveSimulationDates_.begin()][j] = cg_exp(*g_, logState[j]);
369 }
370
371 date = effectiveSimulationDates_.begin();
372 for (Size i = 0; i < effectiveSimulationDates_.size() - 1; ++i) {
373 ++date;
374 for (Size j = 0; j < indices_.size(); ++j) {
375 for (Size k = 0; k < indices_.size(); ++k) {
376 logState[j] = cg_add(*g_, logState[j], cg_mult(*g_, sqrtCov[i][j][k], randomVariates_[k][i]));
377 }
378 logState[j] = cg_add(*g_, logState[j], drift[i][j]);
379 underlyingPaths_[*date][j] = cg_exp(*g_, logState[j]);
380 }
381 }
382
383 // set additional results provided by this model
384
385 for (auto const& c : correlations_) {
386 additionalResults_["BlackScholes.Correlation_" + c.first.first + "_" + c.first.second] =
387 c.second->correlation(0.0);
388 }
389
390 for (Size i = 0; i < calibrationStrikes.size(); ++i) {
391 additionalResults_["BlackScholes.CalibrationStrike_" + indices_[i].name()] =
392 (calibrationStrikes[i] == Null<Real>() ? "ATMF" : std::to_string(calibrationStrikes[i]));
393 }
394
395 for (Size i = 0; i < indices_.size(); ++i) {
396 Size timeStep = 0;
397 for (auto const& d : effectiveSimulationDates_) {
398 Real t = timeGrid_[positionInTimeGrid_[timeStep]];
399 Real forward = atmForward(model_->processes()[i]->x0(), model_->processes()[i]->riskFreeRate(),
400 model_->processes()[i]->dividendYield(), t);
401 if (timeStep > 0) {
402 Real volatility = model_->processes()[i]->blackVolatility()->blackVol(
403 t, calibrationStrikes[i] == Null<Real>() ? forward : calibrationStrikes[i]);
404 additionalResults_["BlackScholes.Volatility_" + indices_[i].name() + "_" + ore::data::to_string(d)] =
405 volatility;
406 }
407 additionalResults_["BlackScholes.Forward_" + indices_[i].name() + "_" + ore::data::to_string(d)] = forward;
408 ++timeStep;
409 }
410 }
411} // performCalculations()
static std::size_t nan
void performCalculations() const override
std::map< Date, std::vector< std::size_t > > underlyingPaths_
const Handle< BlackScholesModelWrapper > model_
const std::map< std::pair< std::string, std::string >, Handle< QuantExt::CorrelationTermStructure > > correlations_
std::vector< Size > positionInTimeGrid_
std::map< std::string, boost::any > additionalResults_
Definition: modelcg.hpp:146
std::vector< std::vector< size_t > > randomVariates_
std::size_t discount(const Date &obsdate, const Date &paydate, const std::string &currency) const override
#define TLOG(text)
Logging Macro (Level = Data)
Definition: log.hpp:556
std::size_t cg_negative(ComputationGraph &g, const std::size_t a, const std::string &label)
Real atmForward(const Real s0, const Handle< YieldTermStructure > &r, const Handle< YieldTermStructure > &q, const Real t)
helper function that computes the atm forward
Definition: utilities.cpp:483
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
std::size_t addModelParameter(ComputationGraph &g, std::vector< std::pair< std::size_t, std::function< double(void)> > > &m, const std::string &id, std::function< double(void)> f)
string name
+ Here is the call graph for this function:

Member Data Documentation

◆ calibration_

const std::string calibration_
private

Definition at line 67 of file blackscholescg.hpp.

◆ calibrationStrikes_

const std::map<std::string, std::vector<Real> > calibrationStrikes_
private

Definition at line 70 of file blackscholescg.hpp.