35 {
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
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
55
56
57
58 auto workingContext = QuantLib::ext::make_shared<Context>(*
context_);
59
60
62
63
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
73
77 workingContext->constants.insert("TODAY");
78
79
80
81 if (stickyCloseOutRun) {
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 }
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
97
98 ScriptEngine engine(
ast_, workingContext,
model_);
100
101
102
103 Size resultSize = relevantTimeIndex.size();
104 std::vector<QuantExt::RandomVariable> result(resultSize + 1);
105
106
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");
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
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) {
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
131
133 auto s = workingContext->scalars.find(n);
134 if (s != workingContext->scalars.end()) {
136
137 }
138 auto v = workingContext->arrays.find(n);
139 if (v != workingContext->arrays.end()) {
141
142 }
143 }
144
145 return result;
146}
std::map< std::string, std::vector< ValueType > > stickyCloseOutRunArrays_
std::map< std::string, ValueType > stickyCloseOutRunScalars_
#define DLOG(text)
Logging Macro (Level = Debug)
RandomVariable expectation(const RandomVariable &r)
void amendContextVariablesSizes(QuantLib::ext::shared_ptr< Context > context, const Size newSize)
void checkDuplicateName(const QuantLib::ext::shared_ptr< Context > context, const std::string &name)