63 QL_FAIL(
"getDifferenceScenario(): key type "
64 << keyType <<
" not expected, and not covered. This is an internal error, contact dev.");
103 QL_FAIL(
"addDifferenceToScenario(): key type "
104 << keyType <<
" not expected, and not covered. This is an internal error, contact dev.");
109 const QuantLib::ext::shared_ptr<Scenario>& s2,
110 const Date& targetScenarioAsOf,
111 const Real targetScenarioNumeraire) {
113 QL_REQUIRE(s1->isAbsolute() && s2->isAbsolute(),
"getDifferenceScenario(): both scenarios must be absolute ("
114 << std::boolalpha << s1->isAbsolute() <<
", "
115 << s2->isAbsolute());
117 QL_REQUIRE(s1->keysHash() == s2->keysHash(),
118 "getDifferenceScenario(): both scenarios must have identical key sets");
120 Date
asof = targetScenarioAsOf;
121 if (
asof == Date() && s1->asof() == s2->asof())
124 QL_REQUIRE(
asof != Date(),
"getDifferenceScenario(): either both scenarios have to have the same asof date ("
125 << s1->asof() <<
", " << s2->asof()
126 <<
") or the target scenario asof date must be given.");
128 auto result = s1->clone();
129 result->setAsof(
asof);
130 result->label(
"differenceScenario(" + s1->label() +
"," + s2->label() +
")");
131 result->setNumeraire(targetScenarioNumeraire);
132 result->setAbsolute(
false);
134 for (
auto const& k : s1->keys()) {
142 const QuantLib::ext::shared_ptr<Scenario>& d,
143 const Date& targetScenarioAsOf,
144 const Real targetScenarioNumeraire) {
146 QL_REQUIRE(!d->isAbsolute(),
"addDifferenceToScenario(): second argument must be difference scenario");
147 QL_REQUIRE(s->keysHash() == d->keysHash(),
148 "addDifferenceToScenario(): both scenarios must have identical key sets.");
150 Date
asof = targetScenarioAsOf;
151 if (
asof == Date() && s->asof() == d->asof())
154 QL_REQUIRE(
asof != Date(),
"addDifferenceToScenario(): either both scenarios have to have the same asof date ("
155 << s->asof() <<
", " << d->asof()
156 <<
") or the target scenario asof date must be given.");
158 auto result = s->clone();
159 result->setAsof(
asof);
160 result->label(
"sumScenario(" + s->label() +
"," + d->label() +
")");
161 result->setNumeraire(targetScenarioNumeraire);
162 result->setAbsolute(s->isAbsolute());
164 for (
auto const& k : s->keys()) {
173Size getKeyIndex(
const std::vector<std::vector<Real>>& oldCoordinates,
const std::vector<Size>& indices) {
174 Size resultIndex = 0;
176 int workingIndex = indices.size() - 1;
178 resultIndex += multiplier * indices[workingIndex];
179 multiplier *= oldCoordinates[workingIndex].size();
180 }
while (--workingIndex >= 0);
184double interpolatedValue(
const std::vector<std::vector<Real>>& oldCoordinates,
185 const std::vector<std::vector<Real>>& newCoordinates,
const std::vector<Size>& newIndex,
186 const std::pair<RiskFactorKey::KeyType, std::string>& key,
187 const QuantLib::ext::shared_ptr<Scenario>& scenario) {
190 std::vector<Size> oldIndex0(oldCoordinates.size());
191 std::vector<Size> oldIndex1(oldCoordinates.size());
193 for (Size i = 0; i < oldCoordinates.size(); ++i) {
194 Size idx = std::distance(
195 oldCoordinates[i].begin(),
196 std::upper_bound(oldCoordinates[i].begin(), oldCoordinates[i].end(), newCoordinates[i][newIndex[i]]));
200 oldIndex0[i] = oldIndex1[i] = 0;
201 }
else if (idx == oldCoordinates[i].
size()) {
204 oldIndex0[i] = oldIndex1[i] = idx - 1;
206 oldIndex0[i] = idx - 1;
208 w1 = (newCoordinates[i][newIndex[i]] - oldCoordinates[i][idx - 1]) /
209 (oldCoordinates[i][idx] - oldCoordinates[i][idx - 1]);
214 Size keyIndex0 = getKeyIndex(oldCoordinates, oldIndex0);
215 Size keyIndex1 = getKeyIndex(oldCoordinates, oldIndex1);
217 return w0 * scenario->get(RiskFactorKey(key.first, key.second, keyIndex0)) +
218 w1 * scenario->get(RiskFactorKey(key.first, key.second, keyIndex1));
219 }
catch (
const std::exception& e) {
220 QL_FAIL(
"recastScenario(): error while interpolating between "
221 << key.first <<
"/" << key.second <<
"/[" << keyIndex0 <<
"," << keyIndex1 <<
"]: " << e.what());
228 const QuantLib::ext::shared_ptr<Scenario>& scenario,
229 const std::map<std::pair<RiskFactorKey::KeyType, std::string>, std::vector<std::vector<Real>>>& oldCoordinates,
230 const std::map<std::pair<RiskFactorKey::KeyType, std::string>, std::vector<std::vector<Real>>>& newCoordinates) {
232 auto result = QuantLib::ext::make_shared<SimpleScenario>(
233 scenario->asof(), scenario->label() +
" (mapped to new coordinates)", scenario->getNumeraire());
234 result->setAbsolute(scenario->isAbsolute());
236 std::set<std::pair<RiskFactorKey::KeyType, std::string>> keys;
237 for (
auto const& k : scenario->keys()) {
238 if(newCoordinates.count({k.keytype, k.name})==1){
239 keys.insert(std::make_pair(k.keytype, k.name));
240 TLOG(
"Insert keys " << k.keytype <<
" " << k.name)
242 TLOG(
"Recast skip " << k.keytype <<
" " << k.name);
248 for (
auto const& k : keys) {
250 auto c0 = oldCoordinates.find(k);
251 auto c1 = newCoordinates.find(k);
252 QL_REQUIRE(c0 != scenario->coordinates().end(),
"recastScenario(): no coordinates for "
253 << k.first <<
"/" << k.second
254 <<
" found in old coordinates. This is unexpected.");
255 QL_REQUIRE(c1 != scenario->coordinates().end(),
"recastScenario(): no coordinates for "
256 << k.first <<
"/" << k.second
257 <<
" found in new coordinates. This is unexpected.");
258 QL_REQUIRE(c0->second.size() == c1->second.size(),
"recastScenario(): number of dimensions in old ("
259 << c0->second.size() <<
") and new ("
260 << c1->second.size() <<
") coordinates for " << k.first
261 <<
"/" << k.second <<
" do not match.");
262 if (c1->second.size() == 0) {
267 result->add(key, scenario->get(key));
271 Size newKeyIndex = 0;
272 std::vector<Size> indices(c0->second.size(), 0);
275 workingIndex = indices.size() - 1;
276 while (workingIndex >= 0 && indices[workingIndex] == c1->second[workingIndex].size()) {
278 if (workingIndex >= 0)
279 indices[workingIndex] = 0;
281 if (workingIndex >= 0) {
283 auto iValue = interpolatedValue(c0->second, c1->second, indices, k, scenario);
284 TLOG(
"Add "<< key <<
" interpolated value = " << iValue);
285 result->add(key, iValue);
286 indices[workingIndex]++;
288 }
while (workingIndex >= 0);
295 const QuantLib::ext::shared_ptr<Scenario>& scenario,
296 const std::map<std::pair<RiskFactorKey::KeyType, std::string>, std::vector<std::vector<Real>>>& oldCoordinates,
297 const std::set<std::tuple<
RiskFactorKey::KeyType, std::string, std::vector<std::vector<Real>>>>& newCoordinates) {
299 std::map<std::pair<RiskFactorKey::KeyType, std::string>, std::vector<std::vector<Real>>> newCoordinatesMap;
300 for (
const auto& [key,
name, coordinates] : newCoordinates) {
301 newCoordinatesMap[{key,
name}] = coordinates;
303 return recastScenario(scenario, oldCoordinates, newCoordinatesMap);
Data types stored in the scenario class.
KeyType
Risk Factor types.
@ YoYInflationCapFloorVolatility
@ ZeroInflationCapFloorVolatility
Real getDifferenceScenario(const RiskFactorKey::KeyType keyType, const Real v1, const Real v2)
QuantLib::ext::shared_ptr< Scenario > recastScenario(const QuantLib::ext::shared_ptr< Scenario > &scenario, const std::map< std::pair< RiskFactorKey::KeyType, std::string >, std::vector< std::vector< Real > > > &oldCoordinates, const std::map< std::pair< RiskFactorKey::KeyType, std::string >, std::vector< std::vector< Real > > > &newCoordinates)
Real addDifferenceToScenario(const RiskFactorKey::KeyType keyType, const Real v, const Real d)
Size size(const ValueType &v)
Scenario utility functions.