Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
jointnpvcube.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2019 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
20
21#include <ql/errors.hpp>
22
23#include <numeric>
24#include <set>
25
26namespace ore {
27namespace analytics {
28
29JointNPVCube::JointNPVCube(const QuantLib::ext::shared_ptr<NPVCube>& cube1, const QuantLib::ext::shared_ptr<NPVCube>& cube2,
30 const std::set<std::string>& ids, const bool requireUniqueIds,
31 const std::function<Real(Real a, Real x)>& accumulator, const Real accumulatorInit)
32 : JointNPVCube({cube1, cube2}, ids, requireUniqueIds, accumulator, accumulatorInit) {}
33
34JointNPVCube::JointNPVCube(const std::vector<QuantLib::ext::shared_ptr<NPVCube>>& cubes, const std::set<std::string>& ids,
35 const bool requireUniqueIds, const std::function<Real(Real a, Real x)>& accumulator,
36 const Real accumulatorInit)
37 : NPVCube(), cubes_(cubes), accumulator_(accumulator), accumulatorInit_(accumulatorInit) {
38
39 // check we have at least one input cube
40
41 QL_REQUIRE(!cubes.empty(), "JointNPVCube: at least one cube must be given");
42
43 // check that the dimensions are consistent
44
45 for (Size i = 1; i < cubes.size(); ++i) {
46 QL_REQUIRE(cubes_[i]->numDates() == cubes_[0]->numDates(),
47 "JointNPVCube: numDates do not match for cube #"
48 << i << " (" << cubes[i]->numDates() << " vs. cube #0 (" << cubes_[0]->numDates() << ")");
49 QL_REQUIRE(cubes_[i]->samples() == cubes_[0]->samples(),
50 "JointNPVCube: samples do not match for cube #" << i << " (" << cubes_[i]->samples()
51 << " vs. cube #0 (" << cubes_[0]->samples() << ")");
52 QL_REQUIRE(cubes_[i]->depth() == cubes_[0]->depth(), "JointNPVCube: depth do not match for cube #"
53 << i << " (" << cubes_[i]->depth() << " vs. cube #0 ("
54 << cubes[0]->depth() << ")");
55 }
56
57 std::set<std::string> allIds;
58 if (!ids.empty()) {
59 // if ids are given, these define the ids in the result cube
60 allIds = ids;
61 } else {
62 // otherwise the ids in the source cubes define the ids in the result cube
63 for (Size i = 0; i < cubes_.size(); ++i) {
64 for (auto const& [id, ignored] : cubes_[i]->idsAndIndexes()) {
65 const auto& [ignored2, success] = allIds.insert(id);
66 QL_REQUIRE(!requireUniqueIds || success,
67 "JointNPVSensiCube: input cubes have duplicate id '" << id << "', this is not allowed");
68 }
69 }
70 }
71
72 // build list of result cube ids
73 Size pos = 0;
74 for (const auto& id : allIds) {
75 idIdx_[id] = pos++;
76 }
77
78 // populate cubeAndId_ vector which is the basis for the lookup
79 cubeAndId_.resize(idIdx_.size());
80 for (const auto& [id, jointPos] : idIdx_) {
81 for (auto const& c : cubes_) {
82 auto searchIt = c->idsAndIndexes().find(id);
83 if (searchIt != c->idsAndIndexes().end()) {
84 cubeAndId_[jointPos].insert(std::make_pair(c, searchIt->second));
85 }
86 }
87 // internal consistency checks
88 QL_REQUIRE(cubeAndId_[jointPos].size() >= 1,
89 "JointNPVCube: internal error, got no input cubes for id '" << id << "'");
90 QL_REQUIRE(!requireUniqueIds || cubeAndId_[jointPos].size() == 1,
91 "JointNPVCube: internal error, got more than one input cube for id '"
92 << id << "', but unique input ids qre required");
93 }
94}
95
96Size JointNPVCube::numIds() const { return idIdx_.size(); }
97
98Size JointNPVCube::numDates() const { return cubes_[0]->numDates(); }
99
100Size JointNPVCube::samples() const { return cubes_[0]->samples(); }
101
102Size JointNPVCube::depth() const { return cubes_[0]->depth(); }
103
104const std::map<std::string, Size>& JointNPVCube::idsAndIndexes() const { return idIdx_; }
105
106const std::vector<QuantLib::Date>& JointNPVCube::dates() const { return cubes_[0]->dates(); }
107
108QuantLib::Date JointNPVCube::asof() const { return cubes_[0]->asof(); }
109
110std::set<std::pair<QuantLib::ext::shared_ptr<NPVCube>, Size>> JointNPVCube::cubeAndId(Size id) const {
111 QL_REQUIRE(id < cubeAndId_.size(),
112 "JointNPVCube: id (" << id << ") out of range, have " << cubeAndId_.size() << " ids");
113 return cubeAndId_[id];
114}
115
116Real JointNPVCube::getT0(Size id, Size depth) const {
117 auto cids = cubeAndId(id);
118 if (cids.size() == 1)
119 return cids.begin()->first->getT0(cids.begin()->second, depth);
120 Real tmp = accumulatorInit_;
121 for (auto const& p : cids)
122 tmp = accumulator_(tmp, p.first->getT0(p.second, depth));
123 return tmp;
124}
125
126void JointNPVCube::setT0(Real value, Size id, Size depth) {
127 auto c = cubeAndId(id);
128 QL_REQUIRE(c.size() == 1,
129 "JointNPVCube::setT0(): not allowed, because id '" << id << "' occurs in more than one input cube");
130 (*c.begin()).first->setT0(value, (*c.begin()).second, depth);
131}
132
133Real JointNPVCube::get(Size id, Size date, Size sample, Size depth) const {
134 auto cids = cubeAndId(id);
135 if (cids.size() == 1)
136 return cids.begin()->first->get(cids.begin()->second, date, sample, depth);
137 Real tmp = accumulatorInit_;
138 for (auto const& p : cids)
139 tmp = accumulator_(tmp, p.first->get(p.second, date, sample, depth));
140 return tmp;
141}
142
143void JointNPVCube::set(Real value, Size id, Size date, Size sample, Size depth) {
144 auto c = cubeAndId(id);
145 QL_REQUIRE(c.size() == 1,
146 "JointNPVCube::set(): not allowed, because id '" << id << "' occurs in more than one input cube");
147 (*c.begin()).first->set(value, (*c.begin()).second, date, sample, depth);
148}
149
150} // namespace analytics
151} // namespace ore
JointNPVCube(const QuantLib::ext::shared_ptr< NPVCube > &cube1, const QuantLib::ext::shared_ptr< NPVCube > &cube2, const std::set< std::string > &ids={}, const bool requireUniqueIds=true, const std::function< Real(Real a, Real x)> &accumulator=[](Real a, Real x) { return a+x;}, const Real accumulatorInit=0.0)
const std::function< Real(Real a, Real x)> accumulator_
void set(Real value, Size id, Size date, Size sample, Size depth=0) override
Set a value in the cube using index.
Size numDates() const override
const std::map< std::string, Size > & idsAndIndexes() const override
Get a map of id and their index position in this cube.
Real getT0(Size id, Size depth=0) const override
Get a T0 value from the cube using index.
std::set< std::pair< QuantLib::ext::shared_ptr< NPVCube >, Size > > cubeAndId(Size id) const
Size numIds() const override
Return the length of each dimension.
const std::vector< QuantLib::ext::shared_ptr< NPVCube > > cubes_
const std::vector< QuantLib::Date > & dates() const override
Get the vector of dates for this cube.
Size depth() const override
QuantLib::Date asof() const override
Return the asof date (T0 date)
std::map< std::string, Size > idIdx_
Size samples() const override
void setT0(Real value, Size id, Size depth=0) override
Set a value in the cube using index.
std::vector< std::set< std::pair< QuantLib::ext::shared_ptr< NPVCube >, Size > > > cubeAndId_
Real get(Size id, Size date, Size sample, Size depth=0) const override
Get a value from the cube using index.
NPV Cube class stores both future and current NPV values.
Definition: npvcube.hpp:53
const std::set< std::string > ids() const
Get a set of all ids in the cube.
Definition: npvcube.hpp:75
SafeStack< ValueType > value
join n cubes in terms of stored ids
Size size(const ValueType &v)