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

#include <ored/portfolio/builders/scriptedtrade.hpp>

+ Inheritance diagram for ScriptedTradeEngineBuilder:
+ Collaboration diagram for ScriptedTradeEngineBuilder:

Public Member Functions

 ScriptedTradeEngineBuilder ()
 constructor that builds a usual pricing engine More...
 
 ScriptedTradeEngineBuilder (const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > &amcCam, const std::vector< Date > &amcGrid)
 constructor that builds an AMC - enabled pricing engine More...
 
 ScriptedTradeEngineBuilder (const QuantLib::ext::shared_ptr< ore::data::ModelCG > &amcCgModel, const std::vector< Date > &amcGrid)
 constructor that builds an AMCCG pricing engine More...
 
QuantLib::ext::shared_ptr< QuantExt::ScriptedInstrument::engineengine (const std::string &id, const ScriptedTrade &scriptedTrade, const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &referenceData=nullptr, const IborFallbackConfig &iborFallbackConfig=IborFallbackConfig::defaultConfig())
 
const std::string & npvCurrency () const
 
const QuantLib::Date & lastRelevantDate () const
 
const std::string & simmProductClass () const
 
const std::string & scheduleProductClass () const
 
const std::string & sensitivityTemplate () const
 
const std::map< std::string, std::set< Date > > & fixings () const
 
- Public Member Functions inherited from EngineBuilder
 EngineBuilder (const string &model, const string &engine, const set< string > &tradeTypes)
 
virtual ~EngineBuilder ()
 Virtual destructor. More...
 
const string & model () const
 Return the model name. More...
 
const string & engine () const
 Return the engine name. More...
 
const set< string > & tradeTypes () const
 Return the possible trade types. More...
 
const string & configuration (const MarketContext &key)
 Return a configuration (or the default one if key not found) More...
 
virtual void reset ()
 reset the builder (e.g. clear cache) More...
 
void init (const QuantLib::ext::shared_ptr< Market > market, const map< MarketContext, string > &configurations, const map< string, string > &modelParameters, const map< string, string > &engineParameters, const std::map< std::string, std::string > &globalParameters={})
 Initialise this Builder with the market and parameters to use. More...
 
const set< std::pair< string, QuantLib::ext::shared_ptr< QuantExt::ModelBuilder > > > & modelBuilders () const
 return model builders More...
 
std::string engineParameter (const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
 
std::string modelParameter (const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
 

Protected Member Functions

virtual QuantLib::Handle< QuantExt::CorrelationTermStructurecorrelationCurve (const std::string &index1, const std::string &index2)
 
void clear ()
 
void extractIndices (const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &referenceData=nullptr)
 
void deriveProductClass (const std::vector< ScriptedTradeValueTypeData > &indices)
 
void populateModelParameters ()
 
void populateFixingsMap (const IborFallbackConfig &iborFallbackConfig)
 
void extractPayCcys ()
 
void determineBaseCcy ()
 
void compileModelCcyList ()
 
void compileModelIndexLists ()
 
void setupCorrelations ()
 
void setLastRelevantDate ()
 
virtual void setupBlackScholesProcesses ()
 
void setupIrReversions ()
 
void compileSimulationAndAddDates ()
 
void buildBlackScholes (const std::string &id, const IborFallbackConfig &iborFallbackConfig)
 
void buildFdBlackScholes (const std::string &id, const IborFallbackConfig &iborFallbackConfig)
 
void buildLocalVol (const std::string &id, const IborFallbackConfig &iborFallbackConfig)
 
void buildGaussianCam (const std::string &id, const IborFallbackConfig &iborFallbackConfig, const std::vector< std::string > &conditionalExpectationModelStates)
 
void buildFdGaussianCam (const std::string &id, const IborFallbackConfig &iborFallbackConfig)
 
void buildGaussianCamAMC (const std::string &id, const IborFallbackConfig &iborFallbackConfig, const std::vector< std::string > &conditionalExpectationModelStates)
 
void buildAMCCGModel (const std::string &id, const IborFallbackConfig &iborFallbackConfig, const std::vector< std::string > &conditionalExpectationModelStates)
 
void addAmcGridToContext (QuantLib::ext::shared_ptr< Context > &context) const
 
void setupCalibrationStrikes (const ScriptedTradeScriptData &script, const QuantLib::ext::shared_ptr< Context > &context)
 
std::string getEqCcy (const IndexInfo &e)
 
std::string getCommCcy (const IndexInfo &e)
 

Protected Attributes

bool buildingAmc_ = false
 
const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModelamcCam_
 
const QuantLib::ext::shared_ptr< ore::data::ModelCGamcCgModel_
 
const std::vector< Date > amcGrid_
 
std::map< std::string, ASTNodePtrastCache_
 
ASTNodePtr ast_
 
std::string npvCurrency_
 
QuantLib::Date lastRelevantDate_
 
std::string simmProductClass_
 
std::string scheduleProductClass_
 
std::string sensitivityTemplate_
 
std::map< std::string, std::set< Date > > fixings_
 
QuantLib::ext::shared_ptr< StaticAnalyserstaticAnalyser_
 
std::set< IndexInfoeqIndices_
 
std::set< IndexInfocommIndices_
 
std::set< IndexInfoirIndices_
 
std::set< IndexInfoinfIndices_
 
std::set< IndexInfofxIndices_
 
std::string resolvedProductTag_
 
std::string assetClassReplacement_
 
std::set< std::string > payCcys_
 
std::string baseCcy_
 
std::vector< std::string > modelCcys_
 
std::vector< Handle< YieldTermStructure > > modelCurves_
 
std::vector< Handle< Quote > > modelFxSpots_
 
std::vector< std::string > modelIndices_
 
std::vector< std::string > modelIndicesCurrencies_
 
std::vector< std::pair< std::string, QuantLib::ext::shared_ptr< InterestRateIndex > > > modelIrIndices_
 
std::vector< std::pair< std::string, QuantLib::ext::shared_ptr< ZeroInflationIndex > > > modelInfIndices_
 
std::map< std::pair< std::string, std::string >, Handle< QuantExt::CorrelationTermStructure > > correlations_
 
std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
 
std::map< std::string, Real > irReversions_
 
std::set< Date > simulationDates_
 
std::set< Date > addDates_
 
QuantLib::ext::shared_ptr< Modelmodel_
 
QuantLib::ext::shared_ptr< ModelCGmodelCG_
 
std::map< std::string, std::vector< Real > > calibrationStrikes_
 
std::string modelParam_
 
std::string infModelType_
 
std::string engineParam_
 
std::string baseCcyParam_
 
std::string gridCoarsening_
 
bool fullDynamicFx_
 
bool fullDynamicIr_
 
bool enforceBaseCcy_
 
Size modelSize_
 
Size timeStepsPerYear_
 
Model::McParams mcParams_
 
bool interactive_
 
bool zeroVolatility_
 
bool continueOnCalibrationError_
 
std::vector< Real > calibrationMoneyness_
 
Real mesherEpsilon_
 
Real mesherScaling_
 
Real mesherConcentration_
 
Size mesherMaxConcentratingPoints_
 
bool mesherIsStatic_
 
std::string referenceCalibrationGrid_
 
Real bootstrapTolerance_
 
bool calibrate_
 
std::string calibration_
 
bool useCg_
 
bool useAd_
 
bool useExternalComputeDevice_
 
bool useDoublePrecisionForExternalCalculation_
 
bool externalDeviceCompatibilityMode_
 
std::string externalComputeDevice_
 
bool includePastCashflows_
 
- Protected Attributes inherited from EngineBuilder
string model_
 
string engine_
 
set< string > tradeTypes_
 
QuantLib::ext::shared_ptr< Marketmarket_
 
map< MarketContext, string > configurations_
 
map< string, string > modelParameters_
 
map< string, string > engineParameters_
 
std::map< std::string, std::string > globalParameters_
 
set< std::pair< string, QuantLib::ext::shared_ptr< QuantExt::ModelBuilder > > > modelBuilders_
 

Detailed Description

Definition at line 38 of file scriptedtrade.hpp.

Constructor & Destructor Documentation

◆ ScriptedTradeEngineBuilder() [1/3]

constructor that builds a usual pricing engine

Definition at line 41 of file scriptedtrade.hpp.

41: EngineBuilder("Generic", "Generic", {"ScriptedTrade"}) {}
EngineBuilder(const string &model, const string &engine, const set< string > &tradeTypes)

◆ ScriptedTradeEngineBuilder() [2/3]

ScriptedTradeEngineBuilder ( const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > &  amcCam,
const std::vector< Date > &  amcGrid 
)

constructor that builds an AMC - enabled pricing engine

Definition at line 44 of file scriptedtrade.hpp.

46 : EngineBuilder("Generic", "Generic", {"ScriptedTrade"}), buildingAmc_(true), amcCam_(amcCam),
47 amcGrid_(amcGrid) {}
const QuantLib::ext::shared_ptr< QuantExt::CrossAssetModel > amcCam_
const std::vector< Date > amcGrid_

◆ ScriptedTradeEngineBuilder() [3/3]

ScriptedTradeEngineBuilder ( const QuantLib::ext::shared_ptr< ore::data::ModelCG > &  amcCgModel,
const std::vector< Date > &  amcGrid 
)

constructor that builds an AMCCG pricing engine

Definition at line 50 of file scriptedtrade.hpp.

52 : EngineBuilder("Generic", "Generic", {"ScriptedTrade"}), buildingAmc_(true), amcCgModel_(amcCgModel),
53 amcGrid_(amcGrid) {}
const QuantLib::ext::shared_ptr< ore::data::ModelCG > amcCgModel_

Member Function Documentation

◆ engine()

QuantLib::ext::shared_ptr< ScriptedInstrument::engine > engine ( const std::string &  id,
const ScriptedTrade scriptedTrade,
const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &  referenceData = nullptr,
const IborFallbackConfig iborFallbackConfig = IborFallbackConfig::defaultConfig() 
)

Definition at line 78 of file scriptedtrade.cpp.

80 {
81
82 const std::vector<ScriptedTradeEventData>& events = scriptedTrade.events();
83 const std::vector<ScriptedTradeValueTypeData>& numbers = scriptedTrade.numbers();
84 const std::vector<ScriptedTradeValueTypeData>& indices = scriptedTrade.indices();
85 const std::vector<ScriptedTradeValueTypeData>& currencies = scriptedTrade.currencies();
86 const std::vector<ScriptedTradeValueTypeData>& daycounters = scriptedTrade.daycounters();
87
88 LOG("Building engine for scripted trade " << id);
89
90 // 0 clear members
91
92 clear();
93
94 // 1 set the SIMM product class, simple EQ > COM > FX approach for Hybrids, that's all we can do automatically?
95 // also set the assetClassReplacement string which is used to replace {AssetClass} in product tags
96
97 deriveProductClass(indices);
98
99 // 1b get product tag from scripted trade or library and build resolved product tag
100
101 std::string productTag = getScript(scriptedTrade, ScriptLibraryStorage::instance().get(), "", false).first;
102 resolvedProductTag_ = boost::replace_all_copy(productTag, "{AssetClass}", assetClassReplacement_);
103 DLOG("got product tag '" << productTag << "', resolved product tag is '" << resolvedProductTag_);
104
105 // 2 populate model and engine parameters
106
108
109 // 3 define purpose, get suitable script and build ast (i.e. parse it or retrieve it from cache)
110
111 std::string purpose = "";
112 if (buildingAmc_)
113 purpose = "AMC";
114 else if (engineParam_ == "FD")
115 purpose = "FD";
116
117 ScriptedTradeScriptData script =
118 getScript(scriptedTrade, ScriptLibraryStorage::instance().get(), purpose, true).second;
119
120 auto f = astCache_.find(script.code());
121
122 if (f != astCache_.end()) {
123 ast_ = f->second;
124 DLOG("retrieved ast from cache");
125 } else {
126 ast_ = parseScript(script.code());
127 astCache_[script.code()] = ast_;
128 DLOGGERSTREAM("built ast:\n" << to_string(ast_));
129 }
130
131 // 4 set up context
132
133 auto context = makeContext(modelSize_, gridCoarsening_, script.schedulesEligibleForCoarsening(), referenceData,
134 events, numbers, indices, currencies, daycounters);
135 addAmcGridToContext(context);
136 addNewSchedulesToContext(context, script.newSchedules());
137
138 DLOG("Built initial context:");
139 DLOGGERSTREAM(*context);
140
141 // 4b set up calibration strike information
142
143 if (!buildingAmc_)
145
146 // 5 run static analyser
147
148 DLOG("Run static analyser on script");
149 staticAnalyser_ = QuantLib::ext::make_shared<StaticAnalyser>(ast_, context);
150 staticAnalyser_->run(script.code());
151
152 // 6 extract eq, fx, ir indices from script
153
154 extractIndices(referenceData);
155
156 // 7 populate fixings map
157
158 populateFixingsMap(iborFallbackConfig);
159
160 // 8 init result variable for NPV
161
162 checkDuplicateName(context, script.npv());
163 context->scalars[script.npv()] = RandomVariable(modelSize_, 0.0);
164
165 // 9 extract pay currencies
166
168
169 // 10 determine base ccy, this might be overwritten in 11 when an AMC engine is built, see the implementation of 11
170
172
173 // 11 compile the model currency list (depends on the model actually)
174
176
177 // 12 get the t0 curves for each model ccy
178
179 std::string externalDiscountCurve = scriptedTrade.envelope().additionalField("discount_curve", false);
180 std::string externalSecuritySpread = scriptedTrade.envelope().additionalField("security_spread", false);
181 for (auto const& c : modelCcys_) {
182 // for base ccy we account for an external discount curve and security spread if given
183 Handle<YieldTermStructure> yts =
184 externalDiscountCurve.empty() || c != baseCcy_
185 ? market_->discountCurve(c, configuration(MarketContext::pricing))
187 if (!externalSecuritySpread.empty() && c == baseCcy_)
188 yts = Handle<YieldTermStructure>(QuantLib::ext::make_shared<ZeroSpreadedTermStructure>(
189 yts, market_->securitySpread(externalSecuritySpread, configuration(MarketContext::pricing))));
190 modelCurves_.push_back(yts);
191 DLOG("curve for " << c << " added.");
192 }
193
194 // 13 get the fx spots for each model ccy vs. the base ccy
195
196 for (Size i = 1; i < modelCcys_.size(); ++i) {
198 DLOG("fx spot " << modelCcys_[i] + baseCcy_ << " added.");
199 }
200
201 // 14 compile the model index (eq, fx, comm) and ir index lists
202
204
205 // 15 determine last relevant date as max over index eval, regression, pay obs/pay dates
206
208
209 // 16 set up correlations between model indices (ir, eq, fx, comm)
210
212
213 // 17 compile the processes (needed for BlackScholes, LocalVol only)
214
215 if (modelParam_ == "BlackScholes" || modelParam_ == "LocalVolDupire" || modelParam_ == "LocalVolAndreasenHuge")
217
218 // 18 setup IR reversion values (needed for Gaussian CAM only)
219
220 if (modelParam_ == "GaussianCam") {
222 }
223
224 // 19 compile the sim and add dates required by the model ctors below
225
227
228 // 20 build the model adapter
229
230 QL_REQUIRE(!buildingAmc_ || modelParam_ == "GaussianCam",
231 "model/engine = GaussianCam/MC required to build an amc model, got " << modelParam_ << "/"
232 << engineParam_);
233
234 if(staticAnalyser_->regressionDates().empty())
235 mcParams_.trainingSamples = Null<Size>();
236
237 if (modelParam_ == "BlackScholes" && engineParam_ == "MC") {
238 buildBlackScholes(id, iborFallbackConfig);
239 } else if (modelParam_ == "BlackScholes" && engineParam_ == "FD") {
240 buildFdBlackScholes(id, iborFallbackConfig);
241 } else if ((modelParam_ == "LocalVolDupire" || modelParam_ == "LocalVolAndreasenHuge") && engineParam_ == "MC") {
242 buildLocalVol(id, iborFallbackConfig);
243 } else if (modelParam_ == "GaussianCam" && engineParam_ == "MC") {
244 if (amcCam_) {
245 buildGaussianCamAMC(id, iborFallbackConfig, script.conditionalExpectationModelStates());
246 } else if (amcCgModel_) {
247 buildAMCCGModel(id, iborFallbackConfig, script.conditionalExpectationModelStates());
248 } else {
249 buildGaussianCam(id, iborFallbackConfig, script.conditionalExpectationModelStates());
250 }
251 } else if (modelParam_ == "GaussianCam" && engineParam_ == "FD") {
252 buildFdGaussianCam(id, iborFallbackConfig);
253 } else {
254 QL_FAIL("model '" << modelParam_ << "' / engine '" << engineParam_
255 << "' not recognised, expected BlackScholes/[MC|FD], LocalVolDupire/MC, "
256 "LocalVolAndreasenHuge/MC, GaussianCam/MC");
257 }
258
259 QL_REQUIRE(model_ != nullptr || modelCG_ != nullptr, "internal error: both model_ and modelCG_ are null");
260
261 // 21 log some summary information
262
263 DLOG("built model : " << modelParam_ << " / " << engineParam_);
264 DLOG("useCg = " << std::boolalpha << useCg_);
265 DLOG("useAd = " << std::boolalpha << useAd_);
266 DLOG("useExternalDevice = " << std::boolalpha << useExternalComputeDevice_);
267 DLOG("useDblPrecExtCalc = " << std::boolalpha << useDoublePrecisionForExternalCalculation_);
268 DLOG("extDeviceCompatMode = " << std::boolalpha << externalDeviceCompatibilityMode_);
269 DLOG("externalDevice = " << (useExternalComputeDevice_ ? externalComputeDevice_ : "na"));
270 DLOG("calibration = " << calibration_);
271 DLOG("base ccy = " << baseCcy_);
272 DLOG("model base (npv) ccy = " << (model_ != nullptr ? model_->baseCcy() : modelCG_->baseCcy()));
273 DLOG("ccys = " << modelCcys_.size());
274 DLOG("eq,fx,com indices = " << modelIndices_.size());
275 DLOG("ir indices = " << irIndices_.size());
276 DLOG("inf indices = " << infIndices_.size());
277 DLOG("sim dates = " << simulationDates_.size());
278 DLOG("add dates = " << addDates_.size());
279 DLOG("timeStepsPerYear = " << timeStepsPerYear_);
280 DLOG("fullDynamicFx = " << std::boolalpha << fullDynamicFx_);
281 if (engineParam_ == "MC") {
282 DLOG("seed = " << mcParams_.seed);
283 DLOG("paths = " << modelSize_);
284 DLOG("regressionOrder = " << mcParams_.regressionOrder);
285 DLOG("sequence type = " << mcParams_.sequenceType);
286 DLOG("polynom type = " << mcParams_.polynomType);
287 if (mcParams_.trainingSamples != Null<Size>()) {
288 DLOG("training seed = " << mcParams_.trainingSeed);
289 DLOG("training paths = " << mcParams_.trainingSamples);
290 DLOG("training seq. type = " << mcParams_.trainingSequenceType);
291 }
292 DLOG("sobol bb ordering = " << mcParams_.sobolOrdering);
293 DLOG("sobol direction int. = " << mcParams_.sobolDirectionIntegers);
294 } else if (engineParam_ == "FD") {
295 DLOG("stateGridPoints = " << modelSize_);
296 DLOG("mesherEpsilon = " << mesherEpsilon_);
297 DLOG("mesherScaling = " << mesherScaling_);
298 DLOG("mesherConcentration = " << mesherConcentration_);
299 DLOG("mesherMaxConcentrPts = " << mesherMaxConcentratingPoints_);
300 DLOG("mesherIsStatic = " << std::boolalpha << mesherIsStatic_);
301 }
302 if (modelParam_ == "GaussianCam") {
303 DLOG("fullDynamicIr = " << std::boolalpha << fullDynamicIr_);
304 DLOG("ref calibration grid = " << referenceCalibrationGrid_);
305 DLOG("bootstrap tolerance = " << bootstrapTolerance_);
306 DLOG("infModelType = " << infModelType_);
307 DLOG("condExpMdlStates = " << boost::algorithm::join(script.conditionalExpectationModelStates(), ","));
308 } else if (modelParam_ == "LocalVolAndreasenHuge") {
309 DLOG("moneyness points = " << calibrationMoneyness_.size());
310 }
311
312 // 22 build the pricing engine and return it
313
314 bool generateAdditionalResults = false;
315 auto p = globalParameters_.find("GenerateAdditionalResults");
316 if (p != globalParameters_.end()) {
317 generateAdditionalResults = parseBool(p->second);
318 }
319
320 QuantLib::ext::shared_ptr<ScriptedInstrument::engine> engine;
321 if (model_) {
322 engine = QuantLib::ext::make_shared<ScriptedInstrumentPricingEngine>(
323 script.npv(), script.results(), model_, ast_, context, script.code(), interactive_, amcCam_ != nullptr,
324 std::set<std::string>(script.stickyCloseOutStates().begin(), script.stickyCloseOutStates().end()),
325 generateAdditionalResults, includePastCashflows_);
326 } else if (modelCG_) {
327 auto rt = globalParameters_.find("RunType");
328 std::string runType = rt != globalParameters_.end() ? rt->second : "<<no run type set>>";
329 bool useCachedSensis = useAd_ && (runType == "SensitivityDelta");
330 bool useExternalDev = useExternalComputeDevice_ && !generateAdditionalResults && !useCachedSensis;
331 if (useAd_ && !useCachedSensis) {
332 WLOG("Will not apply AD although useAD is configured, because runType ("
333 << runType << ") does not match SensitivitiyDelta");
334 }
335 if (useExternalComputeDevice_ && !useExternalDev) {
336 WLOG("Will not use exxternal compute deivce although useExternalComputeDevice is configured, because we "
337 "are either applying AD ("
338 << std::boolalpha << useCachedSensis << ") or we are generating add results ("
339 << generateAdditionalResults << "), both of which do not support external devices at the moment.");
340 }
341 engine = QuantLib::ext::make_shared<ScriptedInstrumentPricingEngineCG>(
342 script.npv(), script.results(), modelCG_, ast_, context, mcParams_, script.code(), interactive_,
343 generateAdditionalResults, includePastCashflows_, useCachedSensis, useExternalDev,
345 if (useExternalDev) {
346 ComputeEnvironment::instance().selectContext(externalComputeDevice_);
347 }
348 }
349
350 LOG("engine built for model " << modelParam_ << " / " << engineParam_ << ", modelSize = " << modelSize_
351 << ", interactive = " << interactive_ << ", amcEnabled = " << buildingAmc_
352 << ", generateAdditionalResults = " << generateAdditionalResults);
353 return engine;
354}
std::string script
QuantLib::ext::shared_ptr< Market > market_
const string & engine() const
Return the engine name.
const string & configuration(const MarketContext &key)
Return a configuration (or the default one if key not found)
std::map< std::string, std::string > globalParameters_
QuantLib::ext::shared_ptr< StaticAnalyser > staticAnalyser_
void buildLocalVol(const std::string &id, const IborFallbackConfig &iborFallbackConfig)
std::vector< std::string > modelIndices_
void buildFdGaussianCam(const std::string &id, const IborFallbackConfig &iborFallbackConfig)
void buildAMCCGModel(const std::string &id, const IborFallbackConfig &iborFallbackConfig, const std::vector< std::string > &conditionalExpectationModelStates)
void buildFdBlackScholes(const std::string &id, const IborFallbackConfig &iborFallbackConfig)
void extractIndices(const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &referenceData=nullptr)
std::vector< Handle< Quote > > modelFxSpots_
QuantLib::ext::shared_ptr< Model > model_
void buildGaussianCam(const std::string &id, const IborFallbackConfig &iborFallbackConfig, const std::vector< std::string > &conditionalExpectationModelStates)
std::vector< std::string > modelCcys_
void buildGaussianCamAMC(const std::string &id, const IborFallbackConfig &iborFallbackConfig, const std::vector< std::string > &conditionalExpectationModelStates)
void setupCalibrationStrikes(const ScriptedTradeScriptData &script, const QuantLib::ext::shared_ptr< Context > &context)
QuantLib::ext::shared_ptr< ModelCG > modelCG_
void addAmcGridToContext(QuantLib::ext::shared_ptr< Context > &context) const
void buildBlackScholes(const std::string &id, const IborFallbackConfig &iborFallbackConfig)
std::vector< Handle< YieldTermStructure > > modelCurves_
void populateFixingsMap(const IborFallbackConfig &iborFallbackConfig)
void deriveProductClass(const std::vector< ScriptedTradeValueTypeData > &indices)
std::map< std::string, ASTNodePtr > astCache_
bool parseBool(const string &s)
Convert text to bool.
Definition: parsers.cpp:144
#define LOG(text)
Logging Macro (Level = Notice)
Definition: log.hpp:552
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
#define WLOG(text)
Logging Macro (Level = Warning)
Definition: log.hpp:550
#define DLOGGERSTREAM(text)
Definition: log.hpp:632
ASTNodePtr parseScript(const std::string &code)
Definition: utilities.cpp:121
Handle< YieldTermStructure > indexOrYieldCurve(const QuantLib::ext::shared_ptr< Market > &market, const std::string &name, const std::string &configuration)
Definition: marketdata.cpp:65
void addNewSchedulesToContext(QuantLib::ext::shared_ptr< Context > context, const std::vector< ScriptedTradeScriptData::NewScheduleData > &newSchedules)
Definition: utilities.cpp:322
std::string to_string(const LocationInfo &l)
Definition: ast.cpp:28
void checkDuplicateName(const QuantLib::ext::shared_ptr< Context > context, const std::string &name)
Definition: utilities.cpp:156
std::pair< std::string, ScriptedTradeScriptData > getScript(const ScriptedTrade &scriptedTrade, const ScriptLibraryData &scriptLibrary, const std::string &purpose, const bool fallBackOnEmptyPurpose)
Definition: utilities.cpp:105
QuantLib::ext::shared_ptr< Context > makeContext(Size nPaths, const std::string &gridCoarsening, const std::vector< std::string > &schedulesEligibleForCoarsening, const QuantLib::ext::shared_ptr< ReferenceDataManager > &referenceData, const std::vector< ScriptedTradeEventData > &events, const std::vector< ScriptedTradeValueTypeData > &numbers, const std::vector< ScriptedTradeValueTypeData > &indices, const std::vector< ScriptedTradeValueTypeData > &currencies, const std::vector< ScriptedTradeValueTypeData > &daycounters)
Definition: utilities.cpp:163
QuantExt::SequenceType sequenceType
Definition: model.hpp:54
QuantLib::SobolBrownianGenerator::Ordering sobolOrdering
Definition: model.hpp:59
QuantExt::SequenceType trainingSequenceType
Definition: model.hpp:55
QuantLib::SobolRsg::DirectionIntegers sobolDirectionIntegers
Definition: model.hpp:60
QuantLib::LsmBasisSystem::PolynomialType polynomType
Definition: model.hpp:58
+ Here is the call graph for this function:

◆ npvCurrency()

const std::string & npvCurrency ( ) const

Definition at line 61 of file scriptedtrade.hpp.

61{ return model_ ? model_->baseCcy() : modelCG_->baseCcy(); }

◆ lastRelevantDate()

const QuantLib::Date & lastRelevantDate ( ) const

Definition at line 62 of file scriptedtrade.hpp.

◆ simmProductClass()

const std::string & simmProductClass ( ) const

Definition at line 63 of file scriptedtrade.hpp.

◆ scheduleProductClass()

const std::string & scheduleProductClass ( ) const

Definition at line 64 of file scriptedtrade.hpp.

◆ sensitivityTemplate()

const std::string & sensitivityTemplate ( ) const

Definition at line 65 of file scriptedtrade.hpp.

◆ fixings()

const std::map< std::string, std::set< Date > > & fixings ( ) const

Definition at line 66 of file scriptedtrade.hpp.

66{ return fixings_; }
std::map< std::string, std::set< Date > > fixings_
+ Here is the caller graph for this function:

◆ correlationCurve()

QuantLib::Handle< QuantExt::CorrelationTermStructure > correlationCurve ( const std::string &  index1,
const std::string &  index2 
)
protectedvirtual

Definition at line 65 of file scriptedtrade.cpp.

65 {
66 if (index1 == index2) {
67 // need to handle this case here, we might have calls with index1 == index arising from COMM
68 // indices with different spot / future reference, for which we expect the correlation on
69 // the name level (i.e. for the spot index)
70 return Handle<QuantExt::CorrelationTermStructure>(
71 QuantLib::ext::make_shared<FlatCorrelation>(0, NullCalendar(), 1.0, ActualActual(ActualActual::ISDA)));
72 } else {
73 return market_->correlationCurve(index1, index2, configuration(MarketContext::pricing));
74 }
75}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ clear()

void clear ( )
protected

Definition at line 356 of file scriptedtrade.cpp.

356 {
357 fixings_.clear();
358 eqIndices_.clear();
359 commIndices_.clear();
360 irIndices_.clear();
361 infIndices_.clear();
362 fxIndices_.clear();
363 payCcys_.clear();
364 modelCcys_.clear();
365 modelCurves_.clear();
366 modelFxSpots_.clear();
367 modelIndices_.clear();
369 modelIrIndices_.clear();
370 modelInfIndices_.clear();
371 correlations_.clear();
372 processes_.clear();
373 irReversions_.clear();
374 simulationDates_.clear();
375 addDates_.clear();
376 calibrationStrikes_.clear();
377}
std::map< std::string, Real > irReversions_
std::vector< std::string > modelIndicesCurrencies_
std::map< std::pair< std::string, std::string >, Handle< QuantExt::CorrelationTermStructure > > correlations_
std::vector< std::pair< std::string, QuantLib::ext::shared_ptr< ZeroInflationIndex > > > modelInfIndices_
std::map< std::string, std::vector< Real > > calibrationStrikes_
std::vector< std::pair< std::string, QuantLib::ext::shared_ptr< InterestRateIndex > > > modelIrIndices_
std::vector< QuantLib::ext::shared_ptr< GeneralizedBlackScholesProcess > > processes_
+ Here is the caller graph for this function:

◆ extractIndices()

void extractIndices ( const QuantLib::ext::shared_ptr< ore::data::ReferenceDataManager > &  referenceData = nullptr)
protected

Definition at line 379 of file scriptedtrade.cpp.

380 {
381 DLOG("Extract indices from script:");
382 for (auto const& i : staticAnalyser_->indexEvalDates()) {
383 IndexInfo ind(i.first);
384 if (ind.isEq()) {
385 eqIndices_.insert(ind);
386 } else if (ind.isIr()) {
387 irIndices_.insert(ind);
388 } else if (ind.isInf()) {
389 infIndices_.insert(ind);
390 } else if (ind.isFx()) {
391 // ignore trivial fx indices
392 if (ind.fx()->sourceCurrency() != ind.fx()->targetCurrency())
393 fxIndices_.insert(ind);
394 } else if (ind.isComm()) {
395 commIndices_.insert(ind);
396 } else if (ind.isGeneric()) {
397 // ignore generic indices, only historical fixings can be retrieved from them
398 } else {
399 QL_FAIL("unexpected index type for '" << ind.name() << "'");
400 }
401 DLOG("got " << ind);
402 }
403 for (auto const& i : staticAnalyser_->fwdCompAvgFixingDates()) {
404 IndexInfo ind(i.first);
405 QL_REQUIRE(ind.isIr(), "expected IR (ON) index for " << ind.name());
406 irIndices_.insert(ind);
407 DLOG("got " << ind);
408 }
409}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ deriveProductClass()

void deriveProductClass ( const std::vector< ScriptedTradeValueTypeData > &  indices)
protected

Definition at line 411 of file scriptedtrade.cpp.

411 {
412 std::set<std::string> names;
413 std::set<IndexInfo> commIndices, eqIndices, fxIndices, irIndices, infIndices;
414
415 for (auto const& i : indices) {
416 if (i.isArray()) {
417 names.insert(i.values().begin(), i.values().end());
418 } else {
419 names.insert(i.value());
420 }
421 }
422
423 for (auto const& n : names) {
424 IndexInfo ind(n);
425 if (ind.isFx())
426 fxIndices.insert(ind);
427 else if (ind.isEq())
428 eqIndices.insert(ind);
429 else if (ind.isComm())
430 commIndices.insert(ind);
431 else if (ind.isIr())
432 irIndices.insert(ind);
433 else if (ind.isInf())
434 infIndices.insert(ind);
435 }
436
438 if (!commIndices.empty()) {
439 simmProductClass_ = "Commodity";
440 scheduleProductClass_ = "Commodity";
441 assetClassReplacement_ = "COMM";
442 } else if (!eqIndices.empty()) {
443 simmProductClass_ = "Equity";
444 scheduleProductClass_ = "Equity";
446 } else if (!fxIndices.empty()) {
447 simmProductClass_ = "RatesFX";
450 for (auto const& i : fxIndices) {
451 std::string f = i.fx()->sourceCurrency().code();
452 std::string d = i.fx()->targetCurrency().code();
453 if (isPseudoCurrency(f) || isPseudoCurrency(d)) {
454 simmProductClass_ = "Commodity";
455 scheduleProductClass_ = "Commodity";
456 // in terms of the asset class replacement we stick with FX for precious metals
457 // assetClassReplacement_ = "COMM";
458 }
459 }
460 } else if (!irIndices.empty() || !infIndices.empty()) {
461 simmProductClass_ = "RatesFX";
462 scheduleProductClass_ = "Rates";
463 } else {
464 simmProductClass_ = "RatesFx"; // fallback if we do not have any indices (an edge case really...)
465 scheduleProductClass_ = "Rates"; // fallback if we do not have any indices (an edge case really...)
466 }
467
468 if ((int)!eqIndices.empty() + (int)!fxIndices.empty() + (int)!commIndices.empty() > 1) {
469 WLOG("SIMM product class for hybrid trade is set to " << simmProductClass_);
470 WLOG("IM Schedule product class for hybrid trade is set to " << scheduleProductClass_);
471 assetClassReplacement_ = "HYBRID";
472 } else {
473 LOG("SIMM product class is set to " << simmProductClass_);
474 LOG("IM Schedule product class is set to " << scheduleProductClass_);
475 }
476}
bool isPseudoCurrency(const string &code)
check for pseudo currency = precious metal or crypto currency *‍/
Definition: parsers.cpp:318
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ populateModelParameters()

void populateModelParameters ( )
protected

Definition at line 478 of file scriptedtrade.cpp.

478 {
479 DLOG("Retrieve model and engine parameters using product tag '" << resolvedProductTag_ << "'");
480
481 // mandatory parameters
482
488
492
493 // optional parameters
494
495 zeroVolatility_ = parseBool(engineParameter("ZeroVolatility", {resolvedProductTag_}, false, "false"));
496 calibration_ = modelParameter("Calibration", {resolvedProductTag_}, false, "Deal");
497 useCg_ = parseBool(engineParameter("UseCG", {resolvedProductTag_}, false, "false"));
498 useAd_ = parseBool(engineParameter("UseAD", {resolvedProductTag_}, false, "false"));
500 parseBool(engineParameter("UseExternalComputeDevice", {resolvedProductTag_}, false, "false"));
502 parseBool(engineParameter("UseDoublePrecisionForExternalCalculation", {resolvedProductTag_}, false, "false"));
503 externalComputeDevice_ = engineParameter("ExternalComputeDevice", {}, false, "");
504 externalDeviceCompatibilityMode_ = parseBool(engineParameter("ExternalDeviceCompatibilityMode", {}, false, "false"));
505 includePastCashflows_ = parseBool(engineParameter("IncludePastCashflows", {resolvedProductTag_}, false, "false"));
506
507 // usage of ad or an external device implies usage of cg
509 useCg_ = true;
510
511 // default values for parameters that are only read for specific models
512
513 fullDynamicIr_ = false;
516 infModelType_ = "DK";
517 mesherEpsilon_ = 1.0E-4;
518 mesherScaling_ = 1.5;
521 mesherIsStatic_ = false;
522
523 // parameters only needed for certain model / engine pairs
524
525 DLOG("Retrieve model / engine specific parameters for " << modelParam_ << " / " << engineParam_);
526
527 if (modelParam_ == "GaussianCam") {
529 referenceCalibrationGrid_ = modelParameter("ReferenceCalibrationGrid", {resolvedProductTag_}, false, "");
531 infModelType_ = modelParameter("InfModelType", {resolvedProductTag_}, false, "DK");
532 } else if (modelParam_ == "LocalVolAndreasenHuge") {
534 parseListOfValues<Real>(engineParameter("CalibrationMoneyness", {resolvedProductTag_}), &parseReal);
535 }
536
537 if (engineParam_ == "MC") {
542 parseSequenceType(engineParameter("SequenceType", {resolvedProductTag_}, false, "SobolBrownianBridge"));
544 parsePolynomType(engineParameter("PolynomType", {resolvedProductTag_}, false, "Monomial"));
546 parseSequenceType(engineParameter("TrainingSequenceType", {resolvedProductTag_}, false, "MersenneTwister"));
548 engineParameter("SobolOrdering", {resolvedProductTag_}, false, "Steps"));
550 engineParameter("SobolDirectionIntegers", {resolvedProductTag_}, false, "JoeKuoD7"));
551 if (auto tmp = engineParameter("TrainingSamples", {resolvedProductTag_}, false, ""); !tmp.empty()) {
553 mcParams_.trainingSeed = parseInteger(engineParameter("TrainingSeed", {resolvedProductTag_}, false, "43"));
554 } else {
555 mcParams_.trainingSamples = Null<Size>();
556 }
558 parseRealOrNull(engineParameter("RegressionVarianceCutoff", {resolvedProductTag_}, false, std::string()));
560 } else if (engineParam_ == "FD") {
562 mesherEpsilon_ = parseReal(engineParameter("MesherEpsilon", {resolvedProductTag_}, false, "1.0E-4"));
563 mesherScaling_ = parseReal(engineParameter("MesherScaling", {resolvedProductTag_}, false, "1.5"));
564 mesherConcentration_ = parseReal(engineParameter("MesherConcentration", {resolvedProductTag_}, false, "0.1"));
566 parseInteger(engineParameter("MesherMaxConcentratingPoints", {resolvedProductTag_}, false, "9999"));
567 mesherIsStatic_ = parseBool(engineParameter("MesherIsStatic", {resolvedProductTag_}, false, "false"));
568 }
569
570 // global parameters that are relevant
571
572 calibrate_ = globalParameters_.count("Calibrate") == 0 || parseBool(globalParameters_.at("Calibrate"));
573
574 if (!calibrate_) {
575 DLOG("model calibration is disalbed in global pricing engine parameters");
576 }
577
578 continueOnCalibrationError_ = globalParameters_.count("ContinueOnCalibrationError") > 0 &&
579 parseBool(globalParameters_.at("ContinueOnCalibrationError"));
580
581 // sensitivity template
582
583 sensitivityTemplate_ = engineParameter("SensitivityTemplate", {resolvedProductTag_}, false, std::string());
584}
std::string modelParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
std::string engineParameter(const std::string &p, const std::vector< std::string > &qualifiers={}, const bool mandatory=true, const std::string &defaultValue="") const
SequenceType parseSequenceType(const std::string &s)
Convert string to sequence type.
Definition: parsers.cpp:668
QuantLib::LsmBasisSystem::PolynomialType parsePolynomType(const std::string &s)
Convert text to QuantLib::LsmBasisSystem::PolynomialType.
Definition: parsers.cpp:527
SobolRsg::DirectionIntegers parseSobolRsgDirectionIntegers(const std::string &s)
Convert text to QuantLib::SobolRsg::DirectionIntegers.
Definition: parsers.cpp:579
Real parseRealOrNull(const string &s)
Convert text to Real, empty string to Null<Real>()
Definition: parsers.cpp:120
Real parseReal(const string &s)
Convert text to Real.
Definition: parsers.cpp:112
SobolBrownianGenerator::Ordering parseSobolBrownianGeneratorOrdering(const std::string &s)
Convert text to QuantLib::SobolBrownianGenerator::Ordering.
Definition: parsers.cpp:567
Integer parseInteger(const string &s)
Convert text to QuantLib::Integer.
Definition: parsers.cpp:136
bool externalDeviceCompatibilityMode
Definition: model.hpp:56
QuantLib::Real regressionVarianceCutoff
Definition: model.hpp:61
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ populateFixingsMap()

void populateFixingsMap ( const IborFallbackConfig iborFallbackConfig)
protected

Definition at line 586 of file scriptedtrade.cpp.

586 {
587 DLOG("Populate fixing map");
588
589 // this might be a superset of the actually required fixings, since index evaluations with fwd date are also
590 // returned, in which case only future estimations are allowed
591
592 std::map<std::string, std::set<std::pair<Date, bool>>> indexFixings;
593
594 for (auto const& [name, fixings] : staticAnalyser_->probFixingDates()) {
595 for (auto const& d : fixings) {
596 indexFixings[name].insert(std::make_pair(d, true));
597 }
598 }
599
600 for (auto const& [name, fixings] : staticAnalyser_->indexEvalDates()) {
601 for (auto const& d : fixings) {
602 indexFixings[name].insert(std::make_pair(d, false));
603 }
604 }
605
606 for (auto const& [name, fixings] : indexFixings) {
607 IndexInfo i(name);
608 if (i.isComm()) {
609 // COMM indices require a special treatment, since they might need resolution
610 std::map<std::string, Size> stats;
611 for (auto const& [d, _] : fixings) {
612 auto idx = i.comm(d);
613 std::string name = idx->name();
614 fixings_[name].insert(idx->fixingCalendar().adjust(d, Preceding));
615 stats[name]++;
616 }
617 for (auto const& s : stats) {
618 DLOG("added " << s.second << " fixings for '" << s.first << "' (from eval op, prob fcts)");
619 }
620 } else {
621 // all other indices can be handled generically, notice for inf we include the scripting specific
622 // suffixes #L, #F in the index name, this is handled in the scripted trade builder when populating the
623 // required fixings
624
625 if (i.irIborFallback(iborFallbackConfig)) {
626 // well, except ibor fallback indices that we handle here...
627 Size nIbor = 0, nRfr = 0;
628 for (auto [d, _] : fixings) {
629 d = i.index()->fixingCalendar().adjust(d, Preceding);
630 if (d >= i.irIborFallback(iborFallbackConfig)->switchDate()) {
631 auto fd = i.irIborFallback(iborFallbackConfig)->onCoupon(d)->fixingDates();
632 fixings_[iborFallbackConfig.fallbackData(name).rfrIndex].insert(fd.begin(), fd.end());
633 nRfr += fd.size();
634 } else {
635 fixings_[i.name()].insert(d);
636 nIbor++;
637 }
638 }
639 DLOG("added " << nIbor << " Ibor and " << nRfr << " Rfr fixings for ibor fallback '" << i.name()
640 << "' (from eval op, prob fcts)");
641 } else if (i.irOvernightFallback(iborFallbackConfig)) {
642 Size nOis = 0, nRfr = 0;
643 for (auto [d, _] : fixings) {
644 d = i.index()->fixingCalendar().adjust(d, Preceding);
645 if (d >= i.irOvernightFallback(iborFallbackConfig)->switchDate()) {
646 fixings_[iborFallbackConfig.fallbackData(name).rfrIndex].insert(d);
647 nRfr++;
648 } else {
649 fixings_[i.name()].insert(d);
650 nOis++;
651 }
652 }
653 DLOG("added " << nOis << " OIS and " << nRfr << " Rfr fallback fixings for OIS fallback '" << i.name()
654 << "' (from eval op, prob fcts)");
655 } else {
656 // ... and all the others here:
657 IndexInfo imkt(name, market_);
658 for (const auto& [d, prob] : fixings) {
659 fixings_[i.name()].insert((prob ? imkt : i).index()->fixingCalendar().adjust(d, Preceding));
660 }
661 DLOG("added " << fixings.size() << " fixings for '" << i.name() << "' (from eval op, prob fcts)");
662 }
663 }
664 }
665
666 // add fixings from FWDCOMP(), FWDAVG()
667 for (auto const& f : staticAnalyser_->fwdCompAvgFixingDates()) {
668 QL_REQUIRE(IndexInfo(f.first).isIr(),
669 "FWD[COMP|AVG]() only supports IR ON indices, got '" << f.first << "' during fixing map population");
670 fixings_[f.first].insert(f.second.begin(), f.second.end());
671 DLOG("added " << f.second.size() << " fixings for '" << f.first << "' (from FWD[COMP|AVG]())");
672 }
673}
const std::map< std::string, std::set< Date > > & fixings() const
string name
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ extractPayCcys()

void extractPayCcys ( )
protected

Definition at line 675 of file scriptedtrade.cpp.

675 {
676 DLOG("Extract pay ccys and determine the model's base ccy");
677 for (auto const& c : staticAnalyser_->payObsDates()) {
678 payCcys_.insert(c.first);
679 DLOG("got pay currency " << c.first);
680 }
681}
+ Here is the caller graph for this function:

◆ determineBaseCcy()

void determineBaseCcy ( )
protected

Definition at line 683 of file scriptedtrade.cpp.

683 {
684 std::set<std::string> baseCcyCandidates;
685
686 // candidates are target currencies from the fx indices
687 for (auto const& i : fxIndices_) {
688 std::string ccy = i.fx()->targetCurrency().code();
689 baseCcyCandidates.insert(ccy);
690 DLOG("add base ccy candidate " << ccy << " from " << i);
691 }
692
693 // add pay currencies as base ccy canditate only if there are no candidates from the fx indices
694 if (baseCcyCandidates.empty()) {
695 for (auto const& p : payCcys_) {
696 baseCcyCandidates.insert(p);
697 DLOG("add base ccy candidate " << p << " from pay ccys");
698 }
699 }
700
701 // if there is only one candidate and we do not enforce the base ccy from the model parameters we take that,
702 // otherweise the base ccy from the model parameters
703
704 if (baseCcyCandidates.size() == 1 && !enforceBaseCcy_) {
705 baseCcy_ = *baseCcyCandidates.begin();
706 } else {
708 }
709
710 DLOG("base ccy is " << baseCcy_
711 << (amcCam_ != nullptr ? "(this choice might be overwritten below for AMC builders)" : ""));
712}
+ Here is the caller graph for this function:

◆ compileModelCcyList()

void compileModelCcyList ( )
protected

Definition at line 732 of file scriptedtrade.cpp.

732 {
733 std::set<std::string> tmpCcys;
734 tmpCcys.insert(baseCcy_);
735
736 DLOG("Compile the model currencies list");
737
738 for (auto const& c : payCcys_) {
739 tmpCcys.insert(c);
740 }
741
742 for (auto const& i : fxIndices_) {
743 std::string f = i.fx()->sourceCurrency().code();
744 std::string d = i.fx()->targetCurrency().code();
745 tmpCcys.insert(f);
746 tmpCcys.insert(d);
747 }
748
749 // ir index currencies are only added for the cam model, for bs or local vol they are not needed
750 // inf index currencies are not needed for the dk in the cam model, but for jy they are
751 if (modelParam_ == "GaussianCam") {
752 for (auto const& i : irIndices_)
753 tmpCcys.insert(i.ir()->currency().code());
754 if (infModelType_ == "DK") {
755 for (auto const& i : infIndices_)
756 tmpCcys.insert(i.inf()->currency().code());
757 }
758 }
759
760 // we only add eqCurrencies / comCurrencies to the modelCcys if we
761 // - build the GaussianCam model which requires all relevant currencies to be present
762 // - or require a dynamic FX process for each currency
763 // In case we build a GaussianCam and fullDynamicIr_ = false, there will be a zero vol process set up
764 // for the IR component though, if there is no requirement for the currency from an IR index.
765 // If fullDynamicFx_ = false the FX components for that currency will be zero vol, too, if there is no
766 // FX index requiring the ccy. See buildGaussianCam().
767 if (fullDynamicFx_ || modelParam_ == "GaussianCam") {
768 for (auto const& e : eqIndices_) {
769 tmpCcys.insert(getEqCcy(e));
770 }
771 for (auto const& c : commIndices_) {
772 tmpCcys.insert(getCommCcy(c));
773 }
774 }
775
776 // if we build an AMC builder, we set the base ccy to the amc model base ccy, otherwise we won't have the
777 // required FX spot processes in the projected model we use for the scripted trade; the only exception is
778 // if we have only one ccy in the final scripted trade model anyway (i.e. only one IR process), in which
779 // case we can go with that one currency and don't need a more complicated model
780 if (amcCam_ != nullptr) {
781 std::string newBaseCcy_ = amcCam_->ir(0)->currency().code();
782 if (newBaseCcy_ == baseCcy_) {
783 DLOG("base ccy and AMC model base ccy are identical (" << baseCcy_ << ")");
784 } else {
785 if (tmpCcys.size() > 1) {
786 DLOG("base ccy " << baseCcy_ << " is overwritten with AMC model base ccy " << newBaseCcy_
787 << ", since more than one ccy is needed in the final model.");
788 baseCcy_ = newBaseCcy_;
789 } else {
790 DLOG("base ccy " << baseCcy_ << " is kept although AMC model base ccy is different (" << newBaseCcy_
791 << "), because it is a single currency model");
792 }
793 }
794 }
795
796 // build currency vector with the base ccy at the front
797 modelCcys_ = std::vector<std::string>(1, baseCcy_);
798 for (auto const& c : tmpCcys)
799 if (c != baseCcy_)
800 modelCcys_.push_back(c);
801
802 // log ccys
803 for (auto const& c : modelCcys_)
804 DLOG("model ccy " << c << " added");
805}
std::string getCommCcy(const IndexInfo &e)
std::string getEqCcy(const IndexInfo &e)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compileModelIndexLists()

void compileModelIndexLists ( )
protected

Definition at line 807 of file scriptedtrade.cpp.

807 {
808 for (auto const& i : eqIndices_) {
809 modelIndices_.push_back(i.name());
810 modelIndicesCurrencies_.push_back(getEqCcy(i));
811 DLOG("added model index " << modelIndices_.back());
812 }
813
814 for (auto const& i : commIndices_) {
815 modelIndices_.push_back(i.name());
817 DLOG("added model index " << modelIndices_.back());
818 }
819
820 // cover the ccys from the actual fx indices
821 std::set<std::string> coveredCcys;
822 coveredCcys.insert(baseCcy_);
823 for (auto const& i : fxIndices_) {
824 std::string targetCcy = i.fx()->targetCurrency().code();
825 std::string sourceCcy = i.fx()->sourceCurrency().code();
826 if (sourceCcy != baseCcy_ &&
827 std::find(coveredCcys.begin(), coveredCcys.end(), sourceCcy) == coveredCcys.end()) {
828 modelIndices_.push_back("FX-GENERIC-" + sourceCcy + "-" + baseCcy_);
829 modelIndicesCurrencies_.push_back(sourceCcy);
830 coveredCcys.insert(sourceCcy);
831 DLOG("added model index " << modelIndices_.back());
832 }
833 if (targetCcy != baseCcy_ &&
834 std::find(coveredCcys.begin(), coveredCcys.end(), targetCcy) == coveredCcys.end()) {
835 modelIndices_.push_back("FX-GENERIC-" + targetCcy + "-" + baseCcy_);
836 modelIndicesCurrencies_.push_back(targetCcy);
837 coveredCcys.insert(targetCcy);
838 DLOG("added model index " << modelIndices_.back());
839 }
840 }
841
842 // cover the remaining model currencies, if we require this via the fullDynamicFx parameter
843 if (fullDynamicFx_) {
844 for (Size i = 1; i < modelCcys_.size(); ++i) {
845 if (std::find(coveredCcys.begin(), coveredCcys.end(), modelCcys_[i]) == coveredCcys.end()) {
846 modelIndices_.push_back("FX-GENERIC-" + modelCcys_[i] + "-" + baseCcy_);
848 coveredCcys.insert(modelCcys_[i]);
849 DLOG("added model index " << modelIndices_.back() << " (since fullDynamicFx = true)");
850 }
851 }
852 }
853
854 for (auto const& i : irIndices_) {
855 if (i.irSwap())
856 modelIrIndices_.push_back(
857 std::make_pair(i.name(), *market_->swapIndex(i.name(), configuration(MarketContext::pricing))));
858 else
859 modelIrIndices_.push_back(
860 std::make_pair(i.name(), *market_->iborIndex(i.name(), configuration(MarketContext::pricing))));
861 DLOG("added model ir index " << i.name());
862 }
863
864 for (auto const& i : infIndices_) {
865 modelInfIndices_.push_back(
866 std::make_pair(i.name(), *market_->zeroInflationIndex(i.infName(), configuration(MarketContext::pricing))));
867 DLOG("added model inf index " << i.name());
868 }
869}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setupCorrelations()

void setupCorrelations ( )
protected

Definition at line 871 of file scriptedtrade.cpp.

871 {
872
873 if (zeroVolatility_) {
874 DLOG("skipping correlation setup because we are using zero volatility");
875 return;
876 }
877
878 // collect pairs of model index names and correlation curve lookup names
879 std::set<std::pair<std::string, std::string>> tmp;
880
881 // EQ, FX, COMM indices
882 for (auto const& m : modelIndices_) {
883 IndexInfo ind(m);
884 if (ind.isComm()) {
885 // for COMM indices we expect the correlation on the COMM name level (not on single futures)
886 // notice we might have different COMM indices on the same name (via spot, future, dynamic future
887 // reference) - for those the correlationCurve() call below will return a constant 1.0 correlation
888 tmp.insert(std::make_pair(m, "COMM-" + ind.commName()));
889 } else {
890 // for EQ, FX the lookup name is the same as the model index name
891 tmp.insert(std::make_pair(m, m));
892 }
893 }
894
895 // need the ir, inf indices only for GaussianCam
896 if (modelParam_ == "GaussianCam") {
897 for (auto const& irIdx : modelIrIndices_) {
898 // for IR the lookup name is the same as the model index name
899 tmp.insert(std::make_pair(irIdx.first, irIdx.first));
900 }
901 for (auto const& infIdx : modelInfIndices_) {
902 // for INF the lookup name is without the #L, #F suffix
903 IndexInfo ind(infIdx.first);
904 tmp.insert(std::make_pair(infIdx.first, ind.infName()));
905 }
906 }
907
908 DLOG("adding correlations for indices:");
909 for (auto const& n : tmp)
910 DLOG("model index '" << n.first << "' lookup name '" << n.second << "'");
911
912 std::vector<std::pair<std::string, std::string>> corrModelIndices(tmp.begin(), tmp.end());
913
914 for (Size i = 0; i < corrModelIndices.size(); ++i) {
915 for (Size j = 0; j < i; ++j) {
916 try {
917 correlations_[std::make_pair(corrModelIndices[i].first, corrModelIndices[j].first)] =
918 correlationCurve(corrModelIndices[i].second, corrModelIndices[j].second);
919 DLOG("added correlation for " << corrModelIndices[j].second << " ~ " << corrModelIndices[i].second);
920 } catch (const std::exception& e) {
921 WLOG("no correlation provided for " << corrModelIndices[j].second << " ~ " << corrModelIndices[i].second
922 << "(" << e.what() << ")");
923 }
924 }
925 }
926}
virtual QuantLib::Handle< QuantExt::CorrelationTermStructure > correlationCurve(const std::string &index1, const std::string &index2)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setLastRelevantDate()

void setLastRelevantDate ( )
protected

Definition at line 928 of file scriptedtrade.cpp.

928 {
929 lastRelevantDate_ = Date::minDate();
930 for (auto const& s : staticAnalyser_->indexEvalDates())
931 for (auto const& d : s.second)
933 for (auto const& d : staticAnalyser_->regressionDates())
935 for (auto const& s : staticAnalyser_->payObsDates())
936 for (auto const& d : s.second)
938 for (auto const& s : staticAnalyser_->payPayDates())
939 for (auto const& d : s.second)
941 for (auto const& s : staticAnalyser_->discountObsDates())
942 for (auto const& d : s.second)
944 for (auto const& s : staticAnalyser_->discountPayDates())
945 for (auto const& d : s.second)
947 DLOG("last relevant date: " << lastRelevantDate_);
948}
+ Here is the caller graph for this function:

◆ setupBlackScholesProcesses()

void setupBlackScholesProcesses ( )
protectedvirtual

Definition at line 950 of file scriptedtrade.cpp.

950 {
951 Handle<BlackVolTermStructure> vol;
952 if (zeroVolatility_) {
953 vol = Handle<BlackVolTermStructure>(
954 QuantLib::ext::make_shared<BlackConstantVol>(0, NullCalendar(), 0.0, ActualActual(ActualActual::ISDA)));
955 DLOG("using zero volatility processes");
956 }
957 for (Size i = 0; i < modelIndices_.size(); ++i) {
958 IndexInfo ind(modelIndices_[i]);
959 if (ind.isEq()) {
960 std::string name = ind.eq()->name();
961 auto spot = market_->equitySpot(name, configuration(MarketContext::pricing));
962 auto div = market_->equityDividendCurve(name, configuration(MarketContext::pricing));
963 auto fc = market_->equityForecastCurve(name, configuration(MarketContext::pricing));
964 if (!zeroVolatility_)
966 processes_.push_back(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(spot, div, fc, vol));
967 DLOG("added process for equity " << name);
968 } else if (ind.isComm()) {
969 std::string name = ind.commName();
970 auto spot = Handle<Quote>(QuantLib::ext::make_shared<DerivedPriceQuote>(
971 market_->commodityPriceCurve(name, configuration(MarketContext::pricing))));
972 auto priceCurve = market_->commodityPriceCurve(name, configuration(MarketContext::pricing));
974 auto div = Handle<YieldTermStructure>(QuantLib::ext::make_shared<PriceTermStructureAdapter>(*priceCurve, *fc));
975 div->enableExtrapolation();
976 if (!zeroVolatility_)
977 vol = market_->commodityVolatility(name, configuration(MarketContext::pricing));
978 processes_.push_back(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(spot, div, fc, vol));
979 DLOG("added process for commodity " << name);
980 } else if (ind.isFx()) {
981 std::string targetCcy = ind.fx()->targetCurrency().code();
982 std::string sourceCcy = ind.fx()->sourceCurrency().code();
983 auto spot = market_->fxSpot(sourceCcy + targetCcy, configuration(MarketContext::pricing));
984 auto div = market_->discountCurve(sourceCcy, configuration(MarketContext::pricing));
985 auto fc = market_->discountCurve(targetCcy, configuration(MarketContext::pricing));
986 if (!zeroVolatility_)
987 vol = market_->fxVol(sourceCcy + targetCcy, configuration(MarketContext::pricing));
988 processes_.push_back(QuantLib::ext::make_shared<GeneralizedBlackScholesProcess>(spot, div, fc, vol));
989 DLOG("added process for fx " << sourceCcy << "-" << targetCcy);
990 } else {
991 QL_FAIL("unexpected model index " << ind);
992 }
993 }
994}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setupIrReversions()

void setupIrReversions ( )
protected

Definition at line 996 of file scriptedtrade.cpp.

996 {
997 if (zeroVolatility_) {
998 DLOG("skipping IR reversion setup because we are using zero volatility");
999 return;
1000 }
1001 // get reversions for ir index currencies ...
1002 std::set<std::string> irCcys;
1003 for (auto const& i : irIndices_)
1004 irCcys.insert(i.ir()->currency().code());
1005 // ... or all currencies if we require dynamic processes for all
1006 if (fullDynamicIr_) {
1007 irCcys.insert(modelCcys_.begin(), modelCcys_.end());
1008 }
1009 for (auto const& ccy : irCcys) {
1010 string revStr = modelParameter("IrReversion_" + ccy, {resolvedProductTag_}, false, "");
1011 if (revStr.empty())
1012 revStr = modelParameter("IrReversion", {resolvedProductTag_}, false, "");
1013 QL_REQUIRE(!revStr.empty(), "Did not find reversion for "
1014 << ccy
1015 << ", need IrReversion_CCY or IrReversion parameter in pricing engine config.");
1016 irReversions_[ccy] = parseReal(revStr);
1017 DLOG("got Hull White reversion " << irReversions_[ccy] << " for " << ccy);
1018 }
1019}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ compileSimulationAndAddDates()

void compileSimulationAndAddDates ( )
protected

Definition at line 1034 of file scriptedtrade.cpp.

1034 {
1035 DLOG("compile simulation and additional dates...");
1036
1037 for (auto const& s : staticAnalyser_->indexEvalDates()) {
1038 IndexInfo info(s.first);
1039 // skip generic indices, for them we do not to add the obs date to sim or add dates
1040 if (info.isGeneric())
1041 continue;
1042 // need ir / inf index observation dates only for GaussianCam as simulation dates, for LocalVol, BS
1043 // we don't need to add them at all
1044 if ((!info.isIr() && !info.isInf()) || modelParam_ == "GaussianCam") {
1045 if (info.isInf()) {
1046 // inf needs special considerations
1047 QuantLib::ext::shared_ptr<ZeroInflationIndex> marketIndex = getInfMarketIndex(info.name(), modelInfIndices_);
1048 Size lag = getInflationSimulationLag(marketIndex);
1049 for (auto const& d : s.second) {
1050 auto lim = inflationPeriod(d, info.inf()->frequency());
1051 simulationDates_.insert(lim.first + lag);
1052 QL_DEPRECATED_DISABLE_WARNING
1053 // This will be removed in a later release and all inf indices are then flat
1054 if (info.inf()->interpolated())
1055 simulationDates_.insert(d + lag);
1056 QL_DEPRECATED_ENABLE_WARNING
1057 }
1058 } else {
1059 // for all other indices we just take the original dates
1060 simulationDates_.insert(s.second.begin(), s.second.end());
1061 }
1062 DLOG("added " << s.second.size() << " simulation dates for '" << s.first << "' (from eval op obs dates)");
1063 }
1064 }
1065
1066 for (auto const& s : staticAnalyser_->indexFwdDates()) {
1067 IndexInfo info(s.first);
1068 // do not need ir / inf index fwd dates (not for LocalVol, BS, but also not for GaussianCam)
1069 if (!info.isIr() && !info.isInf()) {
1070 addDates_.insert(s.second.begin(), s.second.end());
1071 DLOG("added " << s.second.size() << " additional dates for '" << s.first << "' (from eval op fwd dates)");
1072 }
1073 }
1074
1075 for (auto const& s : staticAnalyser_->payObsDates()) {
1076 // need pay obs dates as simulation dates only for GaussianCam, for Local Vol, BS
1077 // add them as addDaes except the pay ccy is not base and there is an fx index with
1078 // the pay ccy as for ccy (then the simulated fx index will be used for ccy conversion)
1079 std::string payCcy = s.first;
1080 if (modelParam_ == "GaussianCam" ||
1081 (baseCcy_ != payCcy &&
1082 std::find_if(modelIndices_.begin(), modelIndices_.end(), [&payCcy](const std::string& s) {
1083 IndexInfo ind(s);
1084 return ind.isFx() && ind.fx()->sourceCurrency().code() == payCcy;
1085 }) != modelIndices_.end())) {
1086 simulationDates_.insert(s.second.begin(), s.second.end());
1087 DLOG("added " << s.second.size() << " simulation dates for '" << payCcy << "' (from pay() obs dates)");
1088 } else {
1089 addDates_.insert(s.second.begin(), s.second.end());
1090 DLOG("added " << s.second.size() << " additional dates for '" << payCcy << "' (from pay() obs dates)");
1091 }
1092 }
1093
1094 simulationDates_.insert(staticAnalyser_->regressionDates().begin(), staticAnalyser_->regressionDates().end());
1095 DLOG("added " << staticAnalyser_->regressionDates().size() << " simulation dates (from npv() regression dates)");
1096
1097 for (auto const& s : staticAnalyser_->payPayDates()) {
1098 addDates_.insert(s.second.begin(), s.second.end());
1099 DLOG("added " << s.second.size() << " additional dates for '" << s.first << "' (from pay() pay dates)");
1100 }
1101
1102 for (auto const& s : staticAnalyser_->discountObsDates()) {
1103 // need disocunt obs dates only for GaussianCam as simulation dates, for Local Vol, BS
1104 // add them as addDates
1105 if (modelParam_ == "GaussianCam") {
1106 simulationDates_.insert(s.second.begin(), s.second.end());
1107 DLOG("added " << s.second.size() << " simulation dates for '" << s.first
1108 << "' (from discount() obs dates)");
1109 } else {
1110 addDates_.insert(s.second.begin(), s.second.end());
1111 DLOG("added " << s.second.size() << " additional dates for '" << s.first
1112 << "' (from discount() obs dates)");
1113 }
1114 DLOG("added " << s.second.size() << " additional dates for '" << s.first << "' (from discount() obs dates)");
1115 }
1116
1117 for (auto const& s : staticAnalyser_->discountPayDates()) {
1118 addDates_.insert(s.second.begin(), s.second.end());
1119 DLOG("added " << s.second.size() << " additional dates for '" << s.first << "' (from discount() pay dates)");
1120 }
1121
1122 for (auto const& s : staticAnalyser_->fwdCompAvgEvalDates()) {
1123 // need fwd comp eval dates only for GaussianCam as simulation dates, for Local Vol, BS
1124 // add them as addDates
1125 if (modelParam_ == "GaussianCam") {
1126 simulationDates_.insert(s.second.begin(), s.second.end());
1127 DLOG("added " << s.second.size() << " simulation dates for '" << s.first
1128 << "' (from fwd[Comp|Avg]() obs dates)");
1129 } else {
1130 addDates_.insert(s.second.begin(), s.second.end());
1131 DLOG("added " << s.second.size() << " additional dates for '" << s.first
1132 << "' (from fwd[Comp|Avg]() obs dates)");
1133 }
1134 }
1135
1136 for (auto const& s : staticAnalyser_->fwdCompAvgStartEndDates()) {
1137 addDates_.insert(s.second.begin(), s.second.end());
1138 DLOG("added " << s.second.size() << " additional dates for '" << s.first
1139 << "' (from fwd[Comp|Avg]() start/end dates)");
1140 }
1141}
Size getInflationSimulationLag(const QuantLib::ext::shared_ptr< ZeroInflationIndex > &index)
Definition: utilities.cpp:660
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildBlackScholes()

void buildBlackScholes ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig 
)
protected

Definition at line 1199 of file scriptedtrade.cpp.

1200 {
1201 Real T = modelCurves_.front()->timeFromReference(lastRelevantDate_);
1202 auto filteredStrikes = filterBlackScholesCalibrationStrikes(calibrationStrikes_, modelIndices_, processes_, T);
1203 // ignore timeStepsPerYear if we have no correlations, i.e. we can take large timesteps without changing anything
1204 auto builder = QuantLib::ext::make_shared<BlackScholesModelBuilder>(
1206 calibration_, getCalibrationStrikesVector(filteredStrikes, modelIndices_));
1207 if (useCg_) {
1208 modelCG_ = QuantLib::ext::make_shared<BlackScholesCG>(
1210 modelIndicesCurrencies_, builder->model(), correlations_, simulationDates_, iborFallbackConfig,
1211 calibration_, filteredStrikes);
1212 } else {
1213 model_ = QuantLib::ext::make_shared<BlackScholes>(modelSize_, modelCcys_, modelCurves_, modelFxSpots_, modelIrIndices_,
1215 builder->model(), correlations_, mcParams_, simulationDates_,
1216 iborFallbackConfig, calibration_, filteredStrikes);
1217 }
1218 modelBuilders_.insert(std::make_pair(id, builder));
1219}
set< std::pair< string, QuantLib::ext::shared_ptr< QuantExt::ModelBuilder > > > modelBuilders_
+ Here is the caller graph for this function:

◆ buildFdBlackScholes()

void buildFdBlackScholes ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig 
)
protected

Definition at line 1221 of file scriptedtrade.cpp.

1222 {
1223 Real T = modelCurves_.front()->timeFromReference(lastRelevantDate_);
1224 auto filteredStrikes = filterBlackScholesCalibrationStrikes(calibrationStrikes_, modelIndices_, processes_, T);
1225 auto builder = QuantLib::ext::make_shared<BlackScholesModelBuilder>(
1227 getCalibrationStrikesVector(filteredStrikes, modelIndices_));
1228 model_ = QuantLib::ext::make_shared<FdBlackScholesBase>(
1230 modelIndicesCurrencies_, payCcys_, builder->model(), correlations_, simulationDates_, iborFallbackConfig,
1233 modelBuilders_.insert(std::make_pair(id, builder));
1234}
+ Here is the caller graph for this function:

◆ buildLocalVol()

void buildLocalVol ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig 
)
protected

Definition at line 1236 of file scriptedtrade.cpp.

1236 {
1238 if (modelParam_ == "LocalVolDupire")
1240 else if (modelParam_ == "LocalVolAndreasenHuge")
1242 else {
1243 QL_FAIL("local vol model type " << modelParam_ << " not recognised.");
1244 }
1245 auto builder = QuantLib::ext::make_shared<LocalVolModelBuilder>(modelCurves_, processes_, simulationDates_, addDates_,
1248 model_ = QuantLib::ext::make_shared<LocalVol>(modelSize_, modelCcys_, modelCurves_, modelFxSpots_, modelIrIndices_,
1250 correlations_, mcParams_, simulationDates_, iborFallbackConfig);
1251 modelBuilders_.insert(std::make_pair(id, builder));
1252}
+ Here is the caller graph for this function:

◆ buildGaussianCam()

void buildGaussianCam ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig,
const std::vector< std::string > &  conditionalExpectationModelStates 
)
protected

Definition at line 1267 of file scriptedtrade.cpp.

1268 {
1269 // compile cam correlation matrix
1270 // - we want to use the maximum tenor of an ir index in a correlation pair if several are given (to have
1271 // a well defined rule how to derive the LGM IR correlations); to get there we store the correlations
1272 // together with the index tenors (or null if not applicatble), so that we can decide if we overwrite
1273 // an existing correlation with another candidate or not
1274 // - correlations are for index pair names and must be constant; if not given for a pair, we assume zero
1275 // correlation;
1276 // - correlations for IR processes are taken from IR index correlations, if several indices exist
1277 // for one ccy, the index with the longest tenor T is selected; we do not apply an LGM adjustment for this
1278 // value due to time dependent volatility, since this is usually negligible
1279 // - for inf we do not apply an adjustment either => TODO is that suitable for both DK and JY approximately?
1280 // - for inf JY we have two driving factors (f1,f2) where f1 drives the real rate process and f2 drives the
1281 // inflation index ("fx") process; we assume the correlation between f1 and any other factor (including f2)
1282 // to be zero and set the correlation between f2 and any other factor to the correlation read from the
1283 // market data for the inflation index, TODO is that assumption reasonable?
1284 std::map<std::pair<std::string, std::string>,
1285 std::tuple<Handle<QuantExt::CorrelationTermStructure>, Period, Period>>
1286 tmpCorrelations;
1287 for (auto const& c : correlations_) {
1288 std::pair<std::string, Period> firstEntry = convertIndexToCamCorrelationEntry(c.first.first);
1289 std::pair<std::string, Period> secondEntry = convertIndexToCamCorrelationEntry(c.first.second);
1290 // if we have identical CAM entries (e.g. IR:EUR, IR:EUR) we skip this pair, since we can't specify a
1291 // correlation in this case
1292 if (firstEntry.first == secondEntry.first)
1293 continue;
1294 auto e = tmpCorrelations.find(std::make_pair(firstEntry.first, secondEntry.first));
1295 if (e == tmpCorrelations.end() ||
1296 (firstEntry.second > std::get<1>(e->second) && secondEntry.second > std::get<2>(e->second))) {
1297 tmpCorrelations[std::make_pair(firstEntry.first, secondEntry.first)] =
1298 std::make_tuple(c.second, firstEntry.second, secondEntry.second);
1299 }
1300 }
1301
1302 map<CorrelationKey, Handle<Quote>> camCorrelations;
1303 for (auto const& c : tmpCorrelations) {
1304 CorrelationFactor f_1 = parseCorrelationFactor(c.first.first, '#');
1305 CorrelationFactor f_2 = parseCorrelationFactor(c.first.second, '#');
1306 // update index for JY from 0 to 1 (i.e. to the factor driving the inf index ("fx") process)
1307 // in all other cases the index 0 is fine, since there is only one driving factor always
1308 if (infModelType_ == "JY") {
1309 if (f_1.type == CrossAssetModel::AssetType::INF)
1310 f_1.index = 1;
1311 if (f_2.type == CrossAssetModel::AssetType::INF)
1312 f_2.index = 1;
1313 }
1314 auto q = Handle<Quote>(QuantLib::ext::make_shared<CorrelationValue>(std::get<0>(c.second), 0.0));
1315 camCorrelations[std::make_pair(f_1, f_2)] = q;
1316 DLOG("added correlation for " << c.first.first << "/" << c.first.second << ": " << q->value());
1317 }
1318
1319 // correlation overwrite from pricing engine parameters
1320
1321 std::set<CorrelationFactor> allCorrRiskFactors;
1322
1323 for (auto const& m : modelIndices_)
1324 allCorrRiskFactors.insert(parseCorrelationFactor(convertIndexToCamCorrelationEntry(m).first, '#'));
1325 for (auto const& m : modelIrIndices_)
1326 allCorrRiskFactors.insert(parseCorrelationFactor(convertIndexToCamCorrelationEntry(m.first).first, '#'));
1327 for (auto const& m : modelInfIndices_)
1328 allCorrRiskFactors.insert(parseCorrelationFactor(convertIndexToCamCorrelationEntry(m.first).first, '#'));
1329 for (auto const& ccy : modelCcys_)
1330 allCorrRiskFactors.insert({CrossAssetModel::AssetType::IR, ccy, 0});
1331
1332 for (auto const& c1 : allCorrRiskFactors) {
1333 for (auto const& c2 : allCorrRiskFactors) {
1334 // determine the number of driving factors for f_1 and f_2
1335 Size nf_1 = c1.type == CrossAssetModel::AssetType::INF && infModelType_ == "JY" ? 2 : 1;
1336 Size nf_2 = c2.type == CrossAssetModel::AssetType::INF && infModelType_ == "JY" ? 2 : 1;
1337 for (Size k = 0; k < nf_1; ++k) {
1338 for (Size l = 0; l < nf_2; ++l) {
1339 auto f_1 = c1;
1340 auto f_2 = c2;
1341 f_1.index = k;
1342 f_2.index = l;
1343 if (f_1 == f_2)
1344 continue;
1345 // lookup names are IR:GBP:0 and IR:GBP whenever the index is zero
1346 auto s_1 = ore::data::to_string(f_1);
1347 auto s_2 = ore::data::to_string(f_2);
1348 std::set<std::string> lookupnames1, lookupnames2;
1349 lookupnames1.insert(s_1);
1350 lookupnames2.insert(s_2);
1351 if (k == 0)
1352 lookupnames1.insert(s_1.substr(0, s_1.size() - 2));
1353 if (l == 0)
1354 lookupnames2.insert(s_2.substr(0, s_2.size() - 2));
1355 for (auto const& l1 : lookupnames1) {
1356 for (auto const& l2 : lookupnames2) {
1357 if (auto overwrite = modelParameter(
1358 "Correlation",
1359 {resolvedProductTag_ + "_" + l1 + "_" + l2, l1 + "_" + l2, resolvedProductTag_},
1360 false);
1361 !overwrite.empty()) {
1362 camCorrelations[std::make_pair(f_1, f_2)] =
1363 Handle<Quote>(QuantLib::ext::make_shared<SimpleQuote>(parseReal(overwrite)));
1364 }
1365 }
1366 }
1367 }
1368 }
1369 }
1370 }
1371
1372 // set up the cam and calibrate it using the cam builder
1373 // if for a non-base currency no fx index is given, we set up a zero vol FX process for this
1374 // if fullDynamicIr is false, we set up a zero vol IR process for currencies that are not irIndex currencies
1375
1376 std::vector<QuantLib::ext::shared_ptr<IrModelData>> irConfigs;
1377 std::vector<QuantLib::ext::shared_ptr<InflationModelData>> infConfigs;
1378 std::vector<QuantLib::ext::shared_ptr<FxBsData>> fxConfigs;
1379 std::vector<QuantLib::ext::shared_ptr<EqBsData>> eqConfigs;
1380 std::vector<QuantLib::ext::shared_ptr<CommoditySchwartzData>> comConfigs;
1381
1382 // calibration expiries and terms for IR, INF, FX, EQ parametrisations (this will only work for a fixed reference
1383 // date, due to the way the cam builder and nested builders work, see ticket #940)
1384 Date referenceDate = modelCurves_.front()->referenceDate();
1385 std::vector<Date> calibrationDates;
1386 std::vector<std::string> calibrationExpiries, calibrationTerms;
1387
1388 for (auto const& d : simulationDates_) {
1389 if (d > referenceDate) {
1390 calibrationDates.push_back(d);
1391 calibrationExpiries.push_back(ore::data::to_string(d));
1392 // make sure the underlying swap has at least 1M to run, QL will throw otherwise during calibration
1393 calibrationTerms.push_back(ore::data::to_string(std::max(d + 1 * Months, lastRelevantDate_)));
1394 }
1395 }
1396
1397 // calibration times (need one less than calibration dates)
1398 std::vector<Real> calibrationTimes;
1399 for (Size i = 0; i + 1 < calibrationDates.size(); ++i) {
1400 calibrationTimes.push_back(modelCurves_.front()->timeFromReference(calibrationDates[i]));
1401 }
1402
1403 // IR configs
1404 for (Size i = 0; i < modelCcys_.size(); ++i) {
1405 auto config = QuantLib::ext::make_shared<IrLgmData>();
1406 config->qualifier() = getFirstIrIndexOrCcy(modelCcys_[i], irIndices_);
1407 config->reversionType() = LgmData::ReversionType::HullWhite;
1408 config->volatilityType() = LgmData::VolatilityType::Hagan;
1409 config->calibrateH() = false;
1410 config->hParamType() = ParamType::Constant;
1411 config->hTimes() = std::vector<Real>();
1412 config->shiftHorizon() =
1413 modelCurves_.front()->timeFromReference(lastRelevantDate_) * 0.5; // TODO hardcode 0.5 here?
1414 config->scaling() = 1.0;
1415 std::string ccy = modelCcys_[i];
1416 // if we don't require fullDynamicIr and there is no model index in the currency, we set up a zero
1417 // vol IR component for this ccy; we also do this if zero vol is specified in the model params
1418 if (calibrationExpiries.empty() || zeroVolatility_ ||
1419 (!fullDynamicIr_ &&
1420 std::find_if(modelIrIndices_.begin(), modelIrIndices_.end(),
1421 [&ccy](const std::pair<std::string, QuantLib::ext::shared_ptr<InterestRateIndex>>& index) {
1422 return index.second->currency().code() == ccy;
1423 }) == modelIrIndices_.end())) {
1424
1425 DLOG("set up zero vol IrLgmData for currency '" << modelCcys_[i] << "'");
1426 // zero vol
1427 config->calibrationType() = CalibrationType::None;
1428 config->hValues() = {0.0};
1429 config->calibrateA() = false;
1430 config->aParamType() = ParamType::Constant;
1431 config->aTimes() = std::vector<Real>();
1432 config->aValues() = {0.0};
1433 } else {
1434 DLOG("set up IrLgmData for currency '" << modelCcys_[i] << "'");
1435 // bootstrapped on atm swaption vols
1436 auto rev = irReversions_.find(modelCcys_[i]);
1437 QL_REQUIRE(rev != irReversions_.end(), "reversion for ccy " << modelCcys_[i] << " not found");
1438 config->calibrationType() = CalibrationType::Bootstrap;
1439 config->hValues() = {rev->second};
1440 config->calibrateA() = true;
1441 config->aParamType() = ParamType::Piecewise;
1442 config->aTimes() = calibrationTimes;
1443 config->aValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.0030); // start value for optimiser
1444 config->optionExpiries() = calibrationExpiries;
1445 config->optionTerms() = calibrationTerms;
1446 config->optionStrikes() =
1447 std::vector<std::string>(calibrationExpiries.size(), "ATM"); // hardcoded ATM calibration strike
1448 }
1449 irConfigs.push_back(config);
1450 }
1451
1452 // INF configs
1453 for (Size i = 0; i < modelInfIndices_.size(); ++i) {
1454 QuantLib::ext::shared_ptr<InflationModelData> config;
1455 if (zeroVolatility_) {
1456 // for both DK and JY we can just use a zero vol dk component
1457 config = QuantLib::ext::make_shared<InfDkData>(
1458 CalibrationType::None, std::vector<CalibrationBasket>(), modelInfIndices_[i].second->currency().code(),
1459 IndexInfo(modelInfIndices_[i].first).infName(),
1460 ReversionParameter(LgmData::ReversionType::Hagan, true, ParamType::Constant, {}, {0.60}),
1461 VolatilityParameter(LgmData::VolatilityType::Hagan, false, ParamType::Constant, {}, {0.00}),
1462 LgmReversionTransformation(), true);
1463 } else {
1464 // build calibration basket (CPI Floors at calibration strike or if that is not given, ATM strike)
1465 QuantLib::ext::shared_ptr<BaseStrike> calibrationStrike;
1466 if (auto k = calibrationStrikes_.find(modelInfIndices_[i].first);
1467 k != calibrationStrikes_.end() && !k->second.empty()) {
1468 calibrationStrike = QuantLib::ext::make_shared<AbsoluteStrike>(k->second.front());
1469 } else {
1470 calibrationStrike = QuantLib::ext::make_shared<AtmStrike>(QuantLib::DeltaVolQuote::AtmType::AtmFwd);
1471 }
1472 std::vector<QuantLib::ext::shared_ptr<CalibrationInstrument>> calInstr;
1473 for (auto const& d : calibrationDates)
1474 calInstr.push_back(
1475 QuantLib::ext::make_shared<CpiCapFloor>(QuantLib::CapFloor::Type::Floor, d, calibrationStrike));
1476 std::vector<CalibrationBasket> calBaskets(1, CalibrationBasket(calInstr));
1477 if (infModelType_ == "DK") {
1478 // build DK config
1479 std::string infName = IndexInfo(modelInfIndices_[i].first).infName();
1480 Real vol = parseReal(modelParameter("InfDkVolatility",
1481 {resolvedProductTag_ + "_" + infName, infName, resolvedProductTag_},
1482 false, "0.0050"));
1483 config = QuantLib::ext::make_shared<InfDkData>(
1484 CalibrationType::Bootstrap, calBaskets, modelInfIndices_[i].second->currency().code(),
1485 IndexInfo(modelInfIndices_[i].first).infName(),
1486 ReversionParameter(LgmData::ReversionType::Hagan, true, ParamType::Piecewise, {}, {0.60}),
1487 VolatilityParameter(LgmData::VolatilityType::Hagan, false, ParamType::Piecewise, {}, {vol}),
1488 LgmReversionTransformation(),
1489 // ignore duplicate expiry times among calibration instruments
1490 true);
1491 } else if (infModelType_ == "JY") {
1492 // build JY config
1493 // we calibrate the index ("fx") process to CPI cap/floors and set the real rate process reversion equal to
1494 // the nominal process reversion. The real rate vol is set to a fixed multiple of nominal rate vol, the
1495 // multiplier is taken from the pe config model parameter "InfJyRealToNominalVolRatio"
1496 std::string infName = IndexInfo(modelInfIndices_[i].first).infName();
1497 Size ccyIndex =
1498 std::distance(modelCcys_.begin(), std::find(modelCcys_.begin(), modelCcys_.end(),
1499 modelInfIndices_[i].second->currency().code()));
1500 ReversionParameter realRateRev = QuantLib::ext::static_pointer_cast<LgmData>(irConfigs[ccyIndex])->reversionParameter();
1501 VolatilityParameter realRateVol = QuantLib::ext::static_pointer_cast<LgmData>(irConfigs[ccyIndex])->volatilityParameter();
1502 realRateRev.setCalibrate(false);
1503 realRateVol.setCalibrate(false);
1504 Real realRateToNominalRateRatio = parseReal(
1505 modelParameter("InfJyRealToNominalVolRatio",
1506 {resolvedProductTag_ + "_" + infName, infName, resolvedProductTag_}, false, "1.0"));
1507 QL_REQUIRE(ccyIndex < modelCcys_.size(),
1508 "ScriptedTrade::buildGaussianCam(): internal error, inflation index currency "
1509 << modelInfIndices_[i].second->currency().code() << " not found in model ccy list.");
1510 realRateVol.mult(realRateToNominalRateRatio);
1511 config = QuantLib::ext::make_shared<InfJyData>(
1512 CalibrationType::Bootstrap, calBaskets, modelInfIndices_[i].second->currency().code(), infName,
1513 // real rate reversion and vol
1514 realRateRev, realRateVol,
1515 // index ("fx") vol, start value 0.10 for calibration
1516 VolatilityParameter(true, ParamType::Piecewise, {}, {0.10}),
1517 // no parameter trafo, no optimisation constraints (TODO do we need boundaries?)
1518 LgmReversionTransformation(), CalibrationConfiguration(),
1519 // ignore duplicate expiry times among calibration instruments
1520 true,
1521 // link real to nominal rate params
1522 true,
1523 // real rate to nominal rate ratio
1524 realRateToNominalRateRatio);
1525 } else {
1526 QL_FAIL("invalid infModelType '" << infModelType_ << "', expected DK or JY");
1527 }
1528 }
1529 infConfigs.push_back(config);
1530 }
1531
1532 // FX configs
1533 for (Size i = 1; i < modelCcys_.size(); ++i) {
1534 auto config = QuantLib::ext::make_shared<FxBsData>();
1535 config->foreignCcy() = modelCcys_[i];
1536 config->domesticCcy() = modelCcys_[0];
1537 // if we do not have a FX index for the currency, we set up a zero vol process (FX indices are added above
1538 // for all non-base ccys if fullDynamicFx is specified)
1539 bool haveFxIndex = false;
1540 for (Size j = 0; j < modelIndices_.size(); ++j) {
1541 if (IndexInfo(modelIndices_[j]).isFx() && modelIndicesCurrencies_[j] == modelCcys_[i])
1542 haveFxIndex = true;
1543 }
1544 if (calibrationExpiries.empty() || !haveFxIndex || zeroVolatility_) {
1545 DLOG("set up zero vol FxBsData for currency '" << modelCcys_[i] << "'");
1546 // zero vols
1547 config->calibrationType() = CalibrationType::None;
1548 config->calibrateSigma() = false;
1549 config->sigmaParamType() = ParamType::Constant;
1550 config->sigmaTimes() = std::vector<Real>();
1551 config->sigmaValues() = {0.0};
1552 } else {
1553 DLOG("set up FxBsData for currency '" << modelCcys_[i] << "'");
1554 // bootstrapped on atm fx vols
1555 config->calibrationType() = CalibrationType::Bootstrap;
1556 config->calibrateSigma() = true;
1557 config->sigmaParamType() = ParamType::Piecewise;
1558 config->sigmaTimes() = calibrationTimes;
1559 config->sigmaValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.10); // start value for optimiser
1560 config->optionExpiries() = calibrationExpiries;
1561 config->optionStrikes() =
1562 std::vector<std::string>(calibrationExpiries.size(), "ATMF"); // hardcoded ATMF calibration strike
1563 }
1564 fxConfigs.push_back(config);
1565 }
1566
1567 // EQ configs
1568 for (auto const& eq : eqIndices_) {
1569 auto config = QuantLib::ext::make_shared<EqBsData>();
1570 config->currency() = getEqCcy(eq);
1571 config->eqName() = eq.eq()->name();
1572 if (calibrationExpiries.empty() || zeroVolatility_) {
1573 DLOG("set up zero vol EqBsData for underlying " << eq.eq()->name());
1574 // zero vols
1575 config->calibrationType() = CalibrationType::None;
1576 config->calibrateSigma() = false;
1577 config->sigmaParamType() = ParamType::Constant;
1578 config->sigmaTimes() = std::vector<Real>();
1579 config->sigmaValues() = {0.0};
1580 } else {
1581 DLOG("set up EqBsData for underlying '" << eq.eq()->name() << "'");
1582 // bootstrapped on atm eq vols
1583 config->calibrationType() = CalibrationType::Bootstrap;
1584 config->calibrateSigma() = true;
1585 config->sigmaParamType() = ParamType::Piecewise;
1586 config->sigmaTimes() = calibrationTimes;
1587 config->sigmaValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.10); // start value for optimiser
1588 config->optionExpiries() = calibrationExpiries;
1589 config->optionStrikes() =
1590 std::vector<std::string>(calibrationExpiries.size(), "ATMF"); // hardcoded ATMF calibration strike
1591 }
1592 eqConfigs.push_back(config);
1593 }
1594
1595 // TODO
1596 std::vector<QuantLib::ext::shared_ptr<CrLgmData>> crLgmConfigs;
1597 std::vector<QuantLib::ext::shared_ptr<CrCirData>> crCirConfigs;
1598
1599 // COMM configs
1600 for (auto const& comm : commIndices_) {
1601 auto config = QuantLib::ext::make_shared<CommoditySchwartzData>();
1602 config->currency() = getCommCcy(comm);
1603 config->name() = comm.commName();
1604 if (calibrationExpiries.empty() || zeroVolatility_) {
1605 config->calibrationType() = CalibrationType::None;
1606 config->calibrateSigma() = false;
1607 config->sigmaParamType() = ParamType::Constant;
1608 config->sigmaValue() = 0.0;
1609 } else {
1610 config->calibrationType() = CalibrationType::BestFit;
1611 config->calibrateSigma() = true;
1612 config->sigmaParamType() = ParamType::Constant;
1613 config->sigmaValue() = 0.10; // start value for optimizer
1614 config->optionExpiries() = calibrationExpiries;
1615 config->optionStrikes() =
1616 std::vector<std::string>(calibrationExpiries.size(), "ATMF"); // hardcoded ATMF calibration strike
1617 }
1618 comConfigs.push_back(config);
1619 }
1620
1621 std::string configurationInCcy = configuration(MarketContext::irCalibration);
1622 std::string configurationXois = configuration(MarketContext::pricing);
1623 auto discretization = useCg_ ? CrossAssetModel::Discretization::Euler : CrossAssetModel::Discretization::Exact;
1624 auto camBuilder = QuantLib::ext::make_shared<CrossAssetModelBuilder>(
1625 market_,
1626 QuantLib::ext::make_shared<CrossAssetModelData>(irConfigs, fxConfigs, eqConfigs, infConfigs, crLgmConfigs, crCirConfigs,
1627 comConfigs, 0, camCorrelations, bootstrapTolerance_, "LGM",
1628 discretization),
1629 configurationInCcy, configurationXois, configurationXois, configurationInCcy, configurationInCcy,
1631 SalvagingAlgorithm::Spectral, id);
1632
1633 // effective time steps per year: zero for exact evolution, otherwise the pricing engine parameter
1634 if (useCg_) {
1635 modelCG_ = QuantLib::ext::make_shared<GaussianCamCG>(
1638 camBuilder->model()->discretization() == CrossAssetModel::Discretization::Exact ? 0 : timeStepsPerYear_,
1639 iborFallbackConfig, std::vector<Size>(), conditionalExpectationModelStates);
1640 } else {
1641 model_ = QuantLib::ext::make_shared<GaussianCam>(
1644 camBuilder->model()->discretization() == CrossAssetModel::Discretization::Exact ? 0 : timeStepsPerYear_,
1645 iborFallbackConfig, std::vector<Size>(), conditionalExpectationModelStates);
1646 }
1647
1648 modelBuilders_.insert(std::make_pair(id, camBuilder));
1649}
@ Hagan
Parametrize LGM H(t) as H(t) = int_0^t h(s) ds with constant or piecewise h(s)
@ Hagan
Parametrize volatility as Hagan alpha(t)
Date referenceDate
Definition: utilities.cpp:442
CorrelationFactor parseCorrelationFactor(const string &name, const char separator)
std::pair< std::string, Period > convertIndexToCamCorrelationEntry(const std::string &i)
Definition: utilities.cpp:138
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildFdGaussianCam()

void buildFdGaussianCam ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig 
)
protected

Definition at line 1651 of file scriptedtrade.cpp.

1652 {
1653
1654 Date referenceDate = modelCurves_.front()->referenceDate();
1655 std::vector<Date> calibrationDates;
1656 std::vector<std::string> calibrationExpiries, calibrationTerms;
1657
1658 for (auto const& d : simulationDates_) {
1659 if (d > referenceDate) {
1660 calibrationDates.push_back(d);
1661 calibrationExpiries.push_back(ore::data::to_string(d));
1662 // make sure the underlying swap has at least 1M to run, QL will throw otherwise during calibration
1663 calibrationTerms.push_back(ore::data::to_string(std::max(d + 1 * Months, lastRelevantDate_)));
1664 }
1665 }
1666
1667 // calibration times (need one less than calibration dates)
1668 std::vector<Real> calibrationTimes;
1669 for (Size i = 0; i + 1 < calibrationDates.size(); ++i) {
1670 calibrationTimes.push_back(modelCurves_.front()->timeFromReference(calibrationDates[i]));
1671 }
1672
1673 // determine calibration strike
1674 std::string calibrationStrike = "ATM";
1675 if(calibration_ == "Deal") {
1676 // first model index found in calibration strike spec and first specified strike therein is used
1677 for (auto const& m : modelIrIndices_) {
1678 if (auto f = calibrationStrikes_.find(m.first); f != calibrationStrikes_.end()) {
1679 if(!f->second.empty()) {
1680 calibrationStrike = boost::lexical_cast<std::string>(f->second.front());
1681 }
1682 }
1683 }
1684 }
1685
1686 // IR config
1687 QL_REQUIRE(modelCcys_.size() == 1,
1688 "ScriptedTradeEngineBuilder::buildFdGaussianCam(): only one ccy is supported, got "
1689 << modelCcys_.size());
1690
1691 auto config = QuantLib::ext::make_shared<IrLgmData>();
1692 config->qualifier() = getFirstIrIndexOrCcy(modelCcys_.front(), irIndices_);
1693 config->reversionType() = LgmData::ReversionType::HullWhite;
1694 config->volatilityType() = LgmData::VolatilityType::Hagan;
1695 config->calibrateH() = false;
1696 config->hParamType() = ParamType::Constant;
1697 config->hTimes() = std::vector<Real>();
1698 config->shiftHorizon() =
1699 modelCurves_.front()->timeFromReference(lastRelevantDate_) * 0.5; // TODO hardcode 0.5 here?
1700 config->scaling() = 1.0;
1701 std::string ccy = modelCcys_.front();
1702 if (zeroVolatility_ ) {
1703 DLOG("set up zero vol IrLgmData for currency '" << modelCcys_.front() << "'");
1704 // zero vol
1705 config->calibrationType() = CalibrationType::None;
1706 config->hValues() = {0.0};
1707 config->calibrateA() = false;
1708 config->aParamType() = ParamType::Constant;
1709 config->aTimes() = std::vector<Real>();
1710 config->aValues() = {0.0};
1711 } else {
1712 DLOG("set up IrLgmData for currency '" << modelCcys_.front() << "'");
1713 auto rev = irReversions_.find(modelCcys_.front());
1714 QL_REQUIRE(rev != irReversions_.end(), "reversion for ccy " << modelCcys_.front() << " not found");
1715 config->calibrationType() = CalibrationType::Bootstrap;
1716 config->hValues() = {rev->second};
1717 config->calibrateA() = true;
1718 config->aParamType() = ParamType::Piecewise;
1719 config->aTimes() = calibrationTimes;
1720 config->aValues() = std::vector<Real>(calibrationTimes.size() + 1, 0.0030); // start value for optimiser
1721 config->optionExpiries() = calibrationExpiries;
1722 config->optionTerms() = calibrationTerms;
1723 config->optionStrikes() = std::vector<std::string>(calibrationExpiries.size(), calibrationStrike);
1724 }
1725
1726 std::string configurationInCcy = configuration(MarketContext::irCalibration);
1727 std::string configurationXois = configuration(MarketContext::pricing);
1728
1729 auto camBuilder = QuantLib::ext::make_shared<CrossAssetModelBuilder>(
1730 market_,
1731 QuantLib::ext::make_shared<CrossAssetModelData>(
1732 std::vector<QuantLib::ext::shared_ptr<IrModelData>>{config}, std::vector<QuantLib::ext::shared_ptr<FxBsData>>{},
1733 std::vector<QuantLib::ext::shared_ptr<EqBsData>>{}, std::vector<QuantLib::ext::shared_ptr<InflationModelData>>{},
1734 std::vector<QuantLib::ext::shared_ptr<CrLgmData>>{}, std::vector<QuantLib::ext::shared_ptr<CrCirData>>{},
1735 std::vector<QuantLib::ext::shared_ptr<CommoditySchwartzData>>{}, 0,
1736 std::map<CorrelationKey, QuantLib::Handle<QuantLib::Quote>>{}, bootstrapTolerance_, "LGM",
1737 CrossAssetModel::Discretization::Exact),
1738 configurationInCcy, configurationXois, configurationXois, configurationInCcy, configurationInCcy,
1740 SalvagingAlgorithm::Spectral, id);
1741
1742 model_ = QuantLib::ext::make_shared<FdGaussianCam>(camBuilder->model(), modelCcys_.front(), modelCurves_.front(),
1744 mesherEpsilon_, iborFallbackConfig);
1745
1746 modelBuilders_.insert(std::make_pair(id, camBuilder));
1747}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildGaussianCamAMC()

void buildGaussianCamAMC ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig,
const std::vector< std::string > &  conditionalExpectationModelStates 
)
protected

Definition at line 1756 of file scriptedtrade.cpp.

1758 {
1759
1760 QL_REQUIRE(!useCg_, "building gaussian cam from external amc cam, useCg must be set to false in this case.");
1761
1762 std::vector<std::pair<CrossAssetModel::AssetType, Size>> selectedComponents;
1763
1764 // IR configs
1765 for (Size i = 0; i < modelCcys_.size(); ++i) {
1766 selectedComponents.push_back(
1767 std::make_pair(CrossAssetModel::AssetType::IR, amcCam_->ccyIndex(parseCurrency(modelCcys_[i]))));
1768 }
1769
1770 // INF configs
1771 for (Size i = 0; i < modelInfIndices_.size(); ++i) {
1772 selectedComponents.push_back(std::make_pair(CrossAssetModel::AssetType::INF,
1773 amcCam_->infIndex(IndexInfo(modelInfIndices_[i].first).infName())));
1774 }
1775
1776 // FX configs
1777 for (Size i = 1; i < modelCcys_.size(); ++i) {
1778 selectedComponents.push_back(
1779 std::make_pair(CrossAssetModel::AssetType::FX, amcCam_->ccyIndex(parseCurrency(modelCcys_[i])) - 1));
1780 }
1781
1782 // EQ configs
1783 for (auto const& eq : eqIndices_) {
1784 selectedComponents.push_back(std::make_pair(CrossAssetModel::AssetType::EQ, amcCam_->eqIndex(eq.eq()->name())));
1785 }
1786
1787 // COMM configs, not supported at this point
1788 QL_REQUIRE(commIndices_.empty(), "GaussianCam model does not support commodity underlyings currently");
1789
1790 std::vector<Size> projectedStateProcessIndices;
1791 Handle<CrossAssetModel> projectedModel(
1792 getProjectedCrossAssetModel(amcCam_, selectedComponents, projectedStateProcessIndices));
1793
1794 // effective time steps per year: zero for exact evolution, otherwise the pricing engine parameter
1795 if (useCg_) {
1796 modelCG_ = QuantLib::ext::make_shared<GaussianCamCG>(
1799 projectedModel->discretization() == CrossAssetModel::Discretization::Exact ? 0 : timeStepsPerYear_,
1800 iborFallbackConfig, projectedStateProcessIndices, conditionalExpectationModelStates);
1801 } else {
1802 model_ = QuantLib::ext::make_shared<GaussianCam>(
1805 projectedModel->discretization() == CrossAssetModel::Discretization::Exact ? 0 : timeStepsPerYear_,
1806 iborFallbackConfig, projectedStateProcessIndices, conditionalExpectationModelStates);
1807 }
1808
1809 DLOG("built GuassianCam model as projection of xva evolution model");
1810 for (auto const& p : projectedStateProcessIndices)
1811 DLOG(" got projected state process index: " << p);
1812}
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
boost::shared_ptr< CrossAssetModel > getProjectedCrossAssetModel(const boost::shared_ptr< CrossAssetModel > &model, const std::vector< std::pair< CrossAssetModel::AssetType, Size > > &selectedComponents, std::vector< Size > &projectedStateProcessIndices)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ buildAMCCGModel()

void buildAMCCGModel ( const std::string &  id,
const IborFallbackConfig iborFallbackConfig,
const std::vector< std::string > &  conditionalExpectationModelStates 
)
protected

Definition at line 1749 of file scriptedtrade.cpp.

1750 {
1751 // nothing to build really, the resulting model is exactly the input model
1752 QL_REQUIRE(useCg_, "building gaussian cam from external amc cg model, useCg must be set to true in this case.");
1754}
+ Here is the caller graph for this function:

◆ addAmcGridToContext()

void addAmcGridToContext ( QuantLib::ext::shared_ptr< Context > &  context) const
protected

Definition at line 1814 of file scriptedtrade.cpp.

1814 {
1815 // the amc grid might be empty, but we add the _AMC_SimDates variable to the context anyway, since
1816 // a script might rely on its existence
1817 DLOG("adding amc date grid (" << amcGrid_.size() << ") to context as _AMC_SimDates");
1818 std::vector<ValueType> tmp;
1819 for (auto const& d : amcGrid_)
1820 tmp.push_back(EventVec{modelSize_, d});
1821 context->arrays["_AMC_SimDates"] = tmp;
1822}
+ Here is the caller graph for this function:

◆ setupCalibrationStrikes()

void setupCalibrationStrikes ( const ScriptedTradeScriptData script,
const QuantLib::ext::shared_ptr< Context > &  context 
)
protected

Definition at line 1824 of file scriptedtrade.cpp.

1825 {
1826 calibrationStrikes_ = getCalibrationStrikes(script.calibrationSpec(), context);
1827}
std::map< std::string, std::vector< Real > > getCalibrationStrikes(const std::vector< ScriptedTradeScriptData::CalibrationData > &calibrationSpec, const QuantLib::ext::shared_ptr< Context > &context)
Definition: utilities.cpp:673
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getEqCcy()

std::string getEqCcy ( const IndexInfo e)
protected

Definition at line 714 of file scriptedtrade.cpp.

714 {
715 QL_REQUIRE(e.isEq(), "ScriptedTradeEngineBuilder::getEqCcy(): expected eq index, got " << e.name());
716 // the eq currency can only be retrieved from the market
717 Currency tmp = market_->equityCurve(e.eq()->name(), configuration(MarketContext::pricing))->currency();
718 QL_REQUIRE(!tmp.empty(), "ScriptedTradeEngineBuilder: Cannot find currency for equity '"
719 << e.eq()->name() << "'. Check if equity is present in curveconfig.");
720 return tmp.code();
721}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ getCommCcy()

std::string getCommCcy ( const IndexInfo e)
protected

Definition at line 723 of file scriptedtrade.cpp.

723 {
724 QL_REQUIRE(e.isComm(), "ScriptedTradeEngineBuilder::getCommCcy(): expected comm index, got " << e.name());
725 // the comm currency can only be retrieved from the market
726 Currency tmp = market_->commodityPriceCurve(e.commName(), configuration(MarketContext::pricing))->currency();
727 QL_REQUIRE(!tmp.empty(), "ScriptedTradeEngineBuilder: Cannot find currency for commodity '"
728 << e.commName() << "'. Check if Commodity is present in curveconfig.");
729 return tmp.code();
730}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ buildingAmc_

bool buildingAmc_ = false
protected

Definition at line 109 of file scriptedtrade.hpp.

◆ amcCam_

const QuantLib::ext::shared_ptr<QuantExt::CrossAssetModel> amcCam_
protected

Definition at line 110 of file scriptedtrade.hpp.

◆ amcCgModel_

const QuantLib::ext::shared_ptr<ore::data::ModelCG> amcCgModel_
protected

Definition at line 111 of file scriptedtrade.hpp.

◆ amcGrid_

const std::vector<Date> amcGrid_
protected

Definition at line 112 of file scriptedtrade.hpp.

◆ astCache_

std::map<std::string, ASTNodePtr> astCache_
protected

Definition at line 115 of file scriptedtrade.hpp.

◆ ast_

ASTNodePtr ast_
protected

Definition at line 118 of file scriptedtrade.hpp.

◆ npvCurrency_

std::string npvCurrency_
protected

Definition at line 119 of file scriptedtrade.hpp.

◆ lastRelevantDate_

QuantLib::Date lastRelevantDate_
protected

Definition at line 120 of file scriptedtrade.hpp.

◆ simmProductClass_

std::string simmProductClass_
protected

Definition at line 121 of file scriptedtrade.hpp.

◆ scheduleProductClass_

std::string scheduleProductClass_
protected

Definition at line 122 of file scriptedtrade.hpp.

◆ sensitivityTemplate_

std::string sensitivityTemplate_
protected

Definition at line 123 of file scriptedtrade.hpp.

◆ fixings_

std::map<std::string, std::set<Date> > fixings_
protected

Definition at line 124 of file scriptedtrade.hpp.

◆ staticAnalyser_

QuantLib::ext::shared_ptr<StaticAnalyser> staticAnalyser_
protected

Definition at line 127 of file scriptedtrade.hpp.

◆ eqIndices_

std::set<IndexInfo> eqIndices_
protected

Definition at line 128 of file scriptedtrade.hpp.

◆ commIndices_

std::set<IndexInfo> commIndices_
protected

Definition at line 128 of file scriptedtrade.hpp.

◆ irIndices_

std::set<IndexInfo> irIndices_
protected

Definition at line 128 of file scriptedtrade.hpp.

◆ infIndices_

std::set<IndexInfo> infIndices_
protected

Definition at line 128 of file scriptedtrade.hpp.

◆ fxIndices_

std::set<IndexInfo> fxIndices_
protected

Definition at line 128 of file scriptedtrade.hpp.

◆ resolvedProductTag_

std::string resolvedProductTag_
protected

Definition at line 129 of file scriptedtrade.hpp.

◆ assetClassReplacement_

std::string assetClassReplacement_
protected

Definition at line 129 of file scriptedtrade.hpp.

◆ payCcys_

std::set<std::string> payCcys_
protected

Definition at line 130 of file scriptedtrade.hpp.

◆ baseCcy_

std::string baseCcy_
protected

Definition at line 131 of file scriptedtrade.hpp.

◆ modelCcys_

std::vector<std::string> modelCcys_
protected

Definition at line 132 of file scriptedtrade.hpp.

◆ modelCurves_

std::vector<Handle<YieldTermStructure> > modelCurves_
protected

Definition at line 133 of file scriptedtrade.hpp.

◆ modelFxSpots_

std::vector<Handle<Quote> > modelFxSpots_
protected

Definition at line 134 of file scriptedtrade.hpp.

◆ modelIndices_

std::vector<std::string> modelIndices_
protected

Definition at line 135 of file scriptedtrade.hpp.

◆ modelIndicesCurrencies_

std::vector<std::string> modelIndicesCurrencies_
protected

Definition at line 135 of file scriptedtrade.hpp.

◆ modelIrIndices_

std::vector<std::pair<std::string, QuantLib::ext::shared_ptr<InterestRateIndex> > > modelIrIndices_
protected

Definition at line 136 of file scriptedtrade.hpp.

◆ modelInfIndices_

std::vector<std::pair<std::string, QuantLib::ext::shared_ptr<ZeroInflationIndex> > > modelInfIndices_
protected

Definition at line 137 of file scriptedtrade.hpp.

◆ correlations_

std::map<std::pair<std::string, std::string>, Handle<QuantExt::CorrelationTermStructure> > correlations_
protected

Definition at line 138 of file scriptedtrade.hpp.

◆ processes_

std::vector<QuantLib::ext::shared_ptr<GeneralizedBlackScholesProcess> > processes_
protected

Definition at line 139 of file scriptedtrade.hpp.

◆ irReversions_

std::map<std::string, Real> irReversions_
protected

Definition at line 140 of file scriptedtrade.hpp.

◆ simulationDates_

std::set<Date> simulationDates_
protected

Definition at line 141 of file scriptedtrade.hpp.

◆ addDates_

std::set<Date> addDates_
protected

Definition at line 141 of file scriptedtrade.hpp.

◆ model_

QuantLib::ext::shared_ptr<Model> model_
protected

Definition at line 142 of file scriptedtrade.hpp.

◆ modelCG_

QuantLib::ext::shared_ptr<ModelCG> modelCG_
protected

Definition at line 143 of file scriptedtrade.hpp.

◆ calibrationStrikes_

std::map<std::string, std::vector<Real> > calibrationStrikes_
protected

Definition at line 144 of file scriptedtrade.hpp.

◆ modelParam_

std::string modelParam_
protected

Definition at line 147 of file scriptedtrade.hpp.

◆ infModelType_

std::string infModelType_
protected

Definition at line 147 of file scriptedtrade.hpp.

◆ engineParam_

std::string engineParam_
protected

Definition at line 147 of file scriptedtrade.hpp.

◆ baseCcyParam_

std::string baseCcyParam_
protected

Definition at line 147 of file scriptedtrade.hpp.

◆ gridCoarsening_

std::string gridCoarsening_
protected

Definition at line 147 of file scriptedtrade.hpp.

◆ fullDynamicFx_

bool fullDynamicFx_
protected

Definition at line 148 of file scriptedtrade.hpp.

◆ fullDynamicIr_

bool fullDynamicIr_
protected

Definition at line 148 of file scriptedtrade.hpp.

◆ enforceBaseCcy_

bool enforceBaseCcy_
protected

Definition at line 148 of file scriptedtrade.hpp.

◆ modelSize_

Size modelSize_
protected

Definition at line 149 of file scriptedtrade.hpp.

◆ timeStepsPerYear_

Size timeStepsPerYear_
protected

Definition at line 149 of file scriptedtrade.hpp.

◆ mcParams_

Model::McParams mcParams_
protected

Definition at line 150 of file scriptedtrade.hpp.

◆ interactive_

bool interactive_
protected

Definition at line 151 of file scriptedtrade.hpp.

◆ zeroVolatility_

bool zeroVolatility_
protected

Definition at line 151 of file scriptedtrade.hpp.

◆ continueOnCalibrationError_

bool continueOnCalibrationError_
protected

Definition at line 151 of file scriptedtrade.hpp.

◆ calibrationMoneyness_

std::vector<Real> calibrationMoneyness_
protected

Definition at line 152 of file scriptedtrade.hpp.

◆ mesherEpsilon_

Real mesherEpsilon_
protected

Definition at line 153 of file scriptedtrade.hpp.

◆ mesherScaling_

Real mesherScaling_
protected

Definition at line 153 of file scriptedtrade.hpp.

◆ mesherConcentration_

Real mesherConcentration_
protected

Definition at line 153 of file scriptedtrade.hpp.

◆ mesherMaxConcentratingPoints_

Size mesherMaxConcentratingPoints_
protected

Definition at line 154 of file scriptedtrade.hpp.

◆ mesherIsStatic_

bool mesherIsStatic_
protected

Definition at line 155 of file scriptedtrade.hpp.

◆ referenceCalibrationGrid_

std::string referenceCalibrationGrid_
protected

Definition at line 156 of file scriptedtrade.hpp.

◆ bootstrapTolerance_

Real bootstrapTolerance_
protected

Definition at line 157 of file scriptedtrade.hpp.

◆ calibrate_

bool calibrate_
protected

Definition at line 158 of file scriptedtrade.hpp.

◆ calibration_

std::string calibration_
protected

Definition at line 159 of file scriptedtrade.hpp.

◆ useCg_

bool useCg_
protected

Definition at line 160 of file scriptedtrade.hpp.

◆ useAd_

bool useAd_
protected

Definition at line 161 of file scriptedtrade.hpp.

◆ useExternalComputeDevice_

bool useExternalComputeDevice_
protected

Definition at line 162 of file scriptedtrade.hpp.

◆ useDoublePrecisionForExternalCalculation_

bool useDoublePrecisionForExternalCalculation_
protected

Definition at line 163 of file scriptedtrade.hpp.

◆ externalDeviceCompatibilityMode_

bool externalDeviceCompatibilityMode_
protected

Definition at line 164 of file scriptedtrade.hpp.

◆ externalComputeDevice_

std::string externalComputeDevice_
protected

Definition at line 165 of file scriptedtrade.hpp.

◆ includePastCashflows_

bool includePastCashflows_
protected

Definition at line 166 of file scriptedtrade.hpp.