Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
sensitivitycubestream.cpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 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 pr 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
23
24using QuantLib::Real;
25
26using std::map;
27
28namespace ore {
29namespace analytics {
30
32
33SensitivityCubeStream::SensitivityCubeStream(const QuantLib::ext::shared_ptr<SensitivityCube>& cube, const string& currency)
34 : SensitivityCubeStream(std::vector<QuantLib::ext::shared_ptr<SensitivityCube>>{cube}, currency) {}
35
36SensitivityCubeStream::SensitivityCubeStream(const std::vector<QuantLib::ext::shared_ptr<SensitivityCube>>& cubes,
37 const string& currency)
38 : cubes_(cubes), currency_(currency), canComputeGamma_(false) {
39
40 // Set the value of canComputeGamma_ based on up and down risk factors.
41
42 canComputeGamma_ = true;
43 for (const auto& cube : cubes_) {
44 const auto& upFactors = cube->upFactors();
45 const auto& downFactors = cube->downFactors();
46 if (upFactors.size() == downFactors.size() &&
47 equal(upFactors.begin(), upFactors.end(), downFactors.begin(),
48 [](const auto& a, const auto& b) { return a.first == b.first; }))
49 continue;
50 canComputeGamma_ = false;
51 break;
52 }
53
54 reset();
55}
56
58
59 if (cubes_.size() == 0)
60 return SensitivityRecord();
61
62 while (tradeIdx_ != cubes_[currentCubeIdx_]->tradeIdx().end() && currentDeltaKey_ == currentDeltaKeys_.end() &&
64 ++tradeIdx_;
66 }
67
68 if (tradeIdx_ == cubes_[currentCubeIdx_]->tradeIdx().end()) {
69 if (currentCubeIdx_ < cubes_.size() - 1) {
71 tradeIdx_ = cubes_[currentCubeIdx_]->tradeIdx().begin();
73 return next();
74 } else {
75 return SensitivityRecord();
76 }
77 }
78
80 Size tradeIdx = tradeIdx_->second;
81 sr.tradeId = tradeIdx_->first;
82 sr.isPar = false;
84 sr.baseNpv = cubes_[currentCubeIdx_]->npv(tradeIdx);
85
87 auto fd = cubes_[currentCubeIdx_]->upFactors().at(*currentDeltaKey_);
89 sr.desc_1 = fd.factorDesc;
90 sr.shift_1 = fd.targetShiftSize;
94 else
95 sr.gamma = Null<Real>();
98 auto fd = cubes_[currentCubeIdx_]->crossFactors().at(*currentCrossGammaKey_);
99 sr.key_1 = currentCrossGammaKey_->first;
100 sr.desc_1 = std::get<0>(fd).factorDesc;
101 sr.shift_1 = std::get<0>(fd).targetShiftSize;
102 sr.key_2 = currentCrossGammaKey_->second;
103 sr.desc_2 = std::get<1>(fd).factorDesc;
104 sr.shift_2 = std::get<1>(fd).targetShiftSize;
105 sr.gamma = cubes_[currentCubeIdx_]->crossGamma(tradeIdx_->first, *currentCrossGammaKey_);
107 }
108
109 TLOG("Next record is: " << sr);
110 return sr;
111}
112
114 currentDeltaKeys_.clear();
116
117 if (tradeIdx_ != cubes_[currentCubeIdx_]->tradeIdx().end()) {
118
119 // add delta keys
120
121 for (auto const& [idx, _] : cubes_[currentCubeIdx_]->npvCube()->getTradeNPVs(tradeIdx_->second)) {
122 if (auto k = cubes_[currentCubeIdx_]->upDownFactor(idx); k.keytype != RiskFactorKey::KeyType::None)
123 currentDeltaKeys_.insert(k);
124 }
125
126 // add cross gamma keys
127
128 for (auto const& [crossPair, data] : cubes_[currentCubeIdx_]->crossFactors()) {
129 // scaling of cross gamma is not relevant here, so we use 1
130 if (!close_enough(cubes_[currentCubeIdx_]->crossGamma(tradeIdx_->second, std::get<0>(data).index,
131 std::get<1>(data).index, std::get<2>(data), 1.0, 1.0),
132 0.0)) {
134
135 // make sure, delta keys contain both cross keys, that's a guarantee of the SensitivityCubeStream
136
137 currentDeltaKeys_.insert(crossPair.first);
138 currentDeltaKeys_.insert(crossPair.second);
139 }
140 }
141 }
142
145}
146
148 currentCubeIdx_ = 0;
149 if (cubes_.size() > 0) {
150 tradeIdx_ = cubes_[currentCubeIdx_]->tradeIdx().begin();
152 }
153}
154
155} // namespace analytics
156} // namespace ore
SensitivityCube is a wrapper for an npvCube that gives easier access to the underlying cube elements.
std::pair< RiskFactorKey, RiskFactorKey > crossPair
SensitivityCubeStream(const QuantLib::ext::shared_ptr< SensitivityCube > &cube, const std::string &currency)
std::string currency_
Currency of the sensitivities in the SensitivityCubes.
std::set< std::pair< RiskFactorKey, RiskFactorKey > > currentCrossGammaKeys_
std::map< std::string, QuantLib::Size >::const_iterator tradeIdx_
Current trade iterator.
std::set< RiskFactorKey >::const_iterator currentDeltaKey_
std::vector< QuantLib::ext::shared_ptr< SensitivityCube > > cubes_
Handle on the SensitivityCubes.
bool canComputeGamma_
Can only compute gamma if the up and down risk factors align.
std::set< std::pair< RiskFactorKey, RiskFactorKey > >::const_iterator currentCrossGammaKey_
std::set< RiskFactorKey > currentDeltaKeys_
Current delta risk factor keys to process and iterators.
Size currentCubeIdx_
Current cube index in vector.
void reset() override
Resets the stream so that SensitivityRecord objects can be streamed again.
data
#define TLOG(text)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Filter equal(Filter x, const Filter &y)
SensitivityCube::crossPair crossPair
Class for streaming SensitivityRecords from a SensitivityCube.
Shift scenario generation.