Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
scriptedinstrumentamccalculator.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2020 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
22
24
27
28namespace ore {
29namespace data {
30
31QuantLib::Currency ScriptedInstrumentAmcCalculator::npvCurrency() { return parseCurrency(model_->baseCcy()); }
32
33std::vector<QuantExt::RandomVariable> ScriptedInstrumentAmcCalculator::simulatePath(
34 const std::vector<QuantLib::Real>& pathTimes, std::vector<std::vector<QuantExt::RandomVariable>>& paths,
35 const std::vector<size_t>& relevantPathIndex, const std::vector<size_t>& relevantTimeIndex) {
36
37 QL_REQUIRE(relevantPathIndex.size() == relevantTimeIndex.size(),
38 "ScriptedInstrumentAmcCalculator::simulatePath: Mismatch between relevantPathIndex size and "
39 "relevantTimeIndex size, internal error");
40
41 bool stickyCloseOutRun = false;
42 for (size_t i = 0; i < relevantPathIndex.size(); ++i) {
43 if (relevantPathIndex[i] != relevantTimeIndex[i]) {
44 stickyCloseOutRun = true;
45 break;
46 }
47 }
48 // inject the global paths into our local model, notice that this will change the size of the model
49
50 auto amcModel = QuantLib::ext::dynamic_pointer_cast<AmcModel>(model_);
51 QL_REQUIRE(amcModel, "expected an AmcModel");
52 amcModel->injectPaths(&pathTimes, &paths, &relevantPathIndex, &relevantTimeIndex);
53
54 // the rest is similar to what is done in the ScriptedInstrumentPricingEngine:
55
56 // set up copy of initial context to run the script engine on
57
58 auto workingContext = QuantLib::ext::make_shared<Context>(*context_);
59
60 // amend context to new model size
61 amendContextVariablesSizes(workingContext, model_->size());
62
63 // make sure we reset the injected path data after the calculation
64 struct InjectedPathReleaser {
65 ~InjectedPathReleaser() {
66 QuantLib::ext::dynamic_pointer_cast<AmcModel>(model)->injectPaths(nullptr, nullptr, nullptr, nullptr);
67 }
68 QuantLib::ext::shared_ptr<Model> model;
69 };
70 InjectedPathReleaser injectedPathReleaser{model_};
71
72 // set TODAY in the context
73
74 checkDuplicateName(workingContext, "TODAY");
75 Date referenceDate = model_->referenceDate();
76 workingContext->scalars["TODAY"] = EventVec{model_->size(), referenceDate};
77 workingContext->constants.insert("TODAY");
78
79 // set context variables that should be static for sticky close-out runs
80
81 if (stickyCloseOutRun) {
82 for (auto const& s : stickyCloseOutRunScalars_) {
83 workingContext->scalars[s.first] = s.second;
84 workingContext->constants.insert(s.first);
85 workingContext->ignoreAssignments.insert(s.first);
86 DLOG("add scalar " << s.first << " to context from previous run, since we have a sticky close-out run now");
87 }
88 for (auto const& s : stickyCloseOutRunArrays_) {
89 workingContext->arrays[s.first] = s.second;
90 workingContext->constants.insert(s.first);
91 workingContext->ignoreAssignments.insert(s.first);
92 DLOG("add array " << s.first << " to context from previous run, since we have a sticky close-out run now");
93 }
94 }
95
96 // set up script engine and run it
97
98 ScriptEngine engine(ast_, workingContext, model_);
99 engine.run(script_, interactive_, nullptr);
100
101 // extract AMC Exposure result and return them
102
103 Size resultSize = relevantTimeIndex.size();
104 std::vector<QuantExt::RandomVariable> result(resultSize + 1);
105
106 // the T0 npv is the first component of the result
107
108 auto npv = workingContext->scalars.find(npv_);
109 QL_REQUIRE(npv != workingContext->scalars.end(),
110 "did not find npv result variable '" << npv_ << "' as scalar in context");
111 QL_REQUIRE(npv->second.which() == ValueTypeWhich::Number,
112 "result variable '" << npv_ << "' must be of type NUMBER, got " << npv->second.which());
113 result[0] = expectation(QuantLib::ext::get<RandomVariable>(npv->second));
114
115 // the other components are given as the additional result _AMC_NPV
116
117 auto s = workingContext->arrays.find("_AMC_NPV");
118 QL_REQUIRE(s != workingContext->arrays.end(), "did not find amc exposure result _AMC_NPV");
119 QL_REQUIRE(s->second.size() == resultSize,
120 "result _AMC_NPV has size "
121 << s->second.size() << " which is inconsistent with number of (positive, and relevant) path times "
122 << resultSize);
123
124 for (Size i = 0; i < resultSize; ++i) {
125 QL_REQUIRE(s->second[i].which() == ValueTypeWhich::Number,
126 "component #" << i << " in _AMC_NPV has wrong type, expected Number");
127 result[i + 1] = QuantLib::ext::get<RandomVariable>(s->second[i]);
128 }
129
130 // extract variables that should be static in subsequent sticky close-out runs
131
132 for (auto const& n : stickyCloseOutStates_) {
133 auto s = workingContext->scalars.find(n);
134 if (s != workingContext->scalars.end()) {
135 stickyCloseOutRunScalars_[n] = s->second;
136 //DLOG("store variable " << n << " for subsequent sticky close-out run");
137 }
138 auto v = workingContext->arrays.find(n);
139 if (v != workingContext->arrays.end()) {
140 stickyCloseOutRunArrays_[n] = v->second;
141 //DLOG("store array " << n << " for subsequent sticky close-out run");
142 }
143 }
144
145 return result;
146}
147
148} // namespace data
149} // namespace ore
void run(const std::string &script="", bool interactive=false, QuantLib::ext::shared_ptr< PayLog > paylog=nullptr, bool includePastCashflows=false)
const QuantLib::ext::shared_ptr< Context > context_
std::vector< QuantExt::RandomVariable > simulatePath(const std::vector< QuantLib::Real > &pathTimes, std::vector< std::vector< QuantExt::RandomVariable > > &paths, const std::vector< size_t > &relevantPathIndex, const std::vector< size_t > &relevantTimeIndex) override
std::map< std::string, std::vector< ValueType > > stickyCloseOutRunArrays_
const QuantLib::ext::shared_ptr< Model > model_
std::map< std::string, ValueType > stickyCloseOutRunScalars_
Currency parseCurrency(const string &s)
Convert text to QuantLib::Currency.
Definition: parsers.cpp:290
Classes and functions for log message handling.
@ data
Definition: log.hpp:77
#define DLOG(text)
Logging Macro (Level = Debug)
Definition: log.hpp:554
Date referenceDate
Definition: utilities.cpp:442
RandomVariable expectation(const RandomVariable &r)
void amendContextVariablesSizes(QuantLib::ext::shared_ptr< Context > context, const Size newSize)
Definition: utilities.cpp:379
void checkDuplicateName(const QuantLib::ext::shared_ptr< Context > context, const std::string &name)
Definition: utilities.cpp:156
Serializable Credit Default Swap.
Definition: namespaces.docs:23
Map text representations to QuantLib/QuantExt types.
amc calculator for scripted trades
scriptengine
some utility functions