Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
Public Member Functions | Private Member Functions | Private Attributes | List of all members
SensitivityScenarioGenerator Class Reference

Sensitivity Scenario Generator. More...

#include <orea/scenario/sensitivityscenariogenerator.hpp>

+ Inheritance diagram for SensitivityScenarioGenerator:
+ Collaboration diagram for SensitivityScenarioGenerator:

Public Member Functions

 SensitivityScenarioGenerator (const QuantLib::ext::shared_ptr< SensitivityScenarioData > &sensitivityData, const QuantLib::ext::shared_ptr< Scenario > &baseScenario, const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > &simMarketData, const QuantLib::ext::shared_ptr< ScenarioSimMarket > &simMarket, const QuantLib::ext::shared_ptr< ScenarioFactory > &sensiScenarioFactory, const bool overrideTenors, const std::string &sensitivityTemplate=std::string(), const bool continueOnError=false, const QuantLib::ext::shared_ptr< Scenario > &baseScenarioAbsolute=nullptr)
 Constructor. More...
 
 ~SensitivityScenarioGenerator ()
 Default destructor. More...
 
const std::map< RiskFactorKey, QuantLib::Real > & shiftSizes () const
 
const std::map< RiskFactorKey, ShiftScheme > & shiftSchemes () const
 
const std::map< RiskFactorKey, QuantLib::Real > & baseValues () const
 
Size numScenarios () const
 
QuantLib::ext::shared_ptr< ScenariobaseScenarioAbsolute () const
 
- Public Member Functions inherited from ShiftScenarioGenerator
 ShiftScenarioGenerator (const QuantLib::ext::shared_ptr< Scenario > &baseScenario, const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > &simMarketData, const QuantLib::ext::weak_ptr< ScenarioSimMarket > &simMarket)
 Constructor. More...
 
 ~ShiftScenarioGenerator ()
 Default destructor. More...
 
QuantLib::ext::shared_ptr< Scenarionext (const Date &d) override
 Scenario Generator interface. More...
 
void reset () override
 Reset the generator so calls to next() return the first scenario. More...
 
Size samples ()
 Inspectors. More...
 
const QuantLib::ext::shared_ptr< Scenario > & baseScenario ()
 Return the base scenario, i.e. cached initial values of all relevant market points. More...
 
const std::vector< QuantLib::ext::shared_ptr< Scenario > > & scenarios ()
 Return vector of sensitivity scenarios, scenario 0 is the base scenario. More...
 
std::vector< ScenarioDescriptionscenarioDescriptions ()
 Return vector of scenario descriptions. More...
 
const std::map< RiskFactorKey, std::string > & keyToFactor ()
 
const std::map< std::string, RiskFactorKey > & factorToKey ()
 Return revers map of factors to RiskFactorKeys. More...
 
void applyShift (Size j, Real shiftSize, bool up, ShiftType type, const vector< Time > &shiftTimes, const vector< Real > &values, const vector< Time > &times, vector< Real > &shiftedValues, bool initialise)
 Apply 1d triangular shift to 1d data such as yield curves, public to allow test suite access. More...
 
void applyShift (Size j, Size k, Real shiftSize, bool up, ShiftType type, const vector< Time > &shiftX, const vector< Time > &shiftY, const vector< Time > &dataX, const vector< Time > &dataY, const vector< vector< Real > > &data, vector< vector< Real > > &shiftedData, bool initialise)
 Apply 2d shift to 2d matrix such as swaption volatilities, public to allow test suite access. More...
 
QuantLib::ext::shared_ptr< ScenariobaseScenario () const
 return the base scenario More...
 
- Public Member Functions inherited from ScenarioGenerator
virtual ~ScenarioGenerator ()
 Default destructor. More...
 
virtual QuantLib::ext::shared_ptr< Scenarionext (const Date &d)=0
 Return the next scenario for the given date. More...
 
virtual void reset ()=0
 Reset the generator so calls to next() return the first scenario. More...
 

Private Member Functions

ShiftType getShiftType (SensitivityScenarioData::ShiftData &data) const
 
Real getShiftSize (SensitivityScenarioData::ShiftData &data) const
 
ShiftScheme getShiftScheme (SensitivityScenarioData::ShiftData &data) const
 
bool isScenarioRelevant (bool up, SensitivityScenarioData::ShiftData &data) const
 
void storeShiftData (const RiskFactorKey &key, const Real rate, const Real newRate)
 
void generateScenarios ()
 
void generateYieldCurveScenarios (bool up)
 
void generateDiscountCurveScenarios (bool up)
 
void generateIndexCurveScenarios (bool up)
 
void generateFxScenarios (bool up)
 
void generateEquityScenarios (bool up)
 
void generateDividendYieldScenarios (bool up)
 
void generateSwaptionVolScenarios (bool up)
 
void generateYieldVolScenarios (bool up)
 
void generateFxVolScenarios (bool up)
 
void generateEquityVolScenarios (bool up)
 
void generateCapFloorVolScenarios (bool up)
 
void generateSurvivalProbabilityScenarios (bool up)
 
void generateCdsVolScenarios (bool up)
 
void generateZeroInflationScenarios (bool up)
 
void generateZeroInflationCapFloorVolScenarios (bool up)
 
void generateYoYInflationScenarios (bool up)
 
void generateYoYInflationCapFloorVolScenarios (bool up)
 
void generateBaseCorrelationScenarios (bool up)
 
void generateCommodityCurveScenarios (bool up)
 
void generateCommodityVolScenarios (bool up)
 
void generateSecuritySpreadScenarios (bool up)
 
void generateCorrelationScenarios (bool up)
 
void generateGenericYieldVolScenarios (bool up, RiskFactorKey::KeyType rfType)
 
ScenarioDescription discountScenarioDescription (string ccy, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription indexScenarioDescription (string index, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription yieldScenarioDescription (string name, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription fxScenarioDescription (string ccypair, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription fxVolScenarioDescription (string ccypair, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription equityScenarioDescription (string equity, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription dividendYieldScenarioDescription (string equity, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription equityVolScenarioDescription (string equity, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription swaptionVolScenarioDescription (string ccy, Size expiryBucket, Size termBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription yieldVolScenarioDescription (string securityId, Size expiryBucket, Size termBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription capFloorVolScenarioDescription (string ccy, Size expiryBucket, Size strikeBucket, bool up, bool isAtm, ShiftScheme shiftScheme)
 
ScenarioDescription survivalProbabilityScenarioDescription (string name, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription CdsVolScenarioDescription (string name, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription zeroInflationScenarioDescription (string index, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription yoyInflationScenarioDescription (string index, Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription zeroInflationCapFloorVolScenarioDescription (string name, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription yoyInflationCapFloorVolScenarioDescription (string name, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription baseCorrelationScenarioDescription (string indexName, Size lossLevelBucket, Size termBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription commodityCurveScenarioDescription (const std::string &commodityName, QuantLib::Size bucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription commodityVolScenarioDescription (const std::string &commodityName, QuantLib::Size expiryBucket, QuantLib::Size strikeBucket, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription securitySpreadScenarioDescription (string bond, bool up, ShiftScheme shiftScheme)
 
ScenarioDescription correlationScenarioDescription (string pair, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
 

Private Attributes

QuantLib::ext::shared_ptr< SensitivityScenarioDatasensitivityData_
 
QuantLib::ext::shared_ptr< ScenarioFactorysensiScenarioFactory_
 
std::string sensitivityTemplate_
 
const bool overrideTenors_
 
const bool continueOnError_
 
std::map< RiskFactorKey, QuantLib::Real > shiftSizes_
 Holds the shift sizes for each risk factor key. More...
 
std::map< RiskFactorKey, ShiftSchemeshiftSchemes_
 Holds the delta shift schemes for each risk factor key. More...
 
std::map< RiskFactorKey, QuantLib::Real > baseValues_
 Holds the base valuesfor each risk factor key. More...
 
QuantLib::ext::shared_ptr< ScenariobaseScenarioAbsolute_
 

Additional Inherited Members

- Protected Attributes inherited from ShiftScenarioGenerator
const QuantLib::ext::shared_ptr< ScenariobaseScenario_
 
const QuantLib::ext::shared_ptr< ScenarioSimMarketParameterssimMarketData_
 
const QuantLib::ext::weak_ptr< ScenarioSimMarketsimMarket_
 
std::vector< QuantLib::ext::shared_ptr< Scenario > > scenarios_
 
Size counter_
 
std::vector< ScenarioDescriptionscenarioDescriptions_
 
std::map< RiskFactorKey, std::string > keyToFactor_
 
std::map< std::string, RiskFactorKeyfactorToKey_
 

Detailed Description

Sensitivity Scenario Generator.

This class builds a vector of sensitivity scenarios based on instructions in SensitivityScenarioData and ScenarioSimMarketParameters objects passed.

The ScenarioSimMarketParameters object determines the scope and structure of a "simulation" market (currencies, currency pairs, curve tenor points, vol matrix expiries and terms/strikes etc) to which sensitivity scenarios are applied in order to compute their NPV impact.

The SensitivityScenarioData object determines the structure of shift curves (shift tenor points can differ from the simulation market's tenor points), as well as type (relative/absolute) and size of shifts applied.

The generator then produces comprehensive scenarios that can be applied to the simulation market, i.e. covering all quotes in the simulation market, possibly filled with "base" scenario values.

Both UP and DOWN shifts are generated in order to facilitate delta and gamma calculation.

The generator currently covers the IR/FX asset class, with shifts for the following term structure types:

For Credit the generator covers shifts to the following termstructure types:

To apply shifts to the integrated hazard rates let:

The relationship between these three can be expressed as:

\[ S(t) = e^{-&Lambda(t) t} \]

\[ &Lambda(t) = \frac{ \int_{0}^t &lambda(t) du}{t} \]

The survival probability quotes from the scenarioSimMarket default curves are then converted as follows:

\[ &Lambda(t) = - \frac{ ln( S(t) )}{t} \]

Note:

If sensitivityData_->generateSpreadScenarios() = true spread scenarios will be generated for supported risk factor types.

Definition at line 102 of file sensitivityscenariogenerator.hpp.

Constructor & Destructor Documentation

◆ SensitivityScenarioGenerator()

SensitivityScenarioGenerator ( const QuantLib::ext::shared_ptr< SensitivityScenarioData > &  sensitivityData,
const QuantLib::ext::shared_ptr< Scenario > &  baseScenario,
const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > &  simMarketData,
const QuantLib::ext::shared_ptr< ScenarioSimMarket > &  simMarket,
const QuantLib::ext::shared_ptr< ScenarioFactory > &  sensiScenarioFactory,
const bool  overrideTenors,
const std::string &  sensitivityTemplate = std::string(),
const bool  continueOnError = false,
const QuantLib::ext::shared_ptr< Scenario > &  baseScenarioAbsolute = nullptr 
)

Constructor.

Definition at line 43 of file sensitivityscenariogenerator.cpp.

50 : ShiftScenarioGenerator(baseScenario, simMarketData, simMarket), sensitivityData_(sensitivityData),
51 sensiScenarioFactory_(sensiScenarioFactory), sensitivityTemplate_(sensitivityTemplate),
52 overrideTenors_(overrideTenors), continueOnError_(continueOnError),
54
55 QL_REQUIRE(sensitivityData_, "SensitivityScenarioGenerator: sensitivityData is null");
56
58}
QuantLib::ext::shared_ptr< ScenarioFactory > sensiScenarioFactory_
QuantLib::ext::shared_ptr< SensitivityScenarioData > sensitivityData_
QuantLib::ext::shared_ptr< Scenario > baseScenarioAbsolute() const
QuantLib::ext::shared_ptr< Scenario > baseScenarioAbsolute_
ShiftScenarioGenerator(const QuantLib::ext::shared_ptr< Scenario > &baseScenario, const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > &simMarketData, const QuantLib::ext::weak_ptr< ScenarioSimMarket > &simMarket)
Constructor.
const QuantLib::ext::shared_ptr< Scenario > & baseScenario()
Return the base scenario, i.e. cached initial values of all relevant market points.
+ Here is the call graph for this function:

◆ ~SensitivityScenarioGenerator()

Default destructor.

Definition at line 114 of file sensitivityscenariogenerator.hpp.

114{};

Member Function Documentation

◆ shiftSizes()

const std::map< RiskFactorKey, QuantLib::Real > & shiftSizes ( ) const

Return the map of absolute shift sizes by risk factor key for this generator

Warning:
Where there are tenor specific shifts the shift size is only meaningful if the tenors in the sensitivity configuration line up with the tenors in the simulation market configuration. If this is not the case, an absolute shift size of Null<Real>() is added for the given risk factor key

Definition at line 124 of file sensitivityscenariogenerator.hpp.

124{ return shiftSizes_; }
std::map< RiskFactorKey, QuantLib::Real > shiftSizes_
Holds the shift sizes for each risk factor key.

◆ shiftSchemes()

const std::map< RiskFactorKey, ShiftScheme > & shiftSchemes ( ) const

Definition at line 127 of file sensitivityscenariogenerator.hpp.

127{ return shiftSchemes_; }
std::map< RiskFactorKey, ShiftScheme > shiftSchemes_
Holds the delta shift schemes for each risk factor key.

◆ baseValues()

const std::map< RiskFactorKey, QuantLib::Real > & baseValues ( ) const

Similarly, reeturn the base values for each risk factor

Definition at line 130 of file sensitivityscenariogenerator.hpp.

130{ return baseValues_; }
std::map< RiskFactorKey, QuantLib::Real > baseValues_
Holds the base valuesfor each risk factor key.
+ Here is the caller graph for this function:

◆ numScenarios()

Size numScenarios ( ) const

Definition at line 132 of file sensitivityscenariogenerator.hpp.

132{ return scenarios_.size(); }
std::vector< QuantLib::ext::shared_ptr< Scenario > > scenarios_

◆ baseScenarioAbsolute()

QuantLib::ext::shared_ptr< Scenario > baseScenarioAbsolute ( ) const

Definition at line 134 of file sensitivityscenariogenerator.hpp.

134{ return baseScenarioAbsolute_; }

◆ getShiftType()

ShiftType getShiftType ( SensitivityScenarioData::ShiftData data) const
private

Definition at line 267 of file sensitivityscenariogenerator.cpp.

267 {
268 if (auto it = data.keyedShiftType.find(sensitivityTemplate_); it != data.keyedShiftType.end())
269 return it->second;
270 return data.shiftType;
271}
data
+ Here is the caller graph for this function:

◆ getShiftSize()

Real getShiftSize ( SensitivityScenarioData::ShiftData data) const
private

Definition at line 273 of file sensitivityscenariogenerator.cpp.

273 {
274 if (auto it = data.keyedShiftSize.find(sensitivityTemplate_); it != data.keyedShiftSize.end())
275 return it->second;
276 return data.shiftSize;
277}
+ Here is the caller graph for this function:

◆ getShiftScheme()

ShiftScheme getShiftScheme ( SensitivityScenarioData::ShiftData data) const
private

Definition at line 279 of file sensitivityscenariogenerator.cpp.

279 {
280 if (auto it = data.keyedShiftScheme.find(sensitivityTemplate_); it != data.keyedShiftScheme.end())
281 return it->second;
282 return data.shiftScheme;
283}
+ Here is the caller graph for this function:

◆ isScenarioRelevant()

bool isScenarioRelevant ( bool  up,
SensitivityScenarioData::ShiftData data 
) const
private

Definition at line 285 of file sensitivityscenariogenerator.cpp.

285 {
286 ShiftScheme scheme = getShiftScheme(data);
287 return sensitivityData_->computeGamma() || (up && (scheme == ShiftScheme::Forward)) ||
288 (!up && scheme == ShiftScheme::Backward) || scheme == ShiftScheme::Central;
289}
ShiftScheme getShiftScheme(SensitivityScenarioData::ShiftData &data) const
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ storeShiftData()

void storeShiftData ( const RiskFactorKey key,
const Real  rate,
const Real  newRate 
)
private

Definition at line 291 of file sensitivityscenariogenerator.cpp.

291 {
292 if (shiftSizes_.find(key) == shiftSizes_.end()) {
293 shiftSizes_[key] = std::abs(newRate - rate);
294 baseValues_[key] = rate;
295 }
296}
+ Here is the caller graph for this function:

◆ generateScenarios()

void generateScenarios ( )
private

Definition at line 85 of file sensitivityscenariogenerator.cpp.

85 {
86 Date asof = baseScenario_->asof();
87
88 QL_REQUIRE(sensitivityData_->crossGammaFilter().empty() || sensitivityData_->computeGamma(),
89 "SensitivityScenarioGenerator::generateScenarios(): if gamma computation is disabled, the cross gamma "
90 "filter must be empty");
91
94
97
100
101 if (simMarketData_->simulateFxSpots()) {
103 generateFxScenarios(false);
104 }
105
108
109 if (simMarketData_->simulateDividendYield()) {
112 }
113
116
119
120 if (simMarketData_->simulateYoYInflationCapFloorVols()) {
123 }
124
125 if (simMarketData_->simulateZeroInflationCapFloorVols()) {
128 }
129
130 if (simMarketData_->simulateFXVols()) {
133 }
134
135 if (simMarketData_->simulateEquityVols()) {
138 }
139
140 if (simMarketData_->simulateSwapVols()) {
143 }
144
145 if (simMarketData_->simulateYieldVols()) {
148 }
149
150 if (simMarketData_->simulateCapFloorVols()) {
153 }
154
155 if (simMarketData_->simulateSurvivalProbabilities()) {
158 }
159
160 if (simMarketData_->simulateCdsVols()) {
163 }
164
165 if (simMarketData_->simulateBaseCorrelations()) {
168 }
169
170 if (simMarketData_->commodityCurveSimulate()) {
173 }
174
175 if (simMarketData_->commodityVolSimulate()) {
178 }
179
180 if (simMarketData_->securitySpreadsSimulate()) {
183 }
184
185 if (simMarketData_->simulateCorrelations()) {
188 }
189
190 // fill keyToFactor and factorToKey maps from scenario descriptions
191
192 DLOG("Fill maps linking factors with RiskFactorKeys");
193 keyToFactor_.clear();
194 factorToKey_.clear();
195 for (Size i = 0; i < scenarioDescriptions_.size(); ++i) {
196 RiskFactorKey key = scenarioDescriptions_[i].key1();
197 string factor = scenarioDescriptions_[i].factor1();
198 keyToFactor_[key] = factor;
199 factorToKey_[factor] = key;
200 DLOG("KeyToFactor map: " << key << " to " << factor);
201 }
202
203 // add simultaneous up-moves in two risk factors for cross gamma calculation
204
205 for (Size i = 0; i < scenarios_.size(); ++i) {
206 ScenarioDescription iDesc = scenarioDescriptions_[i];
207 if (iDesc.type() != ScenarioDescription::Type::Up)
208 continue;
209 string iKeyName = iDesc.keyName1();
210
211 // check if iKey matches filter
212 if (find_if(sensitivityData_->crossGammaFilter().begin(), sensitivityData_->crossGammaFilter().end(),
213 findFactor(iKeyName)) == sensitivityData_->crossGammaFilter().end())
214 continue;
215
216 for (Size j = i + 1; j < scenarios_.size(); ++j) {
217 ScenarioDescription jDesc = scenarioDescriptions_[j];
218 if (jDesc.type() != ScenarioDescription::Type::Up)
219 continue;
220 string jKeyName = jDesc.keyName1();
221
222 // check if jKey matches filter
223 if (find_if(sensitivityData_->crossGammaFilter().begin(), sensitivityData_->crossGammaFilter().end(),
224 findPair(iKeyName, jKeyName)) == sensitivityData_->crossGammaFilter().end())
225 continue;
226
227 // build cross scenario
228 QuantLib::ext::shared_ptr<Scenario> crossScenario =
229 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
230
231 for (auto const& k : baseScenario_->keys()) {
232 Real v1 = scenarios_[i]->get(k);
233 Real v2 = scenarios_[j]->get(k);
234 Real b = baseScenario_->get(k);
235 if (!close_enough(v1, b) || !close_enough(v2, b))
236 // this is correct for both absolute and relative shifts
237 crossScenario->add(k, v1 + v2 - b);
238 }
239
240 scenarioDescriptions_.push_back(ScenarioDescription(iDesc, jDesc));
241 crossScenario->label(to_string(scenarioDescriptions_.back()));
242 scenarios_.push_back(crossScenario);
243 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << crossScenario->label() << " created");
244 }
245 }
246
247 LOG("sensitivity scenario generator finished generating scenarios.");
248}
std::vector< ScenarioDescription > scenarioDescriptions_
std::map< RiskFactorKey, std::string > keyToFactor_
const QuantLib::ext::shared_ptr< Scenario > baseScenario_
std::map< std::string, RiskFactorKey > factorToKey_
const QuantLib::ext::shared_ptr< ScenarioSimMarketParameters > simMarketData_
#define LOG(text)
#define DLOG(text)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
std::string to_string(const LocationInfo &l)
Date asof(14, Jun, 2018)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateYieldCurveScenarios()

void generateYieldCurveScenarios ( bool  up)
private

Definition at line 621 of file sensitivityscenariogenerator.cpp.

621 {
622 Date asof = baseScenario_->asof();
623 // We can choose to shift fewer yield curves than listed in the market
624 // Log an ALERT if some yield curves in simmarket are excluded from the list
625 for (auto sim_yc : simMarketData_->yieldCurveNames()) {
626 if (sensitivityData_->yieldCurveShiftData().find(sim_yc) == sensitivityData_->yieldCurveShiftData().end()) {
627 WLOG("Yield Curve " << sim_yc << " in simmarket is not included in sensitivities analysis");
628 }
629 }
630
631 for (auto y : sensitivityData_->yieldCurveShiftData()) {
632 string name = y.first;
633 Size n_ten;
634 try {
635 n_ten = simMarketData_->yieldCurveTenors(name).size();
636 } catch (const std::exception& e) {
637 ALOG("skip scenario generation for yield curve " << name << ": " << e.what());
638 continue;
639 }
640 // original curves' buffer
641 std::vector<Real> zeros(n_ten);
642 std::vector<Real> times(n_ten);
643 // buffer for shifted zero curves
644 std::vector<Real> shiftedZeros(n_ten);
645 SensitivityScenarioData::CurveShiftData data = *y.second;
646 if (!isScenarioRelevant(up, data))
647 continue;
648 ShiftType shiftType = getShiftType(data);
649 DayCounter dc = Actual365Fixed();
650 try {
651 if (auto s = simMarket_.lock()) {
652 dc = s->yieldCurve(name)->dayCounter();
653 } else {
654 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
655 }
656 } catch (const std::exception&) {
657 WLOG("Day counter lookup in simulation market failed for yield curve " << name << ", using default A365");
658 }
659
660 Real quote = 0.0;
661 bool valid = true;
662 for (Size j = 0; j < n_ten; ++j) {
663 Date d = asof + simMarketData_->yieldCurveTenors(name)[j];
664 times[j] = dc.yearFraction(asof, d);
665 RiskFactorKey key(RiskFactorKey::KeyType::YieldCurve, name, j);
666 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, quote, continueOnError_);
667 zeros[j] = -std::log(quote) / times[j];
668 }
669 if (!valid)
670 continue;
671
672 const std::vector<Period>& shiftTenors = overrideTenors_ && simMarketData_->hasYieldCurveTenors(name)
673 ? simMarketData_->yieldCurveTenors(name)
674 : data.shiftTenors;
675 checkShiftTenors(shiftTenors, data.shiftTenors, "Yield Curve " + name, continueOnError_);
676 std::vector<Time> shiftTimes(shiftTenors.size());
677 for (Size j = 0; j < shiftTenors.size(); ++j)
678 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
679 Real shiftSize = getShiftSize(data);
680 QL_REQUIRE(shiftTenors.size() > 0, "Discount shift tenors not specified");
681
682 // Can we store a valid shift size?
683 bool validShiftSize = vectorEqual(times, shiftTimes);
684
685 for (Size j = 0; j < shiftTenors.size(); ++j) {
686
687 QuantLib::ext::shared_ptr<Scenario> scenario =
688 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
689
690 // apply zero rate shift at tenor point j
691 applyShift(j, shiftSize, up, shiftType, shiftTimes, zeros, times, shiftedZeros, true);
692
693 // store shifted discount curve in the scenario
694 for (Size k = 0; k < n_ten; ++k) {
695 Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
696 RiskFactorKey key(RFType::YieldCurve, name, k);
697 if (sensitivityData_->useSpreadedTermStructures()) {
698 Real discount = exp(-zeros[k] * times[k]);
699 scenario->add(key, shiftedDiscount / discount);
700 } else {
701 scenario->add(key, shiftedDiscount);
702 }
703
704 // Possibly store valid shift size
705 if (validShiftSize && j == k) {
706 storeShiftData(key, zeros[k], shiftedZeros[k]);
707 }
708 }
709
710 // add this scenario to the scenario vector
711 scenarios_.push_back(scenario);
713 scenario->label(to_string(scenarioDescriptions_.back()));
714 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
715
716 } // end of shift curve tenors
717 }
718 DLOG("Yield curve scenarios done");
719}
ScenarioDescription yieldScenarioDescription(string name, Size bucket, bool up, ShiftScheme shiftScheme)
void storeShiftData(const RiskFactorKey &key, const Real rate, const Real newRate)
bool isScenarioRelevant(bool up, SensitivityScenarioData::ShiftData &data) const
ShiftType getShiftType(SensitivityScenarioData::ShiftData &data) const
Real getShiftSize(SensitivityScenarioData::ShiftData &data) const
void applyShift(Size j, Real shiftSize, bool up, ShiftType type, const vector< Time > &shiftTimes, const vector< Real > &values, const vector< Time > &times, vector< Real > &shiftedValues, bool initialise)
Apply 1d triangular shift to 1d data such as yield curves, public to allow test suite access.
const QuantLib::ext::weak_ptr< ScenarioSimMarket > simMarket_
#define ALOG(text)
#define WLOG(text)
RandomVariable exp(RandomVariable x)
bool vectorEqual(const vector< Real > &v_1, const vector< Real > &v_2)
string name
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateDiscountCurveScenarios()

void generateDiscountCurveScenarios ( bool  up)
private

Definition at line 415 of file sensitivityscenariogenerator.cpp.

415 {
416 Date asof = baseScenario_->asof();
417 // Log an ALERT if some currencies in simmarket are excluded from the list
418 for (auto sim_ccy : simMarketData_->ccys()) {
419 if (sensitivityData_->discountCurveShiftData().find(sim_ccy) ==
420 sensitivityData_->discountCurveShiftData().end()) {
421 WLOG("Currency " << sim_ccy << " in simmarket is not included in sensitivities analysis");
422 }
423 }
424
425 for (auto c : sensitivityData_->discountCurveShiftData()) {
426 string ccy = c.first;
427 Size n_ten;
428 try {
429 n_ten = simMarketData_->yieldCurveTenors(ccy).size();
430 } catch (const std::exception& e) {
431 ALOG("skip scenario generation for discount curve " << ccy << ": " << e.what());
432 continue;
433 }
434 // original curves' buffer
435 std::vector<Real> zeros(n_ten);
436 std::vector<Real> times(n_ten);
437 // buffer for shifted zero curves
438 std::vector<Real> shiftedZeros(n_ten);
439 SensitivityScenarioData::CurveShiftData data = *c.second;
440 if (!isScenarioRelevant(up, data))
441 continue;
442 ShiftType shiftType = getShiftType(data);
443 DayCounter dc = Actual365Fixed();
444 try {
445 if (auto s = simMarket_.lock()) {
446 dc = s->discountCurve(ccy)->dayCounter();
447 } else {
448 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
449 }
450 } catch (const std::exception&) {
451 WLOG("Day counter lookup in simulation market failed for discount curve " << ccy << ", using default A365");
452 }
453
454 Real quote = 0.0;
455 bool valid = true;
456 for (Size j = 0; j < n_ten; ++j) {
457 Date d = asof + simMarketData_->yieldCurveTenors(ccy)[j];
458 times[j] = dc.yearFraction(asof, d);
459
460 RiskFactorKey key(RiskFactorKey::KeyType::DiscountCurve, ccy, j);
461 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, quote, continueOnError_);
462 zeros[j] = -std::log(quote) / times[j];
463 }
464 if (!valid)
465 continue;
466
467 std::vector<Period> shiftTenors = overrideTenors_ && simMarketData_->hasYieldCurveTenors(ccy)
468 ? simMarketData_->yieldCurveTenors(ccy)
469 : data.shiftTenors;
470 checkShiftTenors(shiftTenors, data.shiftTenors, "Discount Curve " + ccy, continueOnError_);
471 std::vector<Time> shiftTimes(shiftTenors.size());
472 for (Size j = 0; j < shiftTenors.size(); ++j)
473 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
474 Real shiftSize = getShiftSize(data);
475 QL_REQUIRE(shiftTenors.size() > 0, "Discount shift tenors not specified");
476
477 // Can we store a valid shift size?
478 bool validShiftSize = vectorEqual(times, shiftTimes);
479
480 for (Size j = 0; j < shiftTenors.size(); ++j) {
481
482 QuantLib::ext::shared_ptr<Scenario> scenario =
483 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
484 // apply zero rate shift at tenor point j
485 applyShift(j, shiftSize, up, shiftType, shiftTimes, zeros, times, shiftedZeros, true);
486
487 // store shifted discount curve in the scenario
488 for (Size k = 0; k < n_ten; ++k) {
489 RiskFactorKey key(RFType::DiscountCurve, ccy, k);
490 // FIXME why do we have that here, but not in generateIndexCurveScenarios?
491 if (!close_enough(shiftedZeros[k], zeros[k])) {
492 Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
493 if (sensitivityData_->useSpreadedTermStructures()) {
494 Real discount = exp(-zeros[k] * times[k]);
495 scenario->add(key, shiftedDiscount / discount);
496 } else {
497 scenario->add(key, shiftedDiscount);
498 }
499 }
500
501 // Possibly store valid shift size
502 if (validShiftSize && j == k) {
503 storeShiftData(key, zeros[k], shiftedZeros[k]);
504 }
505 }
506
507 // add this scenario to the scenario vector
508 scenarios_.push_back(scenario);
510 scenario->label(to_string(scenarioDescriptions_.back()));
511 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
512
513 } // end of shift curve tenors
514 }
515 DLOG("Discount curve scenarios done");
516}
ScenarioDescription discountScenarioDescription(string ccy, Size bucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateIndexCurveScenarios()

void generateIndexCurveScenarios ( bool  up)
private

Definition at line 518 of file sensitivityscenariogenerator.cpp.

518 {
519 Date asof = baseScenario_->asof();
520
521 for (auto sim_idx : simMarketData_->indices()) {
522 if (sensitivityData_->indexCurveShiftData().find(sim_idx) == sensitivityData_->indexCurveShiftData().end()) {
523 WLOG("Index " << sim_idx << " in simmarket is not included in sensitivities analysis");
524 }
525 }
526
527 for (auto idx : sensitivityData_->indexCurveShiftData()) {
528 string indexName = idx.first;
529 Size n_ten;
530 try {
531 n_ten = simMarketData_->yieldCurveTenors(indexName).size();
532 } catch (const std::exception& e) {
533 ALOG("skip scenario generation for index curve " << indexName << ": " << e.what());
534 continue;
535 }
536 // original curves' buffer
537 std::vector<Real> zeros(n_ten);
538 std::vector<Real> times(n_ten);
539 // buffer for shifted zero curves
540 std::vector<Real> shiftedZeros(n_ten);
541
542 SensitivityScenarioData::CurveShiftData data = *idx.second;
543 if (!isScenarioRelevant(up, data))
544 continue;
545 ShiftType shiftType = getShiftType(data);
546
547 DayCounter dc = Actual365Fixed();
548 try {
549 if (auto s = simMarket_.lock()) {
550 dc = s->iborIndex(indexName)->forwardingTermStructure()->dayCounter();
551 } else {
552 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
553 }
554 } catch (const std::exception&) {
555 WLOG("Day counter lookup in simulation market failed for index " << indexName << ", using default A365");
556 }
557
558 Real quote = 0.0;
559 bool valid = true;
560 for (Size j = 0; j < n_ten; ++j) {
561 Date d = asof + simMarketData_->yieldCurveTenors(indexName)[j];
562 times[j] = dc.yearFraction(asof, d);
563 RiskFactorKey key(RiskFactorKey::KeyType::IndexCurve, indexName, j);
564 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, quote, continueOnError_);
565 zeros[j] = -std::log(quote) / times[j];
566 }
567 if (!valid)
568 continue;
569
570 std::vector<Period> shiftTenors = overrideTenors_ && simMarketData_->hasYieldCurveTenors(indexName)
571 ? simMarketData_->yieldCurveTenors(indexName)
572 : data.shiftTenors;
573 checkShiftTenors(shiftTenors, data.shiftTenors, "Index Curve " + indexName, continueOnError_);
574 std::vector<Time> shiftTimes(shiftTenors.size());
575 for (Size j = 0; j < shiftTenors.size(); ++j)
576 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
577 Real shiftSize = getShiftSize(data);
578 QL_REQUIRE(shiftTenors.size() > 0, "Index shift tenors not specified");
579
580 // Can we store a valid shift size?
581 bool validShiftSize = vectorEqual(times, shiftTimes);
582
583 for (Size j = 0; j < shiftTenors.size(); ++j) {
584
585 QuantLib::ext::shared_ptr<Scenario> scenario =
586 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
587
588 // apply zero rate shift at tenor point j
589 applyShift(j, shiftSize, up, shiftType, shiftTimes, zeros, times, shiftedZeros, true);
590
591 // store shifted discount curve for this index in the scenario
592 for (Size k = 0; k < n_ten; ++k) {
593 RiskFactorKey key(RFType::IndexCurve, indexName, k);
594
595 Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
596 if (sensitivityData_->useSpreadedTermStructures()) {
597 Real discount = exp(-zeros[k] * times[k]);
598 scenario->add(key, shiftedDiscount / discount);
599 } else {
600 scenario->add(key, shiftedDiscount);
601 }
602
603 // Possibly store valid shift size
604 if (validShiftSize && j == k) {
605 storeShiftData(key, zeros[k], shiftedZeros[k]);
606 }
607 }
608
609 // add this scenario to the scenario vector
610 scenarios_.push_back(scenario);
611 scenarioDescriptions_.push_back(indexScenarioDescription(indexName, j, up, getShiftScheme(data)));
612 scenario->label(to_string(scenarioDescriptions_.back()));
613 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
614 << " created for indexName " << indexName);
615
616 } // end of shift curve tenors
617 }
618 DLOG("Index curve scenarios done");
619}
ScenarioDescription indexScenarioDescription(string index, Size bucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateFxScenarios()

void generateFxScenarios ( bool  up)
private

Definition at line 298 of file sensitivityscenariogenerator.cpp.

298 {
299 Date asof = baseScenario_->asof();
300 // We can choose to shift fewer FX risk factors than listed in the market
301 // Is this too strict?
302 // - implemented to avoid cases where input cross FX rates are not consistent
303 // - Consider an example (baseCcy = EUR) of a GBPUSD FX trade - two separate routes to pricing
304 // - (a) call GBPUSD FX rate from sim market
305 // - (b) call GBPEUR and EURUSD FX rates, manually join them to obtain GBPUSD
306 // - now, if GBPUSD is an explicit risk factor in sim market, consider what happens
307 // - if we bump GBPUSD value and leave other FX rates unchanged (for e.g. a sensitivity analysis)
308 // - (a) the value of the trade changes
309 // - (b) the value of the GBPUSD trade stays the same
310 // - in light of the above we restrict the universe of FX pairs that we support here for the time being
311 string baseCcy = simMarketData_->baseCcy();
312 for (auto sensi_fx : sensitivityData_->fxShiftData()) {
313 string foreign = sensi_fx.first.substr(0, 3);
314 string domestic = sensi_fx.first.substr(3);
315 QL_REQUIRE((domestic == baseCcy) || (foreign == baseCcy),
316 "SensitivityScenarioGenerator does not support cross FX pairs("
317 << sensi_fx.first << ", but base currency is " << baseCcy << ")");
318 }
319 // Log an ALERT if some currencies in simmarket are excluded from the list
320 for (auto sim_fx : simMarketData_->fxCcyPairs()) {
321 if (sensitivityData_->fxShiftData().find(sim_fx) == sensitivityData_->fxShiftData().end()) {
322 WLOG("FX pair " << sim_fx << " in simmarket is not included in sensitivities analysis");
323 }
324 }
325 for (auto sensi_fx : sensitivityData_->fxShiftData()) {
326 string ccypair = sensi_fx.first; // foreign + domestic;
328 if (!isScenarioRelevant(up, data))
329 continue;
330 ShiftType type = getShiftType(data);
331 Real size = (up ? 1.0 : -1.0) * getShiftSize(data);
332 bool relShift = (type == ShiftType::Relative);
333
334 Real rate;
335 RiskFactorKey key(RiskFactorKey::KeyType::FXSpot, ccypair);
336 if (!tryGetBaseScenarioValue(baseScenarioAbsolute_, key, rate, continueOnError_))
337 continue;
338
339 QuantLib::ext::shared_ptr<Scenario> scenario =
340 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
341
342 Real newRate = relShift ? rate * (1.0 + size) : (rate + size);
343 scenario->add(key, sensitivityData_->useSpreadedTermStructures() ? newRate / rate : newRate);
344
345 storeShiftData(key, rate, newRate);
346
347
348 scenarios_.push_back(scenario);
349 scenarioDescriptions_.push_back(fxScenarioDescription(ccypair, up, getShiftScheme(data)));
350 scenario->label(to_string(scenarioDescriptions_.back()));
351 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
352 << " created: " << newRate);
353 }
354 DLOG("FX scenarios done");
355}
ScenarioDescription fxScenarioDescription(string ccypair, bool up, ShiftScheme shiftScheme)
Size size(const ValueType &v)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateEquityScenarios()

void generateEquityScenarios ( bool  up)
private

Definition at line 357 of file sensitivityscenariogenerator.cpp.

357 {
358 Date asof = baseScenario_->asof();
359 // We can choose to shift fewer discount curves than listed in the market
360 // Log an ALERT if some equities in simmarket are excluded from the sensitivities list
361 for (auto sim_equity : simMarketData_->equityNames()) {
362 if (sensitivityData_->equityShiftData().find(sim_equity) == sensitivityData_->equityShiftData().end()) {
363 WLOG("Equity " << sim_equity << " in simmarket is not included in sensitivities analysis");
364 }
365 }
366 for (auto e : sensitivityData_->equityShiftData()) {
367 string equity = e.first;
369 if (!isScenarioRelevant(up, data))
370 continue;
371 ShiftType type = getShiftType(data);
372 Real size = up ? getShiftSize(data) : -1.0 * getShiftSize(data);
373 bool relShift = (type == ShiftType::Relative);
374
375 Real rate;
376 RiskFactorKey key(RiskFactorKey::KeyType::EquitySpot, equity);
377 if (!tryGetBaseScenarioValue(baseScenarioAbsolute_, key, rate, continueOnError_))
378 continue;
379
380 QuantLib::ext::shared_ptr<Scenario> scenario =
381 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
382
383 Real newRate = relShift ? rate * (1.0 + size) : (rate + size);
384 // Real newRate = up ? rate * (1.0 + getShiftSize(data)) : rate * (1.0 - getShiftSize(data));
385 scenario->add(key, sensitivityData_->useSpreadedTermStructures() ? newRate / rate : newRate);
386
387 storeShiftData(key, rate, newRate);
388
389 scenarios_.push_back(scenario);
391 scenario->label(to_string(scenarioDescriptions_.back()));
392 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
393 << " created: " << newRate);
394 }
395 DLOG("Equity scenarios done");
396}
ScenarioDescription equityScenarioDescription(string equity, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateDividendYieldScenarios()

void generateDividendYieldScenarios ( bool  up)
private

Definition at line 721 of file sensitivityscenariogenerator.cpp.

721 {
722 Date asof = baseScenario_->asof();
723
724 // We can choose to shift fewer yield curves than listed in the market
725 // Log an ALERT if some yield curves in simmarket are excluded from the list
726 for (auto sim : simMarketData_->equityNames()) {
727 if (sensitivityData_->dividendYieldShiftData().find(sim) == sensitivityData_->dividendYieldShiftData().end()) {
728 WLOG("Equity " << sim << " in simmarket is not included in dividend yield sensitivity analysis");
729 }
730 }
731
732 for (auto d : sensitivityData_->dividendYieldShiftData()) {
733 string name = d.first;
734 Size n_ten;
735 try {
736 n_ten = simMarketData_->equityDividendTenors(name).size();
737 } catch (const std::exception& e) {
738 ALOG("skip scenario generation for div yield " << name << ": " << e.what());
739 continue;
740 }
741 // original curves' buffer
742 std::vector<Real> zeros(n_ten);
743 std::vector<Real> times(n_ten);
744 // buffer for shifted zero curves
745 std::vector<Real> shiftedZeros(n_ten);
746 SensitivityScenarioData::CurveShiftData data = *d.second;
747 if (!isScenarioRelevant(up, data))
748 continue;
749 ShiftType shiftType = getShiftType(data);
750 DayCounter dc = Actual365Fixed();
751 try {
752 if (auto s = simMarket_.lock()) {
753 dc = s->equityDividendCurve(name)->dayCounter();
754 } else {
755 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
756 }
757 } catch (const std::exception&) {
758 WLOG("Day counter lookup in simulation market failed for dividend yield curve " << name
759 << ", using default A365");
760 }
761
762 Real quote = 0.0;
763 bool valid = true;
764 for (Size j = 0; j < n_ten; ++j) {
765 Date d = asof + simMarketData_->equityDividendTenors(name)[j];
766 times[j] = dc.yearFraction(asof, d);
767 RiskFactorKey key(RiskFactorKey::KeyType::DividendYield, name, j);
768 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, quote, continueOnError_);
769 zeros[j] = -std::log(quote) / times[j];
770 }
771 if (!valid)
772 continue;
773
774 const std::vector<Period>& shiftTenors = overrideTenors_ && simMarketData_->hasEquityDividendTenors(name)
775 ? simMarketData_->equityDividendTenors(name)
776 : data.shiftTenors;
777 checkShiftTenors(shiftTenors, data.shiftTenors, "Dividend Yield " + name, continueOnError_);
778 std::vector<Time> shiftTimes(shiftTenors.size());
779 for (Size j = 0; j < shiftTenors.size(); ++j)
780 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
781 Real shiftSize = getShiftSize(data);
782 QL_REQUIRE(shiftTenors.size() > 0, "Discount shift tenors not specified");
783
784 // Can we store a valid shift size?
785 bool validShiftSize = vectorEqual(times, shiftTimes);
786
787 for (Size j = 0; j < shiftTenors.size(); ++j) {
788
789 QuantLib::ext::shared_ptr<Scenario> scenario =
790 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
791
792 // apply zero rate shift at tenor point j
793 applyShift(j, shiftSize, up, shiftType, shiftTimes, zeros, times, shiftedZeros, true);
794
795 // store shifted discount curve in the scenario
796 for (Size k = 0; k < n_ten; ++k) {
797 Real shiftedDiscount = exp(-shiftedZeros[k] * times[k]);
798 RiskFactorKey key(RFType::DividendYield, name, k);
799 if (sensitivityData_->useSpreadedTermStructures()) {
800 Real discount = exp(-zeros[k] * times[k]);
801 scenario->add(key, shiftedDiscount / discount);
802 } else {
803 scenario->add(key, shiftedDiscount);
804 }
805
806 // Possibly store valid shift size
807 if (validShiftSize && j == k) {
808 storeShiftData(key, zeros[k], shiftedZeros[k]);
809 }
810 }
811
812 // add this scenario to the scenario vector
813 scenarios_.push_back(scenario);
815 scenario->label(to_string(scenarioDescriptions_.back()));
816 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
817
818 } // end of shift curve tenors
819 }
820 DLOG("Dividend yield curve scenarios done");
821}
ScenarioDescription dividendYieldScenarioDescription(string equity, Size bucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateSwaptionVolScenarios()

void generateSwaptionVolScenarios ( bool  up)
private

Definition at line 1261 of file sensitivityscenariogenerator.cpp.

1261 {
1262 DLOG("starting swapVol sgen");
1263 // We can choose to shift fewer discount curves than listed in the market
1264 // Log an ALERT if some swaption currencies in simmarket are excluded from the list
1265 for (auto sim_key : simMarketData_->swapVolKeys()) {
1266 if (sensitivityData_->swaptionVolShiftData().find(sim_key) == sensitivityData_->swaptionVolShiftData().end()) {
1267 WLOG("Swaption key " << sim_key << " in simmarket is not included in sensitivities analysis");
1268 }
1269 }
1270 generateGenericYieldVolScenarios(up, RFType::SwaptionVolatility);
1271 DLOG("Swaption vol scenarios done");
1272}
void generateGenericYieldVolScenarios(bool up, RiskFactorKey::KeyType rfType)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateYieldVolScenarios()

void generateYieldVolScenarios ( bool  up)
private

Definition at line 1274 of file sensitivityscenariogenerator.cpp.

1274 {
1275 DLOG("starting yieldVol sgen");
1276 // We can choose to shift fewer discount curves than listed in the market
1277 // Log an ALERT if some bond securityId in simmarket are excluded from the list
1278 for (auto sim_securityId : simMarketData_->yieldVolNames()) {
1279 if (sensitivityData_->yieldVolShiftData().find(sim_securityId) == sensitivityData_->yieldVolShiftData().end()) {
1280 WLOG("Bond securityId " << sim_securityId << " in simmarket is not included in sensitivities analysis");
1281 }
1282 }
1283 generateGenericYieldVolScenarios(up, RFType::YieldVolatility);
1284 DLOG("Yield vol scenarios done");
1285}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateFxVolScenarios()

void generateFxVolScenarios ( bool  up)
private

Definition at line 823 of file sensitivityscenariogenerator.cpp.

823 {
824 Date asof = baseScenario_->asof();
825 // We can choose to shift fewer discount curves than listed in the market
826 // Log an ALERT if some FX vol pairs in simmarket are excluded from the list
827 for (auto sim_fx : simMarketData_->fxVolCcyPairs()) {
828 if (sensitivityData_->fxVolShiftData().find(sim_fx) == sensitivityData_->fxVolShiftData().end()) {
829 WLOG("FX pair " << sim_fx << " in simmarket is not included in sensitivities analysis");
830 }
831 }
832
833 for (auto f : sensitivityData_->fxVolShiftData()) {
834 string ccyPair = f.first;
835 QL_REQUIRE(ccyPair.length() == 6, "invalid ccy pair length");
836
837 Size n_fxvol_exp;
838 try {
839 n_fxvol_exp = simMarketData_->fxVolExpiries(ccyPair).size();
840 } catch (const std::exception& e) {
841 ALOG("skip scenario generation for fx vol " << ccyPair << ": " << e.what());
842 continue;
843 }
844 std::vector<Real> times(n_fxvol_exp);
845 Size n_fxvol_strikes;
846 vector<Real> vol_strikes;
847 if (!simMarketData_->fxVolIsSurface(ccyPair)) {
848 vol_strikes = {0.0};
849 n_fxvol_strikes = 1;
850 } else if (simMarketData_->fxUseMoneyness(ccyPair)) {
851 n_fxvol_strikes = simMarketData_->fxVolMoneyness(ccyPair).size();
852 vol_strikes = simMarketData_->fxVolMoneyness(ccyPair);
853 } else {
854 n_fxvol_strikes = simMarketData_->fxVolStdDevs(ccyPair).size();
855 vol_strikes = simMarketData_->fxVolStdDevs(ccyPair);
856 }
857 vector<vector<Real>> values(n_fxvol_exp, vector<Real>(n_fxvol_strikes, 0.0));
858
859 // buffer for shifted zero curves
860 vector<vector<Real>> shiftedValues(n_fxvol_exp, vector<Real>(n_fxvol_strikes, 0.0));
861
862 SensitivityScenarioData::VolShiftData data = f.second;
863 if (!isScenarioRelevant(up, data))
864 continue;
865 ShiftType shiftType = getShiftType(data);
866 std::vector<Period> shiftTenors = data.shiftExpiries;
867 std::vector<Real> shiftStrikes = data.shiftStrikes;
868 std::vector<Time> shiftTimes(shiftTenors.size());
869 Real shiftSize = getShiftSize(data);
870 QL_REQUIRE(shiftTenors.size() > 0, "FX vol shift tenors not specified");
871
872 DayCounter dc = Actual365Fixed();
873 try {
874 if (auto s = simMarket_.lock()) {
875 dc = s->fxVol(ccyPair)->dayCounter();
876 } else {
877 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
878 }
879 } catch (const std::exception&) {
880 WLOG("Day counter lookup in simulation market failed for fx vol surface " << ccyPair
881 << ", using default A365");
882 }
883 bool valid = true;
884 for (Size j = 0; j < n_fxvol_exp; ++j) {
885 Date d = asof + simMarketData_->fxVolExpiries(ccyPair)[j];
886 times[j] = dc.yearFraction(asof, d);
887 for (Size k = 0; k < n_fxvol_strikes; k++) {
888 Size idx = k * n_fxvol_exp + j;
889 RiskFactorKey key(RiskFactorKey::KeyType::FXVolatility, ccyPair, idx);
890 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, values[j][k], continueOnError_);
891 }
892 }
893 if (!valid)
894 continue;
895
896 for (Size j = 0; j < shiftTenors.size(); ++j)
897 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
898
899 // Can we store a valid shift size?
900 bool validShiftSize = vectorEqual(times, shiftTimes) && (vectorEqual(vol_strikes, shiftStrikes) ||
901 (vol_strikes.size() == 1 && shiftStrikes.size() == 1));
902
903 for (Size j = 0; j < shiftTenors.size(); ++j) {
904 for (Size strikeBucket = 0; strikeBucket < shiftStrikes.size(); ++strikeBucket) {
905 QuantLib::ext::shared_ptr<Scenario> scenario =
906 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
907
908 applyShift(j, strikeBucket, shiftSize, up, shiftType, shiftTimes, shiftStrikes, times, vol_strikes,
909 values, shiftedValues, true);
910
911 for (Size k = 0; k < n_fxvol_strikes; ++k) {
912 for (Size l = 0; l < n_fxvol_exp; ++l) {
913 Size idx = k * n_fxvol_exp + l;
914 RiskFactorKey key(RFType::FXVolatility, ccyPair, idx);
915
916 if (sensitivityData_->useSpreadedTermStructures()) {
917 scenario->add(key, shiftedValues[l][k] - values[l][k]);
918 } else {
919 scenario->add(key, shiftedValues[l][k]);
920 }
921
922 // Possibly store valid shift size
923 if (validShiftSize && j == l && strikeBucket == k) {
924 storeShiftData(key, values[l][k], shiftedValues[l][k]);
925 }
926 }
927 }
928
929 // add this scenario to the scenario vector
930 scenarios_.push_back(scenario);
931 scenarioDescriptions_.push_back(
932 fxVolScenarioDescription(ccyPair, j, strikeBucket, up, getShiftScheme(data)));
933 scenario->label(to_string(scenarioDescriptions_.back()));
934 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
935 }
936 }
937 }
938 DLOG("FX vol scenarios done");
939}
ScenarioDescription fxVolScenarioDescription(string ccypair, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateEquityVolScenarios()

void generateEquityVolScenarios ( bool  up)
private

Definition at line 941 of file sensitivityscenariogenerator.cpp.

941 {
942 Date asof = baseScenario_->asof();
943 // We can choose to shift fewer discount curves than listed in the market
944 // Log an ALERT if an Equity in simmarket are excluded from the simulation list
945 for (auto sim_equity : simMarketData_->equityVolNames()) {
946 if (sensitivityData_->equityVolShiftData().find(sim_equity) == sensitivityData_->equityVolShiftData().end()) {
947 WLOG("Equity " << sim_equity << " in simmarket is not included in sensitivities analysis");
948 }
949 }
950
951 for (auto e : sensitivityData_->equityVolShiftData()) {
952 string equity = e.first;
953 SensitivityScenarioData::VolShiftData data = e.second;
954 if (!isScenarioRelevant(up, data))
955 continue;
956
957 Size n_eqvol_exp;
958 try {
959 n_eqvol_exp = simMarketData_->equityVolExpiries(equity).size();
960 } catch (const std::exception& e) {
961 ALOG("skip scenario generation for eq vol " << equity << ": " << e.what());
962 continue;
963 }
964 Size n_eqvol_strikes;
965 vector<Real> vol_strikes;
966 if (!simMarketData_->equityVolIsSurface(equity)) {
967 vol_strikes = {0.0};
968 n_eqvol_strikes = 1;
969 } else if (simMarketData_->equityUseMoneyness(equity)) {
970 vol_strikes = simMarketData_->equityVolMoneyness(equity);
971 n_eqvol_strikes = simMarketData_->equityVolMoneyness(equity).size();
972 } else {
973 vol_strikes = simMarketData_->equityVolStandardDevs(equity);
974 n_eqvol_strikes = simMarketData_->equityVolStandardDevs(equity).size();
975 }
976
977 // [strike] x [expiry]
978 vector<vector<Real>> values(n_eqvol_strikes, vector<Real>(n_eqvol_exp, 0.0));
979 vector<Real> times(n_eqvol_exp);
980
981 // buffer for shifted vols
982 vector<vector<Real>> shiftedValues(n_eqvol_strikes, vector<Real>(n_eqvol_exp, 0.0));
983
984 ShiftType shiftType = getShiftType(data);
985 vector<Period> shiftTenors = data.shiftExpiries;
986 std::vector<Real> shiftStrikes = data.shiftStrikes;
987 vector<Time> shiftTimes(shiftTenors.size());
988 Real shiftSize = getShiftSize(data);
989 QL_REQUIRE(shiftTenors.size() > 0, "Equity vol shift tenors not specified");
990 DayCounter dc = Actual365Fixed();
991 try {
992 if (auto s = simMarket_.lock()) {
993 dc = s->equityVol(equity)->dayCounter();
994 } else {
995 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
996 }
997 } catch (const std::exception&) {
998 WLOG("Day counter lookup in simulation market failed for equity vol surface " << equity
999 << ", using default A365");
1000 }
1001 bool valid = true;
1002 for (Size j = 0; j < n_eqvol_exp; ++j) {
1003 Date d = asof + simMarketData_->equityVolExpiries(equity)[j];
1004 times[j] = dc.yearFraction(asof, d);
1005 for (Size k = 0; k < n_eqvol_strikes; k++) {
1006 Size idx = k * n_eqvol_exp + j;
1007 RiskFactorKey key(RiskFactorKey::KeyType::EquityVolatility, equity, idx);
1008 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, values[k][j], continueOnError_);
1009 }
1010 }
1011 if (!valid)
1012 continue;
1013
1014 for (Size j = 0; j < shiftTenors.size(); ++j) {
1015 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
1016 }
1017
1018 // Can we store a valid shift size?
1019 // Will only work currently if simulation market has a single strike
1020 bool validShiftSize = vectorEqual(times, shiftTimes);
1021 validShiftSize = validShiftSize && vectorEqual(vol_strikes, shiftStrikes);
1022
1023 for (Size j = 0; j < shiftTenors.size(); ++j) {
1024 for (Size strikeBucket = 0; strikeBucket < shiftStrikes.size(); ++strikeBucket) {
1025 QuantLib::ext::shared_ptr<Scenario> scenario =
1026 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1027
1028 applyShift(strikeBucket, j, shiftSize, up, shiftType, shiftStrikes, shiftTimes, vol_strikes, times,
1029 values, shiftedValues, true);
1030
1031 // update the scenario
1032 for (Size k = 0; k < n_eqvol_strikes; ++k) {
1033 for (Size l = 0; l < n_eqvol_exp; l++) {
1034 Size idx = k * n_eqvol_exp + l;
1035 RiskFactorKey key(RFType::EquityVolatility, equity, idx);
1036
1037 if (sensitivityData_->useSpreadedTermStructures()) {
1038 scenario->add(key, shiftedValues[k][l] - values[k][l]);
1039 } else {
1040 scenario->add(key, shiftedValues[k][l]);
1041 }
1042
1043 // Possibly store valid shift size
1044 if (validShiftSize && j == l && k == strikeBucket) {
1045 storeShiftData(key, values[k][l], shiftedValues[k][l]);
1046 }
1047 }
1048 }
1049
1050 // add this scenario to the scenario vector
1051 scenarios_.push_back(scenario);
1052 scenarioDescriptions_.push_back(
1053 equityVolScenarioDescription(equity, j, strikeBucket, up, getShiftScheme(data)));
1054 scenario->label(to_string(scenarioDescriptions_.back()));
1055 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
1056 }
1057 }
1058 }
1059 DLOG("Equity vol scenarios done");
1060}
ScenarioDescription equityVolScenarioDescription(string equity, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateCapFloorVolScenarios()

void generateCapFloorVolScenarios ( bool  up)
private

Definition at line 1287 of file sensitivityscenariogenerator.cpp.

1287 {
1288 Date asof = baseScenario_->asof();
1289
1290 // Log an ALERT if some cap currencies in simmarket are excluded from the list
1291 for (auto sim_cap : simMarketData_->capFloorVolKeys()) {
1292 if (sensitivityData_->capFloorVolShiftData().find(sim_cap) == sensitivityData_->capFloorVolShiftData().end()) {
1293 WLOG("CapFloor key " << sim_cap << " in simmarket is not included in sensitivities analysis");
1294 }
1295 }
1296
1297 for (auto c : sensitivityData_->capFloorVolShiftData()) {
1298 std::string key = c.first;
1299
1300 vector<Real> volStrikes;
1301 try {
1302 volStrikes = simMarketData_->capFloorVolStrikes(key);
1303 } catch (const std::exception& e) {
1304 ALOG("skip scenario generation for cf vol " << key << ": " << e.what());
1305 continue;
1306 }
1307 // Strikes may be empty which indicates that the optionlet structure in the simulation market is an ATM curve
1308 if (volStrikes.empty()) {
1309 volStrikes = {0.0};
1310 }
1311 Size n_cfvol_strikes = volStrikes.size();
1312
1313 Size n_cfvol_exp = simMarketData_->capFloorVolExpiries(key).size();
1314 SensitivityScenarioData::CapFloorVolShiftData data = *c.second;
1315 if (!isScenarioRelevant(up, data))
1316 continue;
1317 ShiftType shiftType = getShiftType(data);
1318 Real shiftSize = getShiftSize(data);
1319 vector<vector<Real>> volData(n_cfvol_exp, vector<Real>(n_cfvol_strikes, 0.0));
1320 vector<Real> volExpiryTimes(n_cfvol_exp, 0.0);
1321 vector<vector<Real>> shiftedVolData(n_cfvol_exp, vector<Real>(n_cfvol_strikes, 0.0));
1322
1323 std::vector<Period> expiries = overrideTenors_ && simMarketData_->hasCapFloorVolExpiries(key)
1324 ? simMarketData_->capFloorVolExpiries(key)
1325 : data.shiftExpiries;
1326 QL_REQUIRE(expiries.size() == data.shiftExpiries.size(), "mismatch between effective shift expiries ("
1327 << expiries.size() << ") and shift tenors ("
1328 << data.shiftExpiries.size());
1329 vector<Real> shiftExpiryTimes(expiries.size(), 0.0);
1330 vector<Real> shiftStrikes = data.shiftStrikes;
1331 // Has an ATM shift been configured?
1332 bool sensiIsAtm = false;
1333 if (shiftStrikes.size() == 1 && shiftStrikes[0] == 0.0 && data.isRelative) {
1334 sensiIsAtm = true;
1335 }
1336
1337 DayCounter dc = Actual365Fixed();
1338 try {
1339 if (auto s = simMarket_.lock()) {
1340 dc = s->capFloorVol(key)->dayCounter();
1341 } else {
1342 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1343 }
1344 } catch (const std::exception&) {
1345 WLOG("Day counter lookup in simulation market failed for cap/floor vol surface " << key
1346 << ", using default A365");
1347 }
1348
1349 // cache original vol data
1350 for (Size j = 0; j < n_cfvol_exp; ++j) {
1351 Date expiry = asof + simMarketData_->capFloorVolExpiries(key)[j];
1352 volExpiryTimes[j] = dc.yearFraction(asof, expiry);
1353 }
1354 bool valid = true;
1355 for (Size j = 0; j < n_cfvol_exp; ++j) {
1356 for (Size k = 0; k < n_cfvol_strikes; ++k) {
1357 Size idx = j * n_cfvol_strikes + k;
1358 valid = valid &&
1359 tryGetBaseScenarioValue(baseScenarioAbsolute_,
1360 RiskFactorKey(RiskFactorKey::KeyType::OptionletVolatility, key, idx),
1361 volData[j][k], continueOnError_);
1362 }
1363 }
1364 if (!valid)
1365 continue;
1366
1367 // cache tenor times
1368 for (Size j = 0; j < shiftExpiryTimes.size(); ++j)
1369 shiftExpiryTimes[j] = dc.yearFraction(asof, asof + expiries[j]);
1370
1371 // Can we store a valid shift size?
1372 bool validShiftSize = vectorEqual(volExpiryTimes, shiftExpiryTimes);
1373 validShiftSize = validShiftSize && vectorEqual(volStrikes, shiftStrikes);
1374
1375 // loop over shift expiries and terms
1376 for (Size j = 0; j < shiftExpiryTimes.size(); ++j) {
1377 for (Size k = 0; k < shiftStrikes.size(); ++k) {
1378 QuantLib::ext::shared_ptr<Scenario> scenario =
1379 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1380
1381 applyShift(j, k, shiftSize, up, shiftType, shiftExpiryTimes, shiftStrikes, volExpiryTimes, volStrikes,
1382 volData, shiftedVolData, true);
1383
1384 // add shifted vol data to the scenario
1385 for (Size jj = 0; jj < n_cfvol_exp; ++jj) {
1386 for (Size kk = 0; kk < n_cfvol_strikes; ++kk) {
1387 Size idx = jj * n_cfvol_strikes + kk;
1388 RiskFactorKey rfkey(RFType::OptionletVolatility, key, idx);
1389
1390 if (sensitivityData_->useSpreadedTermStructures()) {
1391 scenario->add(rfkey, shiftedVolData[jj][kk] - volData[jj][kk]);
1392 } else {
1393 scenario->add(rfkey, shiftedVolData[jj][kk]);
1394 }
1395
1396 // Possibly store valid shift size
1397 if (validShiftSize && j == jj && k == kk) {
1398 storeShiftData(rfkey, volData[jj][kk], shiftedVolData[jj][kk]);
1399 }
1400 }
1401 }
1402
1403 // Give the scenario a label
1404
1405 scenarios_.push_back(scenario);
1406 scenarioDescriptions_.push_back(
1407 capFloorVolScenarioDescription(key, j, k, up, sensiIsAtm, getShiftScheme(data)));
1408 scenario->label(to_string(scenarioDescriptions_.back()));
1409 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
1410 }
1411 }
1412 }
1413 DLOG("Optionlet vol scenarios done");
1414}
ScenarioDescription capFloorVolScenarioDescription(string ccy, Size expiryBucket, Size strikeBucket, bool up, bool isAtm, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateSurvivalProbabilityScenarios()

void generateSurvivalProbabilityScenarios ( bool  up)
private

Definition at line 1416 of file sensitivityscenariogenerator.cpp.

1416 {
1417 Date asof = baseScenario_->asof();
1418 // We can choose to shift fewer credit curves than listed in the market
1419 // Log an ALERT if some names in simmarket are excluded from the list
1420 for (auto sim_name : simMarketData_->defaultNames()) {
1421 if (sensitivityData_->creditCurveShiftData().find(sim_name) == sensitivityData_->creditCurveShiftData().end()) {
1422 WLOG("Credit Name " << sim_name << " in simmarket is not included in sensitivities analysis");
1423 }
1424 }
1425 Size n_ten;
1426
1427 // original curves' buffer
1428 std::vector<Real> times;
1429
1430 for (auto c : sensitivityData_->creditCurveShiftData()) {
1431 string name = c.first;
1432 try {
1433 n_ten = simMarketData_->defaultTenors(name).size();
1434 } catch (const std::exception& e) {
1435 ALOG("skip scenario generation for survival curve " << name << ": " << e.what());
1436 continue;
1437 }
1438 std::vector<Real> hazardRates(n_ten); // integrated hazard rates
1439 times.clear();
1440 times.resize(n_ten);
1441 // buffer for shifted survival prob curves
1442 std::vector<Real> shiftedHazardRates(n_ten);
1443 SensitivityScenarioData::CurveShiftData data = *c.second;
1444 if (!isScenarioRelevant(up, data))
1445 continue;
1446 ShiftType shiftType = getShiftType(data);
1447 DayCounter dc = Actual365Fixed();
1448 try {
1449 if (auto s = simMarket_.lock()) {
1450 dc = s->defaultCurve(name)->curve()->dayCounter();
1451 } else {
1452 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1453 }
1454 } catch (const std::exception&) {
1455 WLOG("Day counter lookup in simulation market failed for default curve " << name << ", using default A365");
1456 }
1457 Calendar calendar = parseCalendar(simMarketData_->defaultCurveCalendar(name));
1458
1459 Real prob = 0.0;
1460 bool valid = true;
1461 for (Size j = 0; j < n_ten; ++j) {
1462 Date d = asof + simMarketData_->defaultTenors(name)[j];
1463 times[j] = dc.yearFraction(asof, d);
1464 RiskFactorKey key(RiskFactorKey::KeyType::SurvivalProbability, name, j);
1465 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, prob, continueOnError_);
1466 // ensure we have a valid value, if prob = 0 we need to avoid nan to generate valid scenarios
1467 hazardRates[j] = -std::log(std::max(prob, 1E-8)) / times[j];
1468 }
1469 if (!valid)
1470 continue;
1471
1472 std::vector<Period> shiftTenors = overrideTenors_ && simMarketData_->hasDefaultTenors(name)
1473 ? simMarketData_->defaultTenors(name)
1474 : data.shiftTenors;
1475
1476 checkShiftTenors(shiftTenors, data.shiftTenors, "Default Curve " + name, continueOnError_);
1477
1478 std::vector<Time> shiftTimes(shiftTenors.size());
1479 for (Size j = 0; j < shiftTenors.size(); ++j)
1480 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
1481 Real shiftSize = getShiftSize(data);
1482 QL_REQUIRE(shiftTenors.size() > 0, "Discount shift tenors not specified");
1483
1484 // Can we store a valid shift size?
1485 bool validShiftSize = vectorEqual(times, shiftTimes);
1486
1487 for (Size j = 0; j < shiftTenors.size(); ++j) {
1488
1489 QuantLib::ext::shared_ptr<Scenario> scenario =
1490 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1491
1492 // apply averaged hazard rate shift at tenor point j
1493 applyShift(j, shiftSize, up, shiftType, shiftTimes, hazardRates, times, shiftedHazardRates, true);
1494
1495 // store shifted survival Prob in the scenario
1496 for (Size k = 0; k < n_ten; ++k) {
1497 RiskFactorKey key(RFType::SurvivalProbability, name, k);
1498 Real shiftedProb = exp(-shiftedHazardRates[k] * times[k]);
1499 if (sensitivityData_->useSpreadedTermStructures()) {
1500 Real prob = exp(-hazardRates[k] * times[k]);
1501 scenario->add(key, shiftedProb / prob);
1502 } else {
1503 scenario->add(key, shiftedProb);
1504 }
1505
1506 // Possibly store valid shift size
1507 if (validShiftSize && k == j) {
1508 storeShiftData(key, hazardRates[k], shiftedHazardRates[k]);
1509 }
1510 }
1511
1512 // add this scenario to the scenario vector
1513 scenarios_.push_back(scenario);
1515 scenario->label(to_string(scenarioDescriptions_.back()));
1516 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
1517
1518 } // end of shift curve tenors
1519 }
1520 DLOG("Discount curve scenarios done");
1521}
ScenarioDescription survivalProbabilityScenarioDescription(string name, Size bucket, bool up, ShiftScheme shiftScheme)
Calendar parseCalendar(const string &s)
Calendar calendar
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateCdsVolScenarios()

void generateCdsVolScenarios ( bool  up)
private

Definition at line 1523 of file sensitivityscenariogenerator.cpp.

1523 {
1524 Date asof = baseScenario_->asof();
1525 // We can choose to shift fewer discount curves than listed in the market
1526 // Log an ALERT if some swaption currencies in simmarket are excluded from the list
1527 for (auto sim_name : simMarketData_->cdsVolNames()) {
1528 if (sensitivityData_->cdsVolShiftData().find(sim_name) == sensitivityData_->cdsVolShiftData().end()) {
1529 WLOG("CDS name " << sim_name << " in simmarket is not included in sensitivities analysis");
1530 }
1531 }
1532
1533 Size n_cdsvol_exp = simMarketData_->cdsVolExpiries().size();
1534
1535 vector<Real> volData(n_cdsvol_exp, 0.0);
1536 vector<Real> volExpiryTimes(n_cdsvol_exp, 0.0);
1537 vector<Real> shiftedVolData(n_cdsvol_exp, 0.0);
1538
1539 for (auto c : sensitivityData_->cdsVolShiftData()) {
1540 std::string name = c.first;
1541 SensitivityScenarioData::CdsVolShiftData data = c.second;
1542 if (!isScenarioRelevant(up, data))
1543 continue;
1544 ShiftType shiftType = getShiftType(data);
1545 Real shiftSize = getShiftSize(data);
1546
1547 vector<Time> shiftExpiryTimes(data.shiftExpiries.size(), 0.0);
1548
1549 DayCounter dc = Actual365Fixed();
1550 try {
1551 if (auto s = simMarket_.lock()) {
1552 dc = s->cdsVol(name)->dayCounter();
1553 } else {
1554 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1555 }
1556 } catch (const std::exception&) {
1557 WLOG("Day counter lookup in simulation market failed for cds vol surface " << name
1558 << ", using default A365");
1559 }
1560
1561 // cache original vol data
1562 for (Size j = 0; j < n_cdsvol_exp; ++j) {
1563 Date expiry = asof + simMarketData_->cdsVolExpiries()[j];
1564 volExpiryTimes[j] = dc.yearFraction(asof, expiry);
1565 }
1566 bool valid = true;
1567 for (Size j = 0; j < n_cdsvol_exp; ++j) {
1568 RiskFactorKey key(RiskFactorKey::KeyType::CDSVolatility, name, j);
1569 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, volData[j], continueOnError_);
1570 }
1571 if (!valid)
1572 continue;
1573
1574 // cache tenor times
1575 for (Size j = 0; j < shiftExpiryTimes.size(); ++j)
1576 shiftExpiryTimes[j] = dc.yearFraction(asof, asof + data.shiftExpiries[j]);
1577
1578 // Can we store a valid shift size?
1579 bool validShiftSize = vectorEqual(volExpiryTimes, shiftExpiryTimes);
1580
1581 // loop over shift expiries and terms
1582 for (Size j = 0; j < shiftExpiryTimes.size(); ++j) {
1583 Size strikeBucket = 0; // FIXME
1584 QuantLib::ext::shared_ptr<Scenario> scenario =
1585 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1586
1587 applyShift(j, shiftSize, up, shiftType, shiftExpiryTimes, volData, volExpiryTimes, shiftedVolData, true);
1588 // add shifted vol data to the scenario
1589 for (Size jj = 0; jj < n_cdsvol_exp; ++jj) {
1590 RiskFactorKey key(RFType::CDSVolatility, name, jj);
1591 if (sensitivityData_->useSpreadedTermStructures()) {
1592 scenario->add(key, shiftedVolData[jj] - volData[jj]);
1593 } else {
1594 scenario->add(key, shiftedVolData[jj]);
1595 }
1596
1597 // Possibly store valid shift size
1598 if (validShiftSize && j == jj) {
1599 storeShiftData(key, volData[jj], shiftedVolData[jj]);
1600 }
1601 }
1602
1603 // add this scenario to the scenario vector
1604 scenarios_.push_back(scenario);
1605 scenarioDescriptions_.push_back(CdsVolScenarioDescription(name, j, strikeBucket, up, getShiftScheme(data)));
1606 scenario->label(to_string(scenarioDescriptions_.back()));
1607 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
1608 }
1609 }
1610 DLOG("CDS vol scenarios done");
1611}
ScenarioDescription CdsVolScenarioDescription(string name, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateZeroInflationScenarios()

void generateZeroInflationScenarios ( bool  up)
private

Definition at line 1613 of file sensitivityscenariogenerator.cpp.

1613 {
1614 Date asof = baseScenario_->asof();
1615 // We can choose to shift fewer discount curves than listed in the market
1616 // Log an ALERT if some ibor indices in simmarket are excluded from the list
1617 for (auto sim_idx : simMarketData_->zeroInflationIndices()) {
1618 if (sensitivityData_->zeroInflationCurveShiftData().find(sim_idx) ==
1619 sensitivityData_->zeroInflationCurveShiftData().end()) {
1620 WLOG("Zero Inflation Index " << sim_idx << " in simmarket is not included in sensitivities analysis");
1621 }
1622 }
1623
1624 for (auto z : sensitivityData_->zeroInflationCurveShiftData()) {
1625 string indexName = z.first;
1626 Size n_ten;
1627 try {
1628 n_ten = simMarketData_->zeroInflationTenors(indexName).size();
1629 } catch (const std::exception& e) {
1630 ALOG("skip scenario generation for zero inflation curve " << indexName << ": " << e.what());
1631 continue;
1632 }
1633 // original curves' buffer
1634 std::vector<Real> zeros(n_ten);
1635 std::vector<Real> times(n_ten);
1636 // buffer for shifted zero curves
1637 std::vector<Real> shiftedZeros(n_ten);
1638 SensitivityScenarioData::CurveShiftData data = *z.second;
1639 if (!isScenarioRelevant(up, data))
1640 continue;
1641 ShiftType shiftType = getShiftType(data);
1642 DayCounter dc = Actual365Fixed();
1643 try {
1644 if (auto s = simMarket_.lock()) {
1645 dc = s->zeroInflationIndex(indexName)->zeroInflationTermStructure()->dayCounter();
1646 } else {
1647 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1648 }
1649 } catch (const std::exception&) {
1650 WLOG("Day counter lookup in simulation market failed for zero inflation index " << indexName
1651 << ", using default A365");
1652 }
1653 bool valid = true;
1654 for (Size j = 0; j < n_ten; ++j) {
1655 Date d = asof + simMarketData_->zeroInflationTenors(indexName)[j];
1656 RiskFactorKey key(RiskFactorKey::KeyType::ZeroInflationCurve, indexName, j);
1657 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, zeros[j], continueOnError_);
1658 times[j] = dc.yearFraction(asof, d);
1659 }
1660 if (!valid)
1661 continue;
1662
1663 std::vector<Period> shiftTenors = overrideTenors_ && simMarketData_->hasZeroInflationTenors(indexName)
1664 ? simMarketData_->zeroInflationTenors(indexName)
1665 : data.shiftTenors;
1666 checkShiftTenors(shiftTenors, data.shiftTenors, "Zero Inflation " + indexName, continueOnError_);
1667 std::vector<Time> shiftTimes(shiftTenors.size());
1668 for (Size j = 0; j < shiftTenors.size(); ++j)
1669 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
1670 Real shiftSize = getShiftSize(data);
1671 QL_REQUIRE(shiftTenors.size() > 0, "Zero Inflation Index shift tenors not specified");
1672
1673 // Can we store a valid shift size?
1674 bool validShiftSize = vectorEqual(times, shiftTimes);
1675
1676 for (Size j = 0; j < shiftTenors.size(); ++j) {
1677
1678 QuantLib::ext::shared_ptr<Scenario> scenario =
1679 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1680
1681 // apply zero rate shift at tenor point j
1682 applyShift(j, shiftSize, up, shiftType, shiftTimes, zeros, times, shiftedZeros, true);
1683
1684 // store shifted discount curve for this index in the scenario
1685 for (Size k = 0; k < n_ten; ++k) {
1686 RiskFactorKey key(RFType::ZeroInflationCurve, indexName, k);
1687 if (sensitivityData_->useSpreadedTermStructures()) {
1688 scenario->add(key, shiftedZeros[k] - zeros[k]);
1689 } else {
1690 scenario->add(key, shiftedZeros[k]);
1691 }
1692
1693 // Possibly store valid shift size
1694 if (validShiftSize && j == k) {
1695 storeShiftData(key, zeros[k], shiftedZeros[k]);
1696 }
1697 }
1698
1699 // add this scenario to the scenario vector
1700 scenarios_.push_back(scenario);
1701 scenarioDescriptions_.push_back(zeroInflationScenarioDescription(indexName, j, up, getShiftScheme(data)));
1702 scenario->label(to_string(scenarioDescriptions_.back()));
1703 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
1704 << " created for indexName " << indexName);
1705
1706 } // end of shift curve tenors
1707 }
1708 DLOG("Zero Inflation Index curve scenarios done");
1709}
ScenarioDescription zeroInflationScenarioDescription(string index, Size bucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateZeroInflationCapFloorVolScenarios()

void generateZeroInflationCapFloorVolScenarios ( bool  up)
private

Definition at line 1927 of file sensitivityscenariogenerator.cpp.

1927 {
1928 Date asof = baseScenario_->asof();
1929 for (auto sim_zci : simMarketData_->zeroInflationCapFloorVolNames()) {
1930 if (sensitivityData_->zeroInflationCapFloorVolShiftData().find(sim_zci) ==
1931 sensitivityData_->zeroInflationCapFloorVolShiftData().end()) {
1932 WLOG("Inflation index " << sim_zci << " in simmarket is not included in sensitivities analysis");
1933 }
1934 }
1935
1936 for (auto c : sensitivityData_->zeroInflationCapFloorVolShiftData()) {
1937 std::string name = c.first;
1938 Size n_strikes;
1939 try {
1940 n_strikes = simMarketData_->zeroInflationCapFloorVolStrikes(name).size();
1941 } catch (const std::exception& e) {
1942 ALOG("skip scenario generation for zero inflation cf vol " << name << ": " << e.what());
1943 continue;
1944 }
1945 Size n_exp = simMarketData_->zeroInflationCapFloorVolExpiries(name).size();
1946 vector<Real> volStrikes = simMarketData_->zeroInflationCapFloorVolStrikes(name);
1947 SensitivityScenarioData::VolShiftData data = *c.second;
1948 if (!isScenarioRelevant(up, data))
1949 continue;
1950 ShiftType shiftType = getShiftType(data);
1951 Real shiftSize = getShiftSize(data);
1952 vector<vector<Real>> volData(n_exp, vector<Real>(n_strikes, 0.0));
1953 vector<Real> volExpiryTimes(n_exp, 0.0);
1954 vector<vector<Real>> shiftedVolData(n_exp, vector<Real>(n_strikes, 0.0));
1955
1956 std::vector<Period> expiries = overrideTenors_ && simMarketData_->hasZeroInflationCapFloorVolExpiries(name)
1957 ? simMarketData_->zeroInflationCapFloorVolExpiries(name)
1958 : data.shiftExpiries;
1959 QL_REQUIRE(expiries.size() == data.shiftExpiries.size(), "mismatch between effective shift expiries ("
1960 << expiries.size() << ") and shift tenors ("
1961 << data.shiftExpiries.size());
1962 vector<Real> shiftExpiryTimes(expiries.size(), 0.0);
1963 vector<Real> shiftStrikes = data.shiftStrikes;
1964
1965 DayCounter dc = Actual365Fixed();
1966 try {
1967 if (auto s = simMarket_.lock()) {
1968 dc = s->cpiInflationCapFloorVolatilitySurface(name)->dayCounter();
1969 } else {
1970 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1971 }
1972 } catch (const std::exception&) {
1973 WLOG("Day counter lookup in simulation market failed for cpi cap/floor vol surface "
1974 << name << ", using default A365");
1975 }
1976
1977 // cache original vol data
1978 for (Size j = 0; j < n_exp; ++j) {
1979 Date expiry = asof + simMarketData_->zeroInflationCapFloorVolExpiries(name)[j];
1980 volExpiryTimes[j] = dc.yearFraction(asof, expiry);
1981 }
1982 bool valid = true;
1983 for (Size j = 0; j < n_exp; ++j) {
1984 for (Size k = 0; k < n_strikes; ++k) {
1985 Size idx = j * n_strikes + k;
1986 RiskFactorKey key(RiskFactorKey::KeyType::ZeroInflationCapFloorVolatility, name, idx);
1987 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, volData[j][k], continueOnError_);
1988 }
1989 }
1990 if (!valid)
1991 continue;
1992
1993 // cache tenor times
1994 for (Size j = 0; j < shiftExpiryTimes.size(); ++j)
1995 shiftExpiryTimes[j] = dc.yearFraction(asof, asof + expiries[j]);
1996
1997 bool validShiftSize = vectorEqual(volExpiryTimes, shiftExpiryTimes);
1998 validShiftSize = validShiftSize && vectorEqual(volStrikes, shiftStrikes);
1999
2000 // loop over shift expiries and terms
2001 for (Size j = 0; j < shiftExpiryTimes.size(); ++j) {
2002 for (Size k = 0; k < shiftStrikes.size(); ++k) {
2003 QuantLib::ext::shared_ptr<Scenario> scenario =
2004 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
2005
2006 applyShift(j, k, shiftSize, up, shiftType, shiftExpiryTimes, shiftStrikes, volExpiryTimes, volStrikes,
2007 volData, shiftedVolData, true);
2008
2009 // add shifted vol data to the scenario
2010 for (Size jj = 0; jj < n_exp; ++jj) {
2011 for (Size kk = 0; kk < n_strikes; ++kk) {
2012 Size idx = jj * n_strikes + kk;
2013 RiskFactorKey key(RFType::ZeroInflationCapFloorVolatility, name, idx);
2014 if (sensitivityData_->useSpreadedTermStructures()) {
2015 scenario->add(key, shiftedVolData[jj][kk] - volData[jj][kk]);
2016 } else {
2017 scenario->add(key, shiftedVolData[jj][kk]);
2018 }
2019
2020 // Possibly store valid shift size
2021 if (validShiftSize && j == jj && k == kk) {
2022 storeShiftData(key, volData[jj][kk], shiftedVolData[jj][kk]);
2023 }
2024 }
2025 }
2026
2027 // add this scenario to the scenario vector
2028 scenarios_.push_back(scenario);
2029 scenarioDescriptions_.push_back(
2031 scenario->label(to_string(scenarioDescriptions_.back()));
2032 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
2033 }
2034 }
2035 }
2036 DLOG("Zero inflation cap/floor vol scenarios done");
2037}
ScenarioDescription zeroInflationCapFloorVolScenarioDescription(string name, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateYoYInflationScenarios()

void generateYoYInflationScenarios ( bool  up)
private

Definition at line 1711 of file sensitivityscenariogenerator.cpp.

1711 {
1712 Date asof = baseScenario_->asof();
1713
1714 // We can choose to shift fewer discount curves than listed in the market
1715 std::vector<string> yoyInfIndexNames;
1716 // Log an ALERT if some ibor indices in simmarket are excluded from the list
1717 for (auto sim_idx : simMarketData_->yoyInflationIndices()) {
1718 if (sensitivityData_->yoyInflationCurveShiftData().find(sim_idx) ==
1719 sensitivityData_->yoyInflationCurveShiftData().end()) {
1720 WLOG("YoY Inflation Index " << sim_idx << " in simmarket is not included in sensitivities analysis");
1721 }
1722 }
1723
1724 for (auto y : sensitivityData_->yoyInflationCurveShiftData()) {
1725 string indexName = y.first;
1726 Size n_ten;
1727 try {
1728 n_ten = simMarketData_->yoyInflationTenors(indexName).size();
1729 } catch (const std::exception& e) {
1730 ALOG("skip scenario generation for yoy inflation curve " << indexName << ": " << e.what());
1731 continue;
1732 }
1733 // original curves' buffer
1734 std::vector<Real> yoys(n_ten);
1735 std::vector<Real> times(n_ten);
1736 // buffer for shifted zero curves
1737 std::vector<Real> shiftedYoys(n_ten);
1738 auto itr = sensitivityData_->yoyInflationCurveShiftData().find(indexName);
1739 QL_REQUIRE(itr != sensitivityData_->yoyInflationCurveShiftData().end(),
1740 "yoyinflation CurveShiftData not found for " << indexName);
1741 SensitivityScenarioData::CurveShiftData data = *y.second;
1742 if (!isScenarioRelevant(up, data))
1743 continue;
1744 ShiftType shiftType = getShiftType(data);
1745 DayCounter dc = Actual365Fixed();
1746 try {
1747 if (auto s = simMarket_.lock()) {
1748 dc = s->yoyInflationIndex(indexName)->yoyInflationTermStructure()->dayCounter();
1749 } else {
1750 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1751 }
1752 } catch (const std::exception&) {
1753 WLOG("Day counter lookup in simulation market failed for yoy inflation index " << indexName
1754 << ", using default A365");
1755 }
1756 bool valid = true;
1757 for (Size j = 0; j < n_ten; ++j) {
1758 Date d = asof + simMarketData_->yoyInflationTenors(indexName)[j];
1759 RiskFactorKey key(RiskFactorKey::KeyType::YoYInflationCurve, indexName, j);
1760 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, yoys[j], continueOnError_);
1761 times[j] = dc.yearFraction(asof, d);
1762 }
1763 if (!valid)
1764 continue;
1765
1766 std::vector<Period> shiftTenors = overrideTenors_ && simMarketData_->hasYoyInflationTenors(indexName)
1767 ? simMarketData_->yoyInflationTenors(indexName)
1768 : data.shiftTenors;
1769 checkShiftTenors(shiftTenors, data.shiftTenors, "YoY Inflation " + indexName, continueOnError_);
1770 std::vector<Time> shiftTimes(shiftTenors.size());
1771 for (Size j = 0; j < shiftTenors.size(); ++j) {
1772 shiftTimes[j] = dc.yearFraction(asof, asof + shiftTenors[j]);
1773 }
1774 Real shiftSize = getShiftSize(data);
1775 QL_REQUIRE(shiftTenors.size() > 0, "YoY Inflation Index shift tenors not specified");
1776
1777 // Can we store a valid shift size?
1778 bool validShiftSize = vectorEqual(times, shiftTimes);
1779
1780 for (Size j = 0; j < shiftTenors.size(); ++j) {
1781
1782 QuantLib::ext::shared_ptr<Scenario> scenario =
1783 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1784
1785 // apply zero rate shift at tenor point j
1786 applyShift(j, shiftSize, up, shiftType, shiftTimes, yoys, times, shiftedYoys, true);
1787
1788 // store shifted discount curve for this index in the scenario
1789 for (Size k = 0; k < n_ten; ++k) {
1790 RiskFactorKey key(RFType::YoYInflationCurve, indexName, k);
1791 if (sensitivityData_->useSpreadedTermStructures()) {
1792 scenario->add(key, shiftedYoys[k] - yoys[k]);
1793 } else {
1794 scenario->add(key, shiftedYoys[k]);
1795 }
1796
1797 // Possibly store valid shift size
1798 if (validShiftSize && j == k) {
1799 storeShiftData(key, yoys[k], shiftedYoys[k]);
1800 }
1801 }
1802
1803 // add this scenario to the scenario vector
1804 scenarios_.push_back(scenario);
1805 scenarioDescriptions_.push_back(yoyInflationScenarioDescription(indexName, j, up, getShiftScheme(data)));
1806 scenario->label(to_string(scenarioDescriptions_.back()));
1807 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
1808 << " created for indexName " << indexName);
1809
1810 } // end of shift curve tenors
1811 }
1812 DLOG("YoY Inflation Index curve scenarios done");
1813}
ScenarioDescription yoyInflationScenarioDescription(string index, Size bucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateYoYInflationCapFloorVolScenarios()

void generateYoYInflationCapFloorVolScenarios ( bool  up)
private

Definition at line 1815 of file sensitivityscenariogenerator.cpp.

1815 {
1816 Date asof = baseScenario_->asof();
1817 for (auto sim_yoy : simMarketData_->yoyInflationCapFloorVolNames()) {
1818 if (sensitivityData_->yoyInflationCapFloorVolShiftData().find(sim_yoy) ==
1819 sensitivityData_->yoyInflationCapFloorVolShiftData().end()) {
1820 WLOG("Inflation index " << sim_yoy << " in simmarket is not included in sensitivities analysis");
1821 }
1822 }
1823
1824 for (auto c : sensitivityData_->yoyInflationCapFloorVolShiftData()) {
1825 std::string name = c.first;
1826 Size n_yoyvol_strikes;
1827 try {
1828 n_yoyvol_strikes = simMarketData_->yoyInflationCapFloorVolStrikes(name).size();
1829 } catch (const std::exception& e) {
1830 ALOG("skip scenario generation for yoy inflation cf vol " << name << ": " << e.what());
1831 continue;
1832 }
1833 vector<Real> volStrikes = simMarketData_->yoyInflationCapFloorVolStrikes(name);
1834 Size n_yoyvol_exp = simMarketData_->yoyInflationCapFloorVolExpiries(name).size();
1835 SensitivityScenarioData::VolShiftData data = *c.second;
1836 if (!isScenarioRelevant(up, data))
1837 continue;
1838 ShiftType shiftType = getShiftType(data);
1839 Real shiftSize = getShiftSize(data);
1840 vector<vector<Real>> volData(n_yoyvol_exp, vector<Real>(n_yoyvol_strikes, 0.0));
1841 vector<Real> volExpiryTimes(n_yoyvol_exp, 0.0);
1842 vector<vector<Real>> shiftedVolData(n_yoyvol_exp, vector<Real>(n_yoyvol_strikes, 0.0));
1843
1844 std::vector<Period> expiries = overrideTenors_ && simMarketData_->hasYoYInflationCapFloorVolExpiries(name)
1845 ? simMarketData_->yoyInflationCapFloorVolExpiries(name)
1846 : data.shiftExpiries;
1847 QL_REQUIRE(expiries.size() == data.shiftExpiries.size(), "mismatch between effective shift expiries ("
1848 << expiries.size() << ") and shift tenors ("
1849 << data.shiftExpiries.size());
1850 vector<Real> shiftExpiryTimes(expiries.size(), 0.0);
1851 vector<Real> shiftStrikes = data.shiftStrikes;
1852
1853 DayCounter dc = Actual365Fixed();
1854 try {
1855 if (auto s = simMarket_.lock()) {
1856 dc = s->yoyCapFloorVol(name)->dayCounter();
1857 } else {
1858 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1859 }
1860 } catch (const std::exception&) {
1861 WLOG("Day counter lookup in simulation market failed for yoy cap/floor vol surface "
1862 << name << ", using default A365");
1863 }
1864
1865 // cache original vol data
1866 for (Size j = 0; j < n_yoyvol_exp; ++j) {
1867 Date expiry = asof + simMarketData_->yoyInflationCapFloorVolExpiries(name)[j];
1868 volExpiryTimes[j] = dc.yearFraction(asof, expiry);
1869 }
1870 bool valid = true;
1871 for (Size j = 0; j < n_yoyvol_exp; ++j) {
1872 for (Size k = 0; k < n_yoyvol_strikes; ++k) {
1873 Size idx = j * n_yoyvol_strikes + k;
1874 RiskFactorKey key(RiskFactorKey::KeyType::YoYInflationCapFloorVolatility, name, idx);
1875 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, volData[j][k], continueOnError_);
1876 }
1877 }
1878 if (!valid)
1879 continue;
1880
1881 // cache tenor times
1882 for (Size j = 0; j < shiftExpiryTimes.size(); ++j)
1883 shiftExpiryTimes[j] = dc.yearFraction(asof, asof + expiries[j]);
1884
1885 bool validShiftSize = vectorEqual(volExpiryTimes, shiftExpiryTimes);
1886 validShiftSize = validShiftSize && vectorEqual(volStrikes, shiftStrikes);
1887
1888 // loop over shift expiries and terms
1889 for (Size j = 0; j < shiftExpiryTimes.size(); ++j) {
1890 for (Size k = 0; k < shiftStrikes.size(); ++k) {
1891 QuantLib::ext::shared_ptr<Scenario> scenario =
1892 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1893
1894 applyShift(j, k, shiftSize, up, shiftType, shiftExpiryTimes, shiftStrikes, volExpiryTimes, volStrikes,
1895 volData, shiftedVolData, true);
1896
1897 // add shifted vol data to the scenario
1898 for (Size jj = 0; jj < n_yoyvol_exp; ++jj) {
1899 for (Size kk = 0; kk < n_yoyvol_strikes; ++kk) {
1900 Size idx = jj * n_yoyvol_strikes + kk;
1901 RiskFactorKey key(RFType::YoYInflationCapFloorVolatility, name, idx);
1902 if (sensitivityData_->useSpreadedTermStructures()) {
1903 scenario->add(key, shiftedVolData[jj][kk] - volData[jj][kk]);
1904 } else {
1905 scenario->add(key, shiftedVolData[jj][kk]);
1906 }
1907
1908 // Possibly store valid shift size
1909 if (validShiftSize && j == jj && k == kk) {
1910 storeShiftData(key, volData[jj][kk], shiftedVolData[jj][kk]);
1911 }
1912 }
1913 }
1914
1915 // add this scenario to the scenario vector
1916 scenarios_.push_back(scenario);
1917 scenarioDescriptions_.push_back(
1919 scenario->label(to_string(scenarioDescriptions_.back()));
1920 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
1921 }
1922 }
1923 }
1924 DLOG("YoY inflation optionlet vol scenarios done");
1925}
ScenarioDescription yoyInflationCapFloorVolScenarioDescription(string name, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateBaseCorrelationScenarios()

void generateBaseCorrelationScenarios ( bool  up)
private

Definition at line 2039 of file sensitivityscenariogenerator.cpp.

2039 {
2040 Date asof = baseScenario_->asof();
2041 // We can choose to shift fewer discount curves than listed in the market
2042 // Log an ALERT if some names in simmarket are excluded from the list
2043 for (auto name : simMarketData_->baseCorrelationNames()) {
2044 if (sensitivityData_->baseCorrelationShiftData().find(name) ==
2045 sensitivityData_->baseCorrelationShiftData().end()) {
2046 WLOG("Base Correlation " << name << " in simmarket is not included in sensitivities analysis");
2047 }
2048 }
2049
2050 Size n_bc_terms = simMarketData_->baseCorrelationTerms().size();
2051 Size n_bc_levels = simMarketData_->baseCorrelationDetachmentPoints().size();
2052
2053 vector<vector<Real>> bcData(n_bc_levels, vector<Real>(n_bc_terms, 0.0));
2054 vector<vector<Real>> shiftedBcData(n_bc_levels, vector<Real>(n_bc_levels, 0.0));
2055 vector<Real> termTimes(n_bc_terms, 0.0);
2056 vector<Real> levels = simMarketData_->baseCorrelationDetachmentPoints();
2057
2058 for (auto b : sensitivityData_->baseCorrelationShiftData()) {
2059 std::string name = b.first;
2060 SensitivityScenarioData::BaseCorrelationShiftData data = b.second;
2061 if (!isScenarioRelevant(up, data))
2062 continue;
2063 ShiftType shiftType = getShiftType(data);
2064 Real shiftSize = getShiftSize(data);
2065
2066 vector<Real> shiftLevels = data.shiftLossLevels;
2067 vector<Real> shiftTermTimes(data.shiftTerms.size(), 0.0);
2068
2069 DayCounter dc = Actual365Fixed();
2070 try {
2071 if (auto s = simMarket_.lock()) {
2072 dc = s->baseCorrelation(name)->dayCounter();
2073 } else {
2074 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
2075 }
2076 } catch (const std::exception&) {
2077 WLOG("Day counter lookup in simulation market failed for base correlation structure "
2078 << name << ", using default A365");
2079 }
2080
2081 // cache original base correlation data
2082 for (Size j = 0; j < n_bc_terms; ++j) {
2083 Date term = asof + simMarketData_->baseCorrelationTerms()[j];
2084 termTimes[j] = dc.yearFraction(asof, term);
2085 }
2086 bool valid = true;
2087 for (Size j = 0; j < n_bc_levels; ++j) {
2088 for (Size k = 0; k < n_bc_terms; ++k) {
2089 RiskFactorKey key(RiskFactorKey::KeyType::BaseCorrelation, name, j);
2090 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, bcData[j][k], continueOnError_);
2091 }
2092 }
2093 if (!valid)
2094 continue;
2095
2096 // cache tenor times
2097 for (Size j = 0; j < shiftTermTimes.size(); ++j)
2098 shiftTermTimes[j] = dc.yearFraction(asof, asof + data.shiftTerms[j]);
2099
2100 // Can we store a valid shift size?
2101 bool validShiftSize = vectorEqual(termTimes, shiftTermTimes);
2102 validShiftSize = validShiftSize && vectorEqual(levels, shiftLevels);
2103
2104 // loop over shift levels and terms
2105 for (Size j = 0; j < shiftLevels.size(); ++j) {
2106 for (Size k = 0; k < shiftTermTimes.size(); ++k) {
2107 QuantLib::ext::shared_ptr<Scenario> scenario =
2108 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
2109
2110 applyShift(j, k, shiftSize, up, shiftType, shiftLevels, shiftTermTimes, levels, termTimes, bcData,
2111 shiftedBcData, true);
2112
2113 // add shifted vol data to the scenario
2114 for (Size jj = 0; jj < n_bc_levels; ++jj) {
2115 for (Size kk = 0; kk < n_bc_terms; ++kk) {
2116 Size idx = jj * n_bc_terms + kk;
2117 if (shiftedBcData[jj][kk] < 0.0) {
2118 ALOG("invalid shifted base correlation " << shiftedBcData[jj][kk] << " at lossLevelIndex "
2119 << jj << " and termIndex " << kk
2120 << " set to zero");
2121 shiftedBcData[jj][kk] = 0.0;
2122 } else if (shiftedBcData[jj][kk] > 1.0) {
2123 ALOG("invalid shifted base correlation " << shiftedBcData[jj][kk] << " at lossLevelIndex "
2124 << jj << " and termIndex " << kk
2125 << " set to 1 - epsilon");
2126 shiftedBcData[jj][kk] = 1.0 - QL_EPSILON;
2127 }
2128
2129 RiskFactorKey key(RFType::BaseCorrelation, name, idx);
2130 if (sensitivityData_->useSpreadedTermStructures()) {
2131 scenario->add(key, shiftedBcData[jj][kk] - bcData[jj][kk]);
2132 } else {
2133 scenario->add(key, shiftedBcData[jj][kk]);
2134 }
2135 // Possibly store valid shift size
2136 if (validShiftSize && j == jj && k == kk) {
2137 storeShiftData(key, bcData[jj][kk], shiftedBcData[jj][kk]);
2138 }
2139 }
2140 }
2141
2142 // add this scenario to the scenario vector
2143 scenarios_.push_back(scenario);
2144 scenarioDescriptions_.push_back(
2145 baseCorrelationScenarioDescription(name, j, k, up, getShiftScheme(data)));
2146 scenario->label(to_string(scenarioDescriptions_.back()));
2147 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
2148 }
2149 }
2150 }
2151 DLOG("Base correlation scenarios done");
2152}
ScenarioDescription baseCorrelationScenarioDescription(string indexName, Size lossLevelBucket, Size termBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateCommodityCurveScenarios()

void generateCommodityCurveScenarios ( bool  up)
private

Definition at line 2154 of file sensitivityscenariogenerator.cpp.

2154 {
2155
2156 Date asof = baseScenario_->asof();
2157
2158 // Log an ALERT if some commodity curves in simulation market are not in the list
2159 for (const string& name : simMarketData_->commodityNames()) {
2160 if (sensitivityData_->commodityCurveShiftData().find(name) ==
2161 sensitivityData_->commodityCurveShiftData().end()) {
2162 ALOG("Commodity " << name
2163 << " in simulation market is not "
2164 "included in commodity sensitivity analysis");
2165 }
2166 }
2167
2168 for (auto c : sensitivityData_->commodityCurveShiftData()) {
2169 string name = c.first;
2170 // Tenors for this name in simulation market
2171 vector<Period> simMarketTenors;
2172 try {
2173 simMarketTenors = simMarketData_->commodityCurveTenors(name);
2174 } catch (const std::exception& e) {
2175 ALOG("skip scenario generation for comm curve " << name << ": " << e.what());
2176 continue;
2177 }
2178 DayCounter dc = Actual365Fixed();
2179 try {
2180 if (auto s = simMarket_.lock()) {
2181 dc = s->commodityPriceCurve(name)->dayCounter();
2182 } else {
2183 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
2184 }
2185 } catch (const std::exception&) {
2186 WLOG("Day counter lookup in simulation market failed for commodity price curve " << name
2187 << ", using default A365");
2188 }
2189
2190 vector<Real> times(simMarketTenors.size());
2191 vector<Real> basePrices(times.size());
2192 vector<Real> shiftedPrices(times.size());
2193
2194 // Get the base prices for this name from the base scenario
2195 bool valid = true;
2196 for (Size j = 0; j < times.size(); ++j) {
2197 times[j] = dc.yearFraction(asof, asof + simMarketTenors[j]);
2198 RiskFactorKey key(RiskFactorKey::KeyType::CommodityCurve, name, j);
2199 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, basePrices[j], continueOnError_);
2200 }
2201 if (!valid)
2202 continue;
2203
2204 // Get the sensitivity data for this name
2205 SensitivityScenarioData::CurveShiftData data = *c.second;
2206 if (!isScenarioRelevant(up, data))
2207 continue;
2208 ShiftType shiftType = getShiftType(data);
2209 Real shiftSize = getShiftSize(data);
2210
2211 // Get the times at which we want to apply the shifts
2212 QL_REQUIRE(!data.shiftTenors.empty(), "Commodity curve shift tenors have not been given");
2213 vector<Time> shiftTimes(data.shiftTenors.size());
2214 for (Size j = 0; j < data.shiftTenors.size(); ++j) {
2215 shiftTimes[j] = dc.yearFraction(asof, asof + data.shiftTenors[j]);
2216 }
2217
2218 // Can we store a valid shift size?
2219 bool validShiftSize = vectorEqual(times, shiftTimes);
2220
2221 // Generate the scenarios for each shift
2222 for (Size j = 0; j < data.shiftTenors.size(); ++j) {
2223
2224 QuantLib::ext::shared_ptr<Scenario> scenario =
2225 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
2226
2227 // Apply shift at tenor point j
2228 applyShift(j, shiftSize, up, shiftType, shiftTimes, basePrices, times, shiftedPrices, true);
2229
2230 // store shifted commodity price curve in the scenario
2231 for (Size k = 0; k < times.size(); ++k) {
2232 RiskFactorKey key(RFType::CommodityCurve, name, k);
2233 if (sensitivityData_->useSpreadedTermStructures()) {
2234 scenario->add(key, shiftedPrices[k] - basePrices[k]);
2235 } else {
2236 scenario->add(key, shiftedPrices[k]);
2237 }
2238
2239 // Possibly store valid shift size
2240 if (validShiftSize && j == k) {
2241 storeShiftData(key, basePrices[k], shiftedPrices[k]);
2242 }
2243 }
2244
2245 // add this scenario to the scenario vector
2246 scenarios_.push_back(scenario);
2248 scenario->label(to_string(scenarioDescriptions_.back()));
2249 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
2250 }
2251 }
2252 DLOG("Commodity curve scenarios done");
2253}
ScenarioDescription commodityCurveScenarioDescription(const std::string &commodityName, QuantLib::Size bucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateCommodityVolScenarios()

void generateCommodityVolScenarios ( bool  up)
private

Definition at line 2255 of file sensitivityscenariogenerator.cpp.

2255 {
2256
2257 // Log an ALERT if some commodity vol names in simulation market are not in the list
2258 for (const string& name : simMarketData_->commodityVolNames()) {
2259 if (sensitivityData_->commodityVolShiftData().find(name) == sensitivityData_->commodityVolShiftData().end()) {
2260 ALOG("Commodity volatility " << name
2261 << " in simulation market is not "
2262 "included in commodity sensitivity analysis");
2263 }
2264 }
2265
2266 // Loop over each commodity and create volatility scenario
2267 Date asof = baseScenario_->asof();
2268 for (auto c : sensitivityData_->commodityVolShiftData()) {
2269 string name = c.first;
2270 // Simulation market data for the current name
2271 vector<Period> expiries;
2272 try {
2273 expiries = simMarketData_->commodityVolExpiries(name);
2274 } catch (const std::exception& e) {
2275 ALOG("skip scenario generation for comm vol " << name << ": " << e.what());
2276 continue;
2277 }
2278 const vector<Real>& moneyness = simMarketData_->commodityVolMoneyness(name);
2279 QL_REQUIRE(!expiries.empty(), "Sim market commodity volatility expiries have not been specified for " << name);
2280 QL_REQUIRE(!moneyness.empty(), "Sim market commodity volatility moneyness has not been specified for " << name);
2281 // Store base scenario volatilities, strike x expiry
2282 vector<vector<Real>> baseValues(moneyness.size(), vector<Real>(expiries.size()));
2283 // Time to each expiry
2284 vector<Time> times(expiries.size());
2285 // Store shifted scenario volatilities
2286 vector<vector<Real>> shiftedValues = baseValues;
2287
2288 SensitivityScenarioData::VolShiftData sd = c.second;
2289 if (!isScenarioRelevant(up, sd))
2290 continue;
2291 QL_REQUIRE(!sd.shiftExpiries.empty(), "commodity volatility shift tenors must be specified");
2292
2293 ShiftType shiftType = getShiftType(sd);
2294 vector<Time> shiftTimes(sd.shiftExpiries.size());
2295 DayCounter dc = Actual365Fixed();
2296 try {
2297 if (auto s = simMarket_.lock()) {
2298 dc = s->commodityVolatility(name)->dayCounter();
2299 } else {
2300 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
2301 }
2302 } catch (const std::exception&) {
2303 WLOG("Day counter lookup in simulation market failed for commodity vol surface " << name
2304 << ", using default A365");
2305 }
2306
2307 // Get the base scenario volatility values
2308 bool valid = true;
2309 for (Size j = 0; j < expiries.size(); j++) {
2310 times[j] = dc.yearFraction(asof, asof + expiries[j]);
2311 for (Size i = 0; i < moneyness.size(); i++) {
2312 RiskFactorKey key(RiskFactorKey::KeyType::CommodityVolatility, name, i * expiries.size() + j);
2313 valid =
2314 valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, baseValues[i][j], continueOnError_);
2315 }
2316 }
2317 if (!valid)
2318 continue;
2319
2320 // Store the shift expiry times
2321 for (Size sj = 0; sj < sd.shiftExpiries.size(); ++sj) {
2322 shiftTimes[sj] = dc.yearFraction(asof, asof + sd.shiftExpiries[sj]);
2323 }
2324
2325 // Can we store a valid shift size?
2326 bool validShiftSize = vectorEqual(times, shiftTimes);
2327 validShiftSize = validShiftSize && vectorEqual(moneyness, sd.shiftStrikes);
2328
2329 // Loop and apply scenarios
2330 for (Size sj = 0; sj < sd.shiftExpiries.size(); ++sj) {
2331 for (Size si = 0; si < sd.shiftStrikes.size(); ++si) {
2332
2333 QuantLib::ext::shared_ptr<Scenario> scenario =
2334 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
2335
2336 applyShift(si, sj, getShiftSize(sd), up, shiftType, sd.shiftStrikes, shiftTimes, moneyness, times,
2337 baseValues, shiftedValues, true);
2338
2339 Size counter = 0;
2340 for (Size i = 0; i < moneyness.size(); i++) {
2341 for (Size j = 0; j < expiries.size(); ++j) {
2342 RiskFactorKey key(RFType::CommodityVolatility, name, counter++);
2343 if (sensitivityData_->useSpreadedTermStructures()) {
2344 scenario->add(key, shiftedValues[i][j] - baseValues[i][j]);
2345 } else {
2346 scenario->add(key, shiftedValues[i][j]);
2347 }
2348 // Possibly store valid shift size
2349 if (validShiftSize && si == i && sj == j) {
2350 storeShiftData(key, baseValues[i][j], shiftedValues[i][j]);
2351 }
2352 }
2353 }
2354
2355 // Give the scenario a label
2356
2357 // Add the final scenario to the scenario vector
2359 scenario->label(to_string(scenarioDescriptions_.back()));
2360 scenarios_.push_back(scenario);
2361 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
2362 }
2363 }
2364 }
2365 DLOG("Commodity volatility scenarios done");
2366}
const std::map< RiskFactorKey, QuantLib::Real > & baseValues() const
ScenarioDescription commodityVolScenarioDescription(const std::string &commodityName, QuantLib::Size expiryBucket, QuantLib::Size strikeBucket, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateSecuritySpreadScenarios()

void generateSecuritySpreadScenarios ( bool  up)
private

Definition at line 2480 of file sensitivityscenariogenerator.cpp.

2480 {
2481 // We can choose to shift fewer discount curves than listed in the market
2482 Date asof = baseScenario_->asof();
2483 // Log an ALERT if some equities in simmarket are excluded from the sensitivities list
2484 for (auto sim_security : simMarketData_->securities()) {
2485 if (sensitivityData_->securityShiftData().find(sim_security) == sensitivityData_->securityShiftData().end()) {
2486 WLOG("Security " << sim_security << " in simmarket is not included in sensitivities analysis");
2487 }
2488 }
2489 for (auto s : sensitivityData_->securityShiftData()) {
2490 string bond = s.first;
2492 if (!isScenarioRelevant(up, data))
2493 continue;
2494 ShiftType type = getShiftType(data);
2495 Real size = up ? getShiftSize(data) : -1.0 * getShiftSize(data);
2496 bool relShift = (type == ShiftType::Relative);
2497
2498 QuantLib::ext::shared_ptr<Scenario> scenario =
2499 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
2500
2501 RiskFactorKey key(RiskFactorKey::KeyType::SecuritySpread, bond);
2502 Real base_spread;
2503 if (!tryGetBaseScenarioValue(baseScenarioAbsolute_, key, base_spread, continueOnError_))
2504 continue;
2505 Real newSpread = relShift ? base_spread * (1.0 + size) : (base_spread + size);
2506 // Real newRate = up ? rate * (1.0 + getShiftSize(data)) : rate * (1.0 - getShiftSize(data));
2507 scenario->add(key, sensitivityData_->useSpreadedTermStructures() ? newSpread - base_spread : newSpread);
2508
2509 storeShiftData(key, base_spread, newSpread);
2510
2511 scenarios_.push_back(scenario);
2513 scenario->label(to_string(scenarioDescriptions_.back()));
2514 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
2515 << " created: " << newSpread);
2516 }
2517 DLOG("Security scenarios done");
2518}
ScenarioDescription securitySpreadScenarioDescription(string bond, bool up, ShiftScheme shiftScheme)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateCorrelationScenarios()

void generateCorrelationScenarios ( bool  up)
private

Definition at line 2368 of file sensitivityscenariogenerator.cpp.

2368 {
2369 Date asof = baseScenario_->asof();
2370 for (auto sim_cap : simMarketData_->correlationPairs()) {
2371 if (sensitivityData_->correlationShiftData().find(sim_cap) == sensitivityData_->correlationShiftData().end()) {
2372 WLOG("Correlation " << sim_cap << " in simmarket is not included in sensitivities analysis");
2373 }
2374 }
2375
2376 Size n_c_strikes = simMarketData_->correlationStrikes().size();
2377 vector<Real> corrStrikes = simMarketData_->correlationStrikes();
2378
2379 for (auto c : sensitivityData_->correlationShiftData()) {
2380 std::string label = c.first;
2381 std::vector<std::string> tokens = ore::data::getCorrelationTokens(label);
2382 std::pair<string, string> pair(tokens[0], tokens[1]);
2383 Size n_c_exp = simMarketData_->correlationExpiries().size();
2384 SensitivityScenarioData::VolShiftData data = c.second;
2385 if (!isScenarioRelevant(up, data))
2386 continue;
2387 ShiftType shiftType = getShiftType(data);
2388 Real shiftSize = getShiftSize(data);
2389 vector<vector<Real>> corrData(n_c_exp, vector<Real>(n_c_strikes, 0.0));
2390 vector<Real> corrExpiryTimes(n_c_exp, 0.0);
2391 vector<vector<Real>> shiftedCorrData(n_c_exp, vector<Real>(n_c_strikes, 0.0));
2392
2393 std::vector<Period> expiries = overrideTenors_ ? simMarketData_->correlationExpiries() : data.shiftExpiries;
2394 QL_REQUIRE(expiries.size() == data.shiftExpiries.size(), "mismatch between effective shift expiries ("
2395 << expiries.size() << ") and shift tenors ("
2396 << data.shiftExpiries.size());
2397 vector<Real> shiftExpiryTimes(expiries.size(), 0.0);
2398 vector<Real> shiftStrikes = data.shiftStrikes;
2399
2400 DayCounter dc = Actual365Fixed();
2401 try {
2402 if (auto s = simMarket_.lock()) {
2403 dc = s->correlationCurve(pair.first, pair.second)->dayCounter();
2404 } else {
2405 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
2406 }
2407 } catch (const std::exception&) {
2408 WLOG("Day counter lookup in simulation market failed for correlation curve "
2409 << pair.first << " - " << pair.second << ", using default A365");
2410 }
2411
2412 // cache original vol data
2413 for (Size j = 0; j < n_c_exp; ++j) {
2414 Date expiry = asof + simMarketData_->correlationExpiries()[j];
2415 corrExpiryTimes[j] = dc.yearFraction(asof, expiry);
2416 }
2417 bool valid = true;
2418 for (Size j = 0; j < n_c_exp; ++j) {
2419 for (Size k = 0; k < n_c_strikes; ++k) {
2420 Size idx = j * n_c_strikes + k;
2421 RiskFactorKey key(RiskFactorKey::KeyType::Correlation, label, idx);
2422 valid = valid && tryGetBaseScenarioValue(baseScenarioAbsolute_, key, corrData[j][k], continueOnError_);
2423 }
2424 }
2425 if (!valid)
2426 continue;
2427
2428 // cache tenor times
2429 for (Size j = 0; j < shiftExpiryTimes.size(); ++j)
2430 shiftExpiryTimes[j] = dc.yearFraction(asof, asof + expiries[j]);
2431
2432 // Can we store a valid shift size?
2433 bool validShiftSize = vectorEqual(corrExpiryTimes, shiftExpiryTimes);
2434 validShiftSize = validShiftSize && vectorEqual(corrStrikes, shiftStrikes);
2435
2436 // loop over shift expiries and terms
2437 for (Size j = 0; j < shiftExpiryTimes.size(); ++j) {
2438 for (Size k = 0; k < shiftStrikes.size(); ++k) {
2439 QuantLib::ext::shared_ptr<Scenario> scenario =
2440 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
2441
2442 applyShift(j, k, shiftSize, up, shiftType, shiftExpiryTimes, shiftStrikes, corrExpiryTimes, corrStrikes,
2443 corrData, shiftedCorrData, true);
2444
2445 // add shifted vol data to the scenario
2446 for (Size jj = 0; jj < n_c_exp; ++jj) {
2447 for (Size kk = 0; kk < n_c_strikes; ++kk) {
2448 Size idx = jj * n_c_strikes + kk;
2449 RiskFactorKey key(RFType::Correlation, label, idx);
2450
2451 if (shiftedCorrData[jj][kk] > 1) {
2452 shiftedCorrData[jj][kk] = 1;
2453 } else if (shiftedCorrData[jj][kk] < -1) {
2454 shiftedCorrData[jj][kk] = -1;
2455 }
2456
2457 if (sensitivityData_->useSpreadedTermStructures()) {
2458 scenario->add(key, shiftedCorrData[jj][kk] - corrData[jj][kk]);
2459 } else {
2460 scenario->add(key, shiftedCorrData[jj][kk]);
2461 }
2462 // Possibly store valid shift size
2463 if (validShiftSize && j == jj && k == kk) {
2464 storeShiftData(key, corrData[jj][kk], shiftedCorrData[jj][kk]);
2465 }
2466 }
2467 }
2468
2469 // add this scenario to the scenario vector
2470 scenarios_.push_back(scenario);
2471 scenarioDescriptions_.push_back(correlationScenarioDescription(label, j, k, up, getShiftScheme(data)));
2472 scenario->label(to_string(scenarioDescriptions_.back()));
2473 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label() << " created");
2474 }
2475 }
2476 }
2477 DLOG("Correlation scenarios done");
2478}
ScenarioDescription correlationScenarioDescription(string pair, Size expiryBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
std::vector< std::string > getCorrelationTokens(const std::string &name)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ generateGenericYieldVolScenarios()

void generateGenericYieldVolScenarios ( bool  up,
RiskFactorKey::KeyType  rfType 
)
private

Definition at line 1062 of file sensitivityscenariogenerator.cpp.

1062 {
1063
1064 Date asof = baseScenario_->asof();
1065
1066 // set parameters for swaption resp. yield vol scenarios
1067
1068 bool atmOnly;
1069 map<string, SensitivityScenarioData::GenericYieldVolShiftData> shiftData;
1070 function<Size(string)> get_n_term;
1071 function<Size(string)> get_n_expiry;
1072 function<vector<Real>(string)> getVolStrikes;
1073 function<vector<Period>(string)> getVolExpiries;
1074 function<vector<Period>(string)> getVolTerms;
1075 function<string(string)> getDayCounter;
1076 function<ScenarioDescription(string, Size, Size, Size, bool, SensitivityScenarioData::ShiftData&)>
1077 getScenarioDescription;
1078
1079 if (rfType == RFType::SwaptionVolatility) {
1080 atmOnly = simMarketData_->simulateSwapVolATMOnly();
1081 shiftData = sensitivityData_->swaptionVolShiftData();
1082 get_n_term = [this](const string& k) { return simMarketData_->swapVolTerms(k).size(); };
1083 get_n_expiry = [this](const string& k) { return simMarketData_->swapVolExpiries(k).size(); };
1084 getVolStrikes = [this](const string& k) { return simMarketData_->swapVolStrikeSpreads(k); };
1085 getVolExpiries = [this](const string& k) { return simMarketData_->swapVolExpiries(k); };
1086 getVolTerms = [this](const string& k) { return simMarketData_->swapVolTerms(k); };
1087 getDayCounter = [this](const string& k) {
1088 try {
1089 if (auto s = simMarket_.lock()) {
1090 return to_string(s->swaptionVol(k)->dayCounter());
1091 } else {
1092 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1093 }
1094 } catch (const std::exception&) {
1095 WLOG("Day counter lookup in simulation market failed for swaption vol '" << k
1096 << "', using default A365");
1097 return std::string("A365F");
1098 }
1099 };
1100 getScenarioDescription = [this](string q, Size n, Size m, Size k, bool up,
1101 SensitivityScenarioData::ShiftData& data) {
1102 return swaptionVolScenarioDescription(q, n, m, k, up, getShiftScheme(data));
1103 };
1104 } else if (rfType == RFType::YieldVolatility) {
1105 atmOnly = true;
1106 shiftData = sensitivityData_->yieldVolShiftData();
1107 get_n_term = [this](const string& k) { return simMarketData_->yieldVolTerms().size(); };
1108 get_n_expiry = [this](const string& k) { return simMarketData_->yieldVolExpiries().size(); };
1109 getVolStrikes = [](const string& k) { return vector<Real>({0.0}); };
1110 getVolExpiries = [this](const string& k) { return simMarketData_->yieldVolExpiries(); };
1111 getVolTerms = [this](const string& k) { return simMarketData_->yieldVolTerms(); };
1112 getDayCounter = [this](const string& k) {
1113 try {
1114 if (auto s = simMarket_.lock()) {
1115 return to_string(s->yieldVol(k)->dayCounter());
1116 } else {
1117 QL_FAIL("Internal error: could not lock simMarket. Contact dev.");
1118 }
1119 } catch (const std::exception&) {
1120 WLOG("Day counter lookup in simulation market failed for swaption vol '" << k
1121 << "', using default A365");
1122 return std::string("A365F");
1123 }
1124 };
1125 getScenarioDescription = [this](string q, Size n, Size m, Size k, bool up,
1126 SensitivityScenarioData::ShiftData& data) {
1127 return yieldVolScenarioDescription(q, n, m, up, getShiftScheme(data));
1128 };
1129 } else {
1130 QL_FAIL("SensitivityScenarioGenerator::generateGenericYieldVolScenarios: risk factor type " << rfType
1131 << " not handled.");
1132 }
1133
1134 // generate scenarios
1135 for (auto s : shiftData) {
1136 std::string qualifier = s.first;
1137
1138 Size n_term;
1139 try {
1140 n_term = get_n_term(qualifier);
1141 } catch (const std::exception& e) {
1142 ALOG("skip scenario generation for general yield vol " << qualifier << ": " << e.what());
1143 continue;
1144 }
1145 Size n_expiry = get_n_expiry(qualifier);
1146
1147 vector<Real> volExpiryTimes(n_expiry, 0.0);
1148 vector<Real> volTermTimes(n_term, 0.0);
1149 Size n_strike = getVolStrikes(qualifier).size();
1150
1151 vector<vector<vector<Real>>> volData(n_strike, vector<vector<Real>>(n_expiry, vector<Real>(n_term, 0.0)));
1152 vector<vector<vector<Real>>> shiftedVolData = volData;
1153
1154 SensitivityScenarioData::GenericYieldVolShiftData data = s.second;
1155 if (!isScenarioRelevant(up, data))
1156 continue;
1157 ShiftType shiftType = getShiftType(data);
1158 Real shiftSize = getShiftSize(data);
1159
1160 vector<Real> shiftExpiryTimes(data.shiftExpiries.size(), 0.0);
1161 vector<Real> shiftTermTimes(data.shiftTerms.size(), 0.0);
1162
1163 vector<Real> shiftStrikes;
1164 if (!atmOnly) {
1165 shiftStrikes = data.shiftStrikes;
1166 QL_REQUIRE(data.shiftStrikes.size() == n_strike,
1167 "number of simulated strikes must equal number of sensitivity strikes");
1168 } else {
1169 shiftStrikes = {0.0};
1170 }
1171
1172 DayCounter dc = parseDayCounter(getDayCounter(qualifier));
1173
1174 // cache original vol data
1175 for (Size j = 0; j < n_expiry; ++j) {
1176 Date expiry = asof + getVolExpiries(qualifier)[j];
1177 volExpiryTimes[j] = dc.yearFraction(asof, expiry);
1178 }
1179 for (Size j = 0; j < n_term; ++j) {
1180 Date term = asof + getVolTerms(qualifier)[j];
1181 volTermTimes[j] = dc.yearFraction(asof, term);
1182 }
1183
1184 bool valid = true;
1185 for (Size j = 0; j < n_expiry; ++j) {
1186 for (Size k = 0; k < n_term; ++k) {
1187 for (Size l = 0; l < n_strike; ++l) {
1188 Size idx = j * n_term * n_strike + k * n_strike + l;
1189 RiskFactorKey key(rfType, qualifier, idx);
1190 valid = valid &&
1191 tryGetBaseScenarioValue(baseScenarioAbsolute_, key, volData[l][j][k], continueOnError_);
1192 }
1193 }
1194 }
1195 if (!valid)
1196 continue;
1197
1198 // cache tenor times
1199 for (Size j = 0; j < shiftExpiryTimes.size(); ++j)
1200 shiftExpiryTimes[j] = dc.yearFraction(asof, asof + data.shiftExpiries[j]);
1201 for (Size j = 0; j < shiftTermTimes.size(); ++j)
1202 shiftTermTimes[j] = dc.yearFraction(asof, asof + data.shiftTerms[j]);
1203
1204 // Can we store a valid shift size?
1205 bool validShiftSize = vectorEqual(volExpiryTimes, shiftExpiryTimes);
1206 validShiftSize = validShiftSize && vectorEqual(volTermTimes, shiftTermTimes);
1207 validShiftSize = validShiftSize && vectorEqual(getVolStrikes(qualifier), shiftStrikes);
1208
1209 // loop over shift expiries, terms and strikes
1210 for (Size j = 0; j < shiftExpiryTimes.size(); ++j) {
1211 for (Size k = 0; k < shiftTermTimes.size(); ++k) {
1212 for (Size l = 0; l < shiftStrikes.size(); ++l) {
1213 Size strikeBucket = l;
1214 QuantLib::ext::shared_ptr<Scenario> scenario =
1215 sensiScenarioFactory_->buildScenario(asof, !sensitivityData_->useSpreadedTermStructures());
1216
1217 // if simulating atm only we shift all strikes otherwise we shift each strike individually
1218 Size loopStart = atmOnly ? 0 : l;
1219 Size loopEnd = atmOnly ? n_strike : loopStart + 1;
1220
1221 for (Size ll = loopStart; ll < loopEnd; ++ll) {
1222 applyShift(j, k, shiftSize, up, shiftType, shiftExpiryTimes, shiftTermTimes, volExpiryTimes,
1223 volTermTimes, volData[ll], shiftedVolData[ll], true);
1224 }
1225
1226 for (Size jj = 0; jj < n_expiry; ++jj) {
1227 for (Size kk = 0; kk < n_term; ++kk) {
1228 for (Size ll = 0; ll < n_strike; ++ll) {
1229
1230 Size idx = jj * n_term * n_strike + kk * n_strike + ll;
1231 RiskFactorKey key(rfType, qualifier, idx);
1232
1233 if (ll >= loopStart && ll < loopEnd) {
1234 if (sensitivityData_->useSpreadedTermStructures()) {
1235 scenario->add(key, shiftedVolData[ll][jj][kk] - volData[ll][jj][kk]);
1236 } else {
1237 scenario->add(key, shiftedVolData[ll][jj][kk]);
1238 }
1239 }
1240
1241 // Possibly store valid shift size
1242 if (validShiftSize && j == jj && k == kk && l == ll) {
1243 storeShiftData(key, volData[ll][jj][kk], shiftedVolData[ll][jj][kk]);
1244 }
1245 }
1246 }
1247 }
1248
1249 // add this scenario to the scenario vector
1250 scenarios_.push_back(scenario);
1251 scenarioDescriptions_.push_back(getScenarioDescription(qualifier, j, k, strikeBucket, up, data));
1252 scenario->label(to_string(scenarioDescriptions_.back()));
1253 DLOG("Sensitivity scenario # " << scenarios_.size() << ", label " << scenario->label()
1254 << " created for generic yield vol " << qualifier);
1255 }
1256 }
1257 }
1258 }
1259}
ScenarioDescription yieldVolScenarioDescription(string securityId, Size expiryBucket, Size termBucket, bool up, ShiftScheme shiftScheme)
ScenarioDescription swaptionVolScenarioDescription(string ccy, Size expiryBucket, Size termBucket, Size strikeBucket, bool up, ShiftScheme shiftScheme)
DayCounter parseDayCounter(const string &s)
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ discountScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription discountScenarioDescription ( string  ccy,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2559 of file sensitivityscenariogenerator.cpp.

2559 {
2560 QL_REQUIRE(sensitivityData_->discountCurveShiftData().find(ccy) != sensitivityData_->discountCurveShiftData().end(),
2561 "currency " << ccy << " not found in discount shift data");
2562 QL_REQUIRE(bucket < sensitivityData_->discountCurveShiftData()[ccy]->shiftTenors.size(),
2563 "bucket " << bucket << " out of range");
2564 RiskFactorKey key(RiskFactorKey::KeyType::DiscountCurve, ccy, bucket);
2565 std::ostringstream o;
2566 o << sensitivityData_->discountCurveShiftData()[ccy]->shiftTenors[bucket];
2567 string text = o.str();
2568 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2569 ScenarioDescription desc(type, key, text);
2570 shiftSchemes_[key] = shiftScheme;
2571 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2572 return desc;
2573}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ indexScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription indexScenarioDescription ( string  index,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2576 of file sensitivityscenariogenerator.cpp.

2576 {
2577 QL_REQUIRE(sensitivityData_->indexCurveShiftData().find(index) != sensitivityData_->indexCurveShiftData().end(),
2578 "currency " << index << " not found in index shift data");
2579 QL_REQUIRE(bucket < sensitivityData_->indexCurveShiftData()[index]->shiftTenors.size(),
2580 "bucket " << bucket << " out of range");
2581 RiskFactorKey key(RiskFactorKey::KeyType::IndexCurve, index, bucket);
2582 std::ostringstream o;
2583 o << sensitivityData_->indexCurveShiftData()[index]->shiftTenors[bucket];
2584 string text = o.str();
2585 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2586 ScenarioDescription desc(type, key, text);
2587 shiftSchemes_[key] = shiftScheme;
2588 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2589 return desc;
2590}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ yieldScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription yieldScenarioDescription ( string  name,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2593 of file sensitivityscenariogenerator.cpp.

2593 {
2594 QL_REQUIRE(sensitivityData_->yieldCurveShiftData().find(name) != sensitivityData_->yieldCurveShiftData().end(),
2595 "currency " << name << " not found in index shift data");
2596 QL_REQUIRE(bucket < sensitivityData_->yieldCurveShiftData()[name]->shiftTenors.size(),
2597 "bucket " << bucket << " out of range");
2598 RiskFactorKey key(RiskFactorKey::KeyType::YieldCurve, name, bucket);
2599 std::ostringstream o;
2600 o << sensitivityData_->yieldCurveShiftData()[name]->shiftTenors[bucket];
2601 string text = o.str();
2602 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2603 ScenarioDescription desc(type, key, text);
2604 shiftSchemes_[key] = shiftScheme;
2605 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2606 return desc;
2607}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fxScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription fxScenarioDescription ( string  ccypair,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2521 of file sensitivityscenariogenerator.cpp.

2521 {
2522 RiskFactorKey key(RiskFactorKey::KeyType::FXSpot, ccypair);
2523 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2524 ScenarioDescription desc(type, key, "spot");
2525 shiftSchemes_[key] = shiftScheme;
2526 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2527 return desc;
2528}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ fxVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription fxVolScenarioDescription ( string  ccypair,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2610 of file sensitivityscenariogenerator.cpp.

2611 {
2612 QL_REQUIRE(sensitivityData_->fxVolShiftData().find(ccypair) != sensitivityData_->fxVolShiftData().end(),
2613 "currency pair " << ccypair << " not found in fx vol shift data");
2614 SensitivityScenarioData::VolShiftData data = sensitivityData_->fxVolShiftData()[ccypair];
2615 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2616 Size index = strikeBucket * data.shiftExpiries.size() + expiryBucket;
2617 RiskFactorKey key(RiskFactorKey::KeyType::FXVolatility, ccypair, index);
2618 std::ostringstream o;
2619 if (data.shiftStrikes.size() == 0 ||
2620 close_enough(data.shiftStrikes[strikeBucket], 0)) { // shiftStrikes defaults to {0.00}
2621 o << data.shiftExpiries[expiryBucket] << "/ATM";
2622 } else {
2623 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2624 o << data.shiftExpiries[expiryBucket] << "/" << data.shiftStrikes[strikeBucket];
2625 }
2626 string text = o.str();
2627 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2628 ScenarioDescription desc(type, key, text);
2629 shiftSchemes_[key] = shiftScheme;
2630 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2631 return desc;
2632}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ equityScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription equityScenarioDescription ( string  equity,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2531 of file sensitivityscenariogenerator.cpp.

2531 {
2532 RiskFactorKey key(RiskFactorKey::KeyType::EquitySpot, equity);
2533 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2534 ScenarioDescription desc(type, key, "spot");
2535 shiftSchemes_[key] = shiftScheme;
2536 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2537 return desc;
2538}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ dividendYieldScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription dividendYieldScenarioDescription ( string  equity,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2541 of file sensitivityscenariogenerator.cpp.

2541 {
2542 QL_REQUIRE(sensitivityData_->dividendYieldShiftData().find(name) !=
2543 sensitivityData_->dividendYieldShiftData().end(),
2544 "equity " << name << " not found in dividend yield shift data");
2545 QL_REQUIRE(bucket < sensitivityData_->dividendYieldShiftData()[name]->shiftTenors.size(),
2546 "bucket " << bucket << " out of range");
2547 RiskFactorKey key(RiskFactorKey::KeyType::DividendYield, name, bucket);
2548 std::ostringstream o;
2549 o << sensitivityData_->dividendYieldShiftData()[name]->shiftTenors[bucket];
2550 string text = o.str();
2551 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2552 ScenarioDescription desc(type, key, text);
2553 shiftSchemes_[key] = shiftScheme;
2554 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2555 return desc;
2556}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ equityVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription equityVolScenarioDescription ( string  equity,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2635 of file sensitivityscenariogenerator.cpp.

2636 {
2637 QL_REQUIRE(sensitivityData_->equityVolShiftData().find(equity) != sensitivityData_->equityVolShiftData().end(),
2638 "currency pair " << equity << " not found in fx vol shift data");
2639 SensitivityScenarioData::VolShiftData data = sensitivityData_->equityVolShiftData()[equity];
2640 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2641 Size index = strikeBucket * data.shiftExpiries.size() + expiryBucket;
2642 RiskFactorKey key(RiskFactorKey::KeyType::EquityVolatility, equity, index);
2643 std::ostringstream o;
2644 if (data.shiftStrikes.size() == 0 || close_enough(data.shiftStrikes[strikeBucket], 0)) {
2645 o << data.shiftExpiries[expiryBucket] << "/ATM";
2646 } else {
2647 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2648 o << data.shiftExpiries[expiryBucket] << "/" << data.shiftStrikes[strikeBucket];
2649 }
2650 string text = o.str();
2651 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2652 ScenarioDescription desc(type, key, text);
2653 shiftSchemes_[key] = shiftScheme;
2654 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2655 return desc;
2656}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ swaptionVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription swaptionVolScenarioDescription ( string  ccy,
Size  expiryBucket,
Size  termBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2659 of file sensitivityscenariogenerator.cpp.

2660 {
2661 QL_REQUIRE(sensitivityData_->swaptionVolShiftData().find(ccy) != sensitivityData_->swaptionVolShiftData().end(),
2662 "currency " << ccy << " not found in swaption vol shift data");
2663 SensitivityScenarioData::GenericYieldVolShiftData data = sensitivityData_->swaptionVolShiftData()[ccy];
2664 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2665 QL_REQUIRE(termBucket < data.shiftTerms.size(), "term bucket " << termBucket << " out of range");
2666 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2667 Size index = expiryBucket * data.shiftStrikes.size() * data.shiftTerms.size() +
2668 termBucket * data.shiftStrikes.size() + strikeBucket;
2669 RiskFactorKey key(RiskFactorKey::KeyType::SwaptionVolatility, ccy, index);
2670 std::ostringstream o;
2671 if (data.shiftStrikes.size() == 0 || close_enough(data.shiftStrikes[strikeBucket], 0)) {
2672 o << data.shiftExpiries[expiryBucket] << "/" << data.shiftTerms[termBucket] << "/ATM";
2673 } else {
2674 o << data.shiftExpiries[expiryBucket] << "/" << data.shiftTerms[termBucket] << "/" << std::setprecision(4)
2675 << data.shiftStrikes[strikeBucket];
2676 }
2677 string text = o.str();
2678 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2679 ScenarioDescription desc(type, key, text);
2680 shiftSchemes_[key] = shiftScheme;
2681 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2682 return desc;
2683}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ yieldVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription yieldVolScenarioDescription ( string  securityId,
Size  expiryBucket,
Size  termBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2686 of file sensitivityscenariogenerator.cpp.

2687 {
2688 QL_REQUIRE(sensitivityData_->yieldVolShiftData().find(securityId) != sensitivityData_->yieldVolShiftData().end(),
2689 "currency " << securityId << " not found in yield vol shift data");
2690 SensitivityScenarioData::GenericYieldVolShiftData data = sensitivityData_->yieldVolShiftData()[securityId];
2691 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2692 QL_REQUIRE(termBucket < data.shiftTerms.size(), "term bucket " << termBucket << " out of range");
2693 Size index =
2694 expiryBucket * data.shiftStrikes.size() * data.shiftTerms.size() + termBucket * data.shiftStrikes.size();
2695 RiskFactorKey key(RiskFactorKey::KeyType::YieldVolatility, securityId, index);
2696 std::ostringstream o;
2697 o << data.shiftExpiries[expiryBucket] << "/" << data.shiftTerms[termBucket] << "/ATM";
2698 string text = o.str();
2699 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2700 ScenarioDescription desc(type, key, text);
2701 shiftSchemes_[key] = shiftScheme;
2702 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2703 return desc;
2704}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ capFloorVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription capFloorVolScenarioDescription ( string  ccy,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
bool  isAtm,
ShiftScheme  shiftScheme 
)
private

Definition at line 2707 of file sensitivityscenariogenerator.cpp.

2708 {
2709 QL_REQUIRE(sensitivityData_->capFloorVolShiftData().find(ccy) != sensitivityData_->capFloorVolShiftData().end(),
2710 "currency " << ccy << " not found in cap/floor vol shift data");
2711 SensitivityScenarioData::CapFloorVolShiftData data = *sensitivityData_->capFloorVolShiftData()[ccy];
2712 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2713 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2714 Size index = expiryBucket * data.shiftStrikes.size() + strikeBucket;
2715 RiskFactorKey key(RiskFactorKey::KeyType::OptionletVolatility, ccy, index);
2716 std::ostringstream o;
2717 o << data.shiftExpiries[expiryBucket] << "/";
2718 if (isAtm) {
2719 o << "ATM";
2720 } else {
2721 o << std::setprecision(4) << data.shiftStrikes[strikeBucket];
2722 }
2723 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2724 ScenarioDescription desc(type, key, o.str());
2725 shiftSchemes_[key] = shiftScheme;
2726 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2727 return desc;
2728}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ survivalProbabilityScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription survivalProbabilityScenarioDescription ( string  name,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2731 of file sensitivityscenariogenerator.cpp.

2732 {
2733 QL_REQUIRE(sensitivityData_->creditCurveShiftData().find(name) != sensitivityData_->creditCurveShiftData().end(),
2734 "Name " << name << " not found in credit shift data");
2735 QL_REQUIRE(bucket < sensitivityData_->creditCurveShiftData()[name]->shiftTenors.size(),
2736 "bucket " << bucket << " out of range");
2737 RiskFactorKey key(RiskFactorKey::KeyType::SurvivalProbability, name, bucket);
2738 std::ostringstream o;
2739 o << sensitivityData_->creditCurveShiftData()[name]->shiftTenors[bucket];
2740 string text = o.str();
2741 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2742 ScenarioDescription desc(type, key, text);
2743 shiftSchemes_[key] = shiftScheme;
2744 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2745 return desc;
2746}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ CdsVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription CdsVolScenarioDescription ( string  name,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2749 of file sensitivityscenariogenerator.cpp.

2750 {
2751 QL_REQUIRE(sensitivityData_->cdsVolShiftData().find(name) != sensitivityData_->cdsVolShiftData().end(),
2752 "name " << name << " not found in swaption name shift data");
2753 SensitivityScenarioData::CdsVolShiftData data = sensitivityData_->cdsVolShiftData()[name];
2754 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2755 Size index = strikeBucket * data.shiftExpiries.size() + expiryBucket;
2756 RiskFactorKey key(RiskFactorKey::KeyType::CDSVolatility, name, index);
2757 std::ostringstream o;
2758 o << data.shiftExpiries[expiryBucket] << "/"
2759 << "ATM";
2760 string text = o.str();
2761 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2762 ScenarioDescription desc(type, key, text);
2763 shiftSchemes_[key] = shiftScheme;
2764 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2765 return desc;
2766}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ zeroInflationScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription zeroInflationScenarioDescription ( string  index,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2769 of file sensitivityscenariogenerator.cpp.

2769 {
2770 QL_REQUIRE(sensitivityData_->zeroInflationCurveShiftData().find(index) !=
2771 sensitivityData_->zeroInflationCurveShiftData().end(),
2772 "inflation index " << index << " not found in zero inflation index shift data");
2773 QL_REQUIRE(bucket < sensitivityData_->zeroInflationCurveShiftData()[index]->shiftTenors.size(),
2774 "bucket " << bucket << " out of range");
2775 RiskFactorKey key(RiskFactorKey::KeyType::ZeroInflationCurve, index, bucket);
2776 std::ostringstream o;
2777 o << sensitivityData_->zeroInflationCurveShiftData()[index]->shiftTenors[bucket];
2778 string text = o.str();
2779 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2780 ScenarioDescription desc(type, key, text);
2781 shiftSchemes_[key] = shiftScheme;
2782 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2783 return desc;
2784}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ yoyInflationScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription yoyInflationScenarioDescription ( string  index,
Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2787 of file sensitivityscenariogenerator.cpp.

2787 {
2788 QL_REQUIRE(sensitivityData_->yoyInflationCurveShiftData().find(index) !=
2789 sensitivityData_->yoyInflationCurveShiftData().end(),
2790 "yoy inflation index " << index << " not found in zero inflation index shift data");
2791 QL_REQUIRE(bucket < sensitivityData_->yoyInflationCurveShiftData()[index]->shiftTenors.size(),
2792 "bucket " << bucket << " out of range");
2793 RiskFactorKey key(RiskFactorKey::KeyType::YoYInflationCurve, index, bucket);
2794 std::ostringstream o;
2795 o << sensitivityData_->yoyInflationCurveShiftData()[index]->shiftTenors[bucket];
2796 string text = o.str();
2797 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2798 ScenarioDescription desc(type, key, text);
2799 shiftSchemes_[key] = shiftScheme;
2800 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2801 return desc;
2802}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ zeroInflationCapFloorVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription zeroInflationCapFloorVolScenarioDescription ( string  name,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2828 of file sensitivityscenariogenerator.cpp.

2830 {
2831 QL_REQUIRE(sensitivityData_->zeroInflationCapFloorVolShiftData().find(name) !=
2832 sensitivityData_->zeroInflationCapFloorVolShiftData().end(),
2833 "currency " << name << " not found in zero inflation cap/floor vol shift data");
2834 SensitivityScenarioData::VolShiftData data = *sensitivityData_->zeroInflationCapFloorVolShiftData()[name];
2835 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2836 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2837 Size index = expiryBucket * data.shiftStrikes.size() + strikeBucket;
2838 RiskFactorKey key(RiskFactorKey::KeyType::ZeroInflationCapFloorVolatility, name, index);
2839 std::ostringstream o;
2840 if (data.shiftStrikes.size() == 0 || close_enough(data.shiftStrikes[strikeBucket], 0)) {
2841 o << data.shiftExpiries[expiryBucket] << "/ATM";
2842 } else {
2843 o << data.shiftExpiries[expiryBucket] << "/" << std::setprecision(4) << data.shiftStrikes[strikeBucket];
2844 }
2845 string text = o.str();
2846 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2847 ScenarioDescription desc(type, key, text);
2848 shiftSchemes_[key] = shiftScheme;
2849 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2850 return desc;
2851}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ yoyInflationCapFloorVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription yoyInflationCapFloorVolScenarioDescription ( string  name,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2805 of file sensitivityscenariogenerator.cpp.

2807 {
2808 QL_REQUIRE(sensitivityData_->yoyInflationCapFloorVolShiftData().find(name) !=
2809 sensitivityData_->yoyInflationCapFloorVolShiftData().end(),
2810 "index " << name << " not found in yoy cap/floor vol shift data");
2811 SensitivityScenarioData::CapFloorVolShiftData data = *sensitivityData_->yoyInflationCapFloorVolShiftData()[name];
2812 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2813 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2814 Size index = expiryBucket * data.shiftStrikes.size() + strikeBucket;
2815 RiskFactorKey key(RiskFactorKey::KeyType::YoYInflationCapFloorVolatility, name, index);
2816 std::ostringstream o;
2817 // Currently CapFloorVolShiftData must have a collection of absolute strikes for yoy inflation cap/floor vols
2818 o << data.shiftExpiries[expiryBucket] << "/" << std::setprecision(4) << data.shiftStrikes[strikeBucket];
2819 string text = o.str();
2820 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2821 ScenarioDescription desc(type, key, text);
2822 shiftSchemes_[key] = shiftScheme;
2823 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2824 return desc;
2825}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ baseCorrelationScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription baseCorrelationScenarioDescription ( string  indexName,
Size  lossLevelBucket,
Size  termBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2854 of file sensitivityscenariogenerator.cpp.

2855 {
2856 QL_REQUIRE(sensitivityData_->baseCorrelationShiftData().find(indexName) !=
2857 sensitivityData_->baseCorrelationShiftData().end(),
2858 "name " << indexName << " not found in base correlation shift data");
2859 SensitivityScenarioData::BaseCorrelationShiftData data = sensitivityData_->baseCorrelationShiftData()[indexName];
2860 QL_REQUIRE(termBucket < data.shiftTerms.size(), "term bucket " << termBucket << " out of range");
2861 QL_REQUIRE(lossLevelBucket < data.shiftLossLevels.size(),
2862 "loss level bucket " << lossLevelBucket << " out of range");
2863 Size index = lossLevelBucket * data.shiftTerms.size() + termBucket;
2864 RiskFactorKey key(RiskFactorKey::KeyType::BaseCorrelation, indexName, index);
2865 std::ostringstream o;
2866 o << data.shiftLossLevels[lossLevelBucket] << "/" << data.shiftTerms[termBucket];
2867 string text = o.str();
2868 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2869 ScenarioDescription desc(type, key, text);
2870 shiftSchemes_[key] = shiftScheme;
2871 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2872 return desc;
2873}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ commodityCurveScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription commodityCurveScenarioDescription ( const std::string &  commodityName,
QuantLib::Size  bucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2876 of file sensitivityscenariogenerator.cpp.

2877 {
2878
2879 QL_REQUIRE(sensitivityData_->commodityCurveShiftData().count(commodityName) > 0,
2880 "Name " << commodityName << " not found in commodity curve shift data");
2881 vector<Period>& shiftTenors = sensitivityData_->commodityCurveShiftData()[commodityName]->shiftTenors;
2882 QL_REQUIRE(bucket < shiftTenors.size(), "bucket " << bucket << " out of commodity curve bucket range");
2883
2884 RiskFactorKey key(RiskFactorKey::KeyType::CommodityCurve, commodityName, bucket);
2885 ostringstream oss;
2886 oss << shiftTenors[bucket];
2887 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2888 shiftSchemes_[key] = shiftScheme;
2889 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2890 return ScenarioDescription(type, key, oss.str());
2891}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ commodityVolScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription commodityVolScenarioDescription ( const std::string &  commodityName,
QuantLib::Size  expiryBucket,
QuantLib::Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2894 of file sensitivityscenariogenerator.cpp.

2895 {
2896
2897 QL_REQUIRE(sensitivityData_->commodityVolShiftData().count(commodityName) > 0,
2898 "commodity " << commodityName << " not found in commodity vol shift data");
2899
2900 SensitivityScenarioData::VolShiftData data = sensitivityData_->commodityVolShiftData()[commodityName];
2901 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2902 Size index = strikeBucket * data.shiftExpiries.size() + expiryBucket;
2903 RiskFactorKey key(RiskFactorKey::KeyType::CommodityVolatility, commodityName, index);
2904 ostringstream o;
2905 if (data.shiftStrikes.size() == 0 || close_enough(data.shiftStrikes[strikeBucket], 1.0)) {
2906 o << data.shiftExpiries[expiryBucket] << "/ATM";
2907 } else {
2908 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2909 o << data.shiftExpiries[expiryBucket] << "/" << data.shiftStrikes[strikeBucket];
2910 }
2911 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2912 shiftSchemes_[key] = shiftScheme;
2913 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2914 return ScenarioDescription(type, key, o.str());
2915}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ securitySpreadScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription securitySpreadScenarioDescription ( string  bond,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2943 of file sensitivityscenariogenerator.cpp.

2943 {
2944 RiskFactorKey key(RiskFactorKey::KeyType::SecuritySpread, bond);
2945 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2946 ScenarioDescription desc(type, key, "spread");
2947 shiftSchemes_[key] = shiftScheme;
2948 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2949 return desc;
2950}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ correlationScenarioDescription()

SensitivityScenarioGenerator::ScenarioDescription correlationScenarioDescription ( string  pair,
Size  expiryBucket,
Size  strikeBucket,
bool  up,
ShiftScheme  shiftScheme 
)
private

Definition at line 2918 of file sensitivityscenariogenerator.cpp.

2919 {
2920 QL_REQUIRE(sensitivityData_->correlationShiftData().find(pair) != sensitivityData_->correlationShiftData().end(),
2921 "pair " << pair << " not found in correlation shift data");
2922 SensitivityScenarioData::VolShiftData data = sensitivityData_->correlationShiftData()[pair];
2923 QL_REQUIRE(expiryBucket < data.shiftExpiries.size(), "expiry bucket " << expiryBucket << " out of range");
2924 QL_REQUIRE(strikeBucket < data.shiftStrikes.size(), "strike bucket " << strikeBucket << " out of range");
2925 // Size index = strikeBucket * data.shiftExpiries.size() + expiryBucket;
2926 Size index = expiryBucket * data.shiftStrikes.size() + strikeBucket;
2927 RiskFactorKey key(RiskFactorKey::KeyType::Correlation, pair, index);
2928 std::ostringstream o;
2929 if (data.shiftStrikes.size() == 0 || close_enough(data.shiftStrikes[strikeBucket], 0)) {
2930 o << data.shiftExpiries[expiryBucket] << "/ATM";
2931 } else {
2932 o << data.shiftExpiries[expiryBucket] << "/" << std::setprecision(4) << data.shiftStrikes[strikeBucket];
2933 }
2934 string text = o.str();
2935 ScenarioDescription::Type type = up ? ScenarioDescription::Type::Up : ScenarioDescription::Type::Down;
2936 ScenarioDescription desc(type, key, text);
2937 shiftSchemes_[key] = shiftScheme;
2938 storeShiftData(key, 0.0, 0.0); // default, only used if not popoulated before
2939 return desc;
2940}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ sensitivityData_

QuantLib::ext::shared_ptr<SensitivityScenarioData> sensitivityData_
private

Definition at line 206 of file sensitivityscenariogenerator.hpp.

◆ sensiScenarioFactory_

QuantLib::ext::shared_ptr<ScenarioFactory> sensiScenarioFactory_
private

Definition at line 207 of file sensitivityscenariogenerator.hpp.

◆ sensitivityTemplate_

std::string sensitivityTemplate_
private

Definition at line 208 of file sensitivityscenariogenerator.hpp.

◆ overrideTenors_

const bool overrideTenors_
private

Definition at line 209 of file sensitivityscenariogenerator.hpp.

◆ continueOnError_

const bool continueOnError_
private

Definition at line 209 of file sensitivityscenariogenerator.hpp.

◆ shiftSizes_

std::map<RiskFactorKey, QuantLib::Real> shiftSizes_
private

Holds the shift sizes for each risk factor key.

Definition at line 212 of file sensitivityscenariogenerator.hpp.

◆ shiftSchemes_

std::map<RiskFactorKey, ShiftScheme> shiftSchemes_
private

Holds the delta shift schemes for each risk factor key.

Definition at line 214 of file sensitivityscenariogenerator.hpp.

◆ baseValues_

std::map<RiskFactorKey, QuantLib::Real> baseValues_
private

Holds the base valuesfor each risk factor key.

Definition at line 216 of file sensitivityscenariogenerator.hpp.

◆ baseScenarioAbsolute_

QuantLib::ext::shared_ptr<Scenario> baseScenarioAbsolute_
private

Definition at line 218 of file sensitivityscenariogenerator.hpp.