22#include <ql/errors.hpp>
34 : setCategories_(categories) {
37 for (
const auto& kv : setCategories_) {
38 categories_[kv.first] = bind(&SensitivityAggregator::inCategory,
this, std::placeholders::_1, kv.first);
45SensitivityAggregator::SensitivityAggregator(
const map<
string, function<
bool(
string)>>& categories)
46 : categories_(categories) {
52void SensitivityAggregator::aggregate(
SensitivityStream& ss,
const QuantLib::ext::shared_ptr<ScenarioFilter>& filter) {
59 if (!sr.isCrossGamma() && !
filter->allow(sr.key_1))
61 if (sr.isCrossGamma() && (!
filter->allow(sr.key_1) || !
filter->allow(sr.key_2)))
65 string tradeId = sr.tradeId;
69 for (
const auto& kv : categories_) {
71 if (kv.second(tradeId)) {
72 DLOG(
"Updating aggregated sensitivities for category " << kv.first <<
" with record: " << sr);
73 add(sr, aggRecords_[kv.first]);
79void SensitivityAggregator::reset() {
87const set<SensitivityRecord>& SensitivityAggregator::sensitivities(
const string& category)
const {
89 auto it = aggRecords_.find(category);
90 QL_REQUIRE(it != aggRecords_.end(),
91 "The category " << category <<
" was not used in the construction of the SensitivityAggregator");
96void SensitivityAggregator::generateDeltaGamma(
const string& category, map<RiskFactorKey, Real>& deltas,
97 map<CrossPair, Real>& gammas) {
99 auto srs = sensitivities(category);
100 for (
const auto& sr : srs) {
101 if (!sr.isCrossGamma()) {
102 QL_REQUIRE(deltas.count(sr.key_1) == 0,
103 "Duplicate sensitivity entry for risk factor key " << sr.key_1 <<
" in the set");
104 deltas[sr.key_1] = sr.delta;
105 gammas[std::make_pair(sr.key_1, sr.key_1)] = sr.gamma;
108 sr.key_1 < sr.key_2 ? std::make_pair(sr.key_1, sr.key_2) : std::make_pair(sr.key_2, sr.key_1);
109 QL_REQUIRE(gammas.count(keyPair) == 0,
"Duplicate sensitivity entry for cross gamma pair ["
110 << keyPair.first <<
", " << keyPair.second <<
"] in the set");
111 gammas[keyPair] = sr.gamma;
116 for (
const auto& kv : gammas) {
117 QL_REQUIRE(deltas.count(kv.first.first) > 0,
118 "The key " << kv.first.first <<
" is in the cross gammas but not in the deltas");
119 QL_REQUIRE(deltas.count(kv.first.second) > 0,
120 "The key " << kv.first.second <<
" is in the cross gammas but not in the deltas");
124void SensitivityAggregator::init() {
126 for (
const auto& kv : categories_) {
127 aggRecords_[kv.first] = {};
133 auto p = records.insert(sr);
136 p.first->baseNpv += sr.
baseNpv;
137 p.first->delta += sr.
delta;
138 p.first->gamma += sr.
gamma;
142bool SensitivityAggregator::inCategory(
const string& tradeId,
const string& category)
const {
143 QL_REQUIRE(setCategories_.count(category),
"The category " << category <<
" is not valid");
144 auto tradeIds = setCategories_.at(category);
145 for (
auto it = tradeIds.begin(); it != tradeIds.end(); ++it) {
146 if (it->first == tradeId)
A scenario filter can exclude certain key from updating the scenario.
SensitivityAggregator(const std::map< std::string, std::set< std::pair< std::string, QuantLib::Size > > > &categories)
Base Class for streaming SensitivityRecords.
virtual void reset()=0
Resets the stream so that SensitivityRecord objects can be streamed again.
virtual SensitivityRecord next()=0
Returns the next SensitivityRecord in the stream.
SafeStack< Filter > filter
Class for aggregating SensitivityRecords.