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

Par Sensitivity Analysis. More...

#include <orea/engine/parsensitivityanalysis.hpp>

+ Collaboration diagram for ParSensitivityAnalysis:

Public Types

typedef std::map< std::pair< ore::analytics::RiskFactorKey, ore::analytics::RiskFactorKey >, Real > ParContainer
 

Public Member Functions

 ParSensitivityAnalysis (const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > &simMarketParams, const ore::analytics::SensitivityScenarioData &sensitivityData, const string &marketConfiguration=Market::defaultConfiguration, const bool continueOnError=false, const std::set< ore::analytics::RiskFactorKey::KeyType > &typesDisabled={})
 Constructor. More...
 
virtual ~ParSensitivityAnalysis ()
 
void computeParInstrumentSensitivities (const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket)
 Compute par instrument sensitivities. More...
 
const ParContainerparSensitivities () const
 Return computed par sensitivities. Empty if they have not been computed yet. More...
 
void alignPillars ()
 align pillars in scenario simulation market parameters with those of the par instruments More...
 
const std::set< ore::analytics::RiskFactorKey > & relevantRiskFactors () const
 get / set the relevant scenarios (if empty, these are ignored) More...
 
std::set< ore::analytics::RiskFactorKey > & relevantRiskFactors ()
 
std::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > shiftSizes () const
 Return the zero rate and par rate absolute shift size for each risk factor key. More...
 
void disable (const std::set< ore::analytics::RiskFactorKey::KeyType > &types)
 
const std::set< ore::analytics::RiskFactorKey::KeyType > & typesDisabled () const
 Return the set of key types disabled for this instance of ParSensitivityAnalysis. More...
 
const ParSensitivityInstrumentBuilder::InstrumentsparInstruments () const
 

Static Public Member Functions

static bool isParType (ore::analytics::RiskFactorKey::KeyType type)
 Returns true if risk factor type is applicable for par conversion. More...
 

Private Member Functions

void augmentRelevantRiskFactors ()
 Augment relevant risk factors. More...
 
void populateShiftSizes (const ore::analytics::RiskFactorKey &key, QuantLib::Real parRate, const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket)
 Populate shiftSizes_ for key given the implied fair par rate parRate. More...
 

Private Attributes

QuantLib::Date asof_
 As of date for the calculation of the par sensitivities. More...
 
QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameterssimMarketParams_
 Simulation market parameters. More...
 
ore::analytics::SensitivityScenarioData sensitivityData_
 Sensitivity data. More...
 
ParContainer parSensi_
 sensitivity of par rates w.r.t. raw rate shifts (including optionlet/cap volatility) More...
 
ParSensitivityInstrumentBuilder::Instruments instruments_
 
std::string marketConfiguration_
 
bool continueOnError_
 
std::set< ore::analytics::RiskFactorKeyrelevantRiskFactors_
 
std::set< ore::analytics::RiskFactorKey::KeyTypetypesDisabled_
 Set of risk factor types disabled for this instance of ParSensitivityAnalysis. More...
 
std::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > shiftSizes_
 

Static Private Attributes

static std::set< ore::analytics::RiskFactorKey::KeyTypeparTypes_
 

Detailed Description

Par Sensitivity Analysis.

This class adds par sensitivity conversion to the base class functionality

Definition at line 57 of file parsensitivityanalysis.hpp.

Member Typedef Documentation

◆ ParContainer

Definition at line 59 of file parsensitivityanalysis.hpp.

Constructor & Destructor Documentation

◆ ParSensitivityAnalysis()

ParSensitivityAnalysis ( const QuantLib::Date &  asof,
const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > &  simMarketParams,
const ore::analytics::SensitivityScenarioData sensitivityData,
const string &  marketConfiguration = Market::defaultConfiguration,
const bool  continueOnError = false,
const std::set< ore::analytics::RiskFactorKey::KeyType > &  typesDisabled = {} 
)

Constructor.

Definition at line 89 of file parsensitivityanalysis.cpp.

94 : asof_(asof), simMarketParams_(simMarketParams), sensitivityData_(sensitivityData),
95 marketConfiguration_(marketConfiguration), continueOnError_(continueOnError), typesDisabled_(typesDisabled) {
96 const QuantLib::ext::shared_ptr<Conventions>& conventions = InstrumentConventions::instance().conventions();
97 QL_REQUIRE(conventions != nullptr, "conventions are empty");
101}
ore::analytics::SensitivityScenarioData sensitivityData_
Sensitivity data.
std::set< ore::analytics::RiskFactorKey::KeyType > typesDisabled_
Set of risk factor types disabled for this instance of ParSensitivityAnalysis.
QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > simMarketParams_
Simulation market parameters.
QuantLib::Date asof_
As of date for the calculation of the par sensitivities.
std::set< ore::analytics::RiskFactorKey > relevantRiskFactors_
ParSensitivityInstrumentBuilder::Instruments instruments_
static std::set< ore::analytics::RiskFactorKey::KeyType > parTypes_
const std::set< ore::analytics::RiskFactorKey::KeyType > & typesDisabled() const
Return the set of key types disabled for this instance of ParSensitivityAnalysis.
void createParInstruments(ParSensitivityInstrumentBuilder::Instruments &instruments, const QuantLib::Date &asof, const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > &simMarketParams, const ore::analytics::SensitivityScenarioData &sensitivityData, const std::set< ore::analytics::RiskFactorKey::KeyType > &typesDisabled={}, const std::set< ore::analytics::RiskFactorKey::KeyType > &parTypes={}, const std::set< ore::analytics::RiskFactorKey > &relevantRiskFactors={}, const bool continueOnError=false, const std::string &marketConfiguration=ore::data::Market::defaultConfiguration, const QuantLib::ext::shared_ptr< ore::analytics::Market > &simMarket=nullptr) const
Create par QuantLib::Instruments.
Date asof(14, Jun, 2018)
+ Here is the call graph for this function:

◆ ~ParSensitivityAnalysis()

virtual ~ParSensitivityAnalysis ( )
virtual

Definition at line 69 of file parsensitivityanalysis.hpp.

69{}

Member Function Documentation

◆ computeParInstrumentSensitivities()

void computeParInstrumentSensitivities ( const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &  simMarket)

Compute par instrument sensitivities.

Definition at line 154 of file parsensitivityanalysis.cpp.

154 {
155
156 LOG("Cache base scenario par rates and flat vols");
157
158 if (relevantRiskFactors_.empty()) {
159 DLOG("Relevant risk factors not provided");
160 } else {
161 DLOG("Relevant risk factors provided:");
162 for (auto const& rf : relevantRiskFactors_)
163 DLOG("Relevant risk factor " << rf);
164 }
165
166 // remove todays fixings from relevant indices for the scope of this method
167 struct TodaysFixingsRemover {
168 TodaysFixingsRemover(const std::set<std::string>& names) : today_(Settings::instance().evaluationDate()) {
169 Date today = Settings::instance().evaluationDate();
170 for (auto const& n : names) {
171 TimeSeries<Real> t = IndexManager::instance().getHistory(n);
172 if (t[today] != Null<Real>()) {
173 DLOG("removing todays fixing (" << std::setprecision(6) << t[today] << ") from " << n);
174 savedFixings_.insert(std::make_pair(n, t[today]));
175 t[today] = Null<Real>();
176 IndexManager::instance().setHistory(n, t);
177 }
178 }
179 }
180 ~TodaysFixingsRemover() {
181 for (auto const& p : savedFixings_) {
182 TimeSeries<Real> t = IndexManager::instance().getHistory(p.first);
183 t[today_] = p.second;
184 IndexManager::instance().setHistory(p.first, t);
185 DLOG("restored todays fixing (" << std::setprecision(6) << p.second << ") for " << p.first);
186 }
187 }
188 const Date today_;
189 std::set<std::pair<std::string, Real>> savedFixings_;
190 };
191 TodaysFixingsRemover fixingRemover(instruments_.removeTodaysFixingIndices_);
192
193 // We must have a ShiftScenarioGenerator
194 QuantLib::ext::shared_ptr<ScenarioGenerator> simMarketScenGen = simMarket->scenarioGenerator();
195 QuantLib::ext::shared_ptr<ShiftScenarioGenerator> scenarioGenerator =
196 QuantLib::ext::dynamic_pointer_cast<ShiftScenarioGenerator>(simMarketScenGen);
197
198 struct SimMarketResetter {
199 SimMarketResetter(QuantLib::ext::shared_ptr<SimMarket> simMarket) : simMarket_(simMarket) {}
200 ~SimMarketResetter() { simMarket_->reset(); }
201 QuantLib::ext::shared_ptr<SimMarket> simMarket_;
202 } simMarketResetter(simMarket);
203
204 simMarket->reset();
205 scenarioGenerator->reset();
206 simMarket->update(asof_);
207
208 if (!relevantRiskFactors_.empty())
213
214 map<RiskFactorKey, Real> parRatesBase, parCapVols; // for both ir and yoy caps
215
216 for (auto& p : instruments_.parHelpers_) {
217 try {
218 Real parRate = impliedQuote(p.second);
219 parRatesBase[p.first] = parRate;
220
221 // Populate zero and par shift size for the current risk factor
222 populateShiftSizes(p.first, parRate, simMarket);
223
224 } catch (const std::exception& e) {
225 QL_FAIL("could not imply quote for par helper " << p.first << ": " << e.what());
226 }
227 }
228
229 for (auto& c : instruments_.parCaps_) {
230
231 QL_REQUIRE(instruments_.parCapsYts_.count(c.first) > 0,
232 "computeParInstrumentSensitivities(): no cap yts found for key " << c.first);
233 QL_REQUIRE(instruments_.parCapsVts_.count(c.first) > 0,
234 "computeParInstrumentSensitivities(): no cap vts found for key " << c.first);
235
236 Real price = c.second->NPV();
238 *c.second, price, instruments_.parCapsYts_.at(c.first), 0.01,
239 instruments_.parCapsVts_.at(c.first)->volatilityType(), instruments_.parCapsVts_.at(c.first)->displacement());
240 parCapVols[c.first] = parVol;
241 TLOG("Fair implied cap volatility for key " << c.first << " is " << std::fixed << std::setprecision(12)
242 << parVol << ".");
243
244 // Populate zero and par shift size for the current risk factor
245 populateShiftSizes(c.first, parVol, simMarket);
246 }
247
248 for (auto& c : instruments_.parYoYCaps_) {
249
250 QL_REQUIRE(instruments_.parYoYCapsYts_.count(c.first) > 0,
251 "computeParInstrumentSensitivities(): no cap yts found for key " << c.first);
252 QL_REQUIRE(instruments_.parYoYCapsIndex_.count(c.first) > 0,
253 "computeParInstrumentSensitivities(): no cap index found for key " << c.first);
254 QL_REQUIRE(instruments_.parYoYCapsVts_.count(c.first) > 0,
255 "computeParInstrumentSensitivities(): no cap vts found for key " << c.first);
256
257 Real price = c.second->NPV();
259 *c.second, price, instruments_.parYoYCapsYts_.at(c.first), 0.01,
260 instruments_.parYoYCapsVts_.at(c.first)->volatilityType(),
261 instruments_.parYoYCapsVts_.at(c.first)->displacement(), instruments_.parYoYCapsIndex_.at(c.first));
262 parCapVols[c.first] = parVol;
263 TLOG("Fair implied yoy cap volatility for key " << c.first << " is " << std::fixed << std::setprecision(12)
264 << parVol << ".");
265
266 // Populate zero and par shift size for the current risk factor
267 populateShiftSizes(c.first, parVol, simMarket);
268 }
269
270 LOG("Caching base scenario par rates and float vols done.");
271
272 /****************************************************************
273 * Discount curve instrument fair rate sensitivity to zero shifts
274 * Index curve instrument fair rate sensitivity to zero shifts
275 * Cap/Floor flat vol sensitivity to optionlet vol shifts
276 *
277 * Step 3:
278 * - Apply all single up-shift scenarios,
279 * - Compute respective fair par rates and flat vols
280 * - Compute par rate / flat vol sensitivities
281 */
282 LOG("Compute par rate and flat vol sensitivities");
283
284 vector<ShiftScenarioGenerator::ScenarioDescription> desc = scenarioGenerator->scenarioDescriptions();
285 QL_REQUIRE(desc.size() == scenarioGenerator->samples(),
286 "descriptions size " << desc.size() << " does not match samples " << scenarioGenerator->samples());
287
288 std::set<RiskFactorKey> parKeysCheck, parKeysNonZero;
289 std::set<RiskFactorKey> rawKeysCheck, rawKeysNonZero;
290
291 for (auto const& p : instruments_.parHelpers_) {
292 parKeysCheck.insert(p.first);
293 }
294
295 for (auto const& p : instruments_.parCaps_) {
296 parKeysCheck.insert(p.first);
297 }
298
299 for (auto const& p : instruments_.parYoYCaps_) {
300 parKeysCheck.insert(p.first);
301 }
302
303 for (Size i = 1; i < scenarioGenerator->samples(); ++i) {
304
305 simMarket->update(asof_);
306
307 // use single "UP" shift scenarios only, use only scenarios relevant for par instruments,
308 // use relevant scenarios only, if specified
309 // ignore risk factor types that have been disabled
311 !isParType(desc[i].key1().keytype) || typesDisabled_.count(desc[i].key1().keytype) == 1 ||
312 !(relevantRiskFactors_.empty() || relevantRiskFactors_.find(desc[i].key1()) != relevantRiskFactors_.end()))
313 continue;
314
315 // Since we are not using ValuationEngine we need to manually perform the trade updates here
316 // TODO - explore means of utilising valuation engine
317 if (ObservationMode::instance().mode() == ObservationMode::Mode::Disable) {
318 for (auto it : instruments_.parHelpers_)
319 it.second->deepUpdate();
320 for (auto it : instruments_.parCaps_)
321 it.second->deepUpdate();
322 for (auto it : instruments_.parYoYCaps_)
323 it.second->deepUpdate();
324 }
325
326 rawKeysCheck.insert(desc[i].key1());
327
328 // Get the absolute shift size and skip if close to zero
329
330 Real shiftSize = getShiftSize(desc[i].key1(), sensitivityData_, simMarket);
331
332 if (close_enough(shiftSize, 0.0)) {
333 ALOG("Shift size for " << desc[i].key1() << " is zero, skipping");
334 continue;
335 }
336
337 // process par helpers
338
339 std::set<RiskFactorKey::KeyType> survivalAndRateCurveTypes = {
342
343 for (auto const& p : instruments_.parHelpers_) {
344
345 // skip if par helper has no sensi to zero risk factor (except the special treatment below kicks in)
346
347 if (p.second->isCalculated() &&
348 (survivalAndRateCurveTypes.find(p.first.keytype) == survivalAndRateCurveTypes.end() ||
349 p.first != desc[i].key1())) {
350 continue;
351 }
352
353 // compute fair and base quotes
354
355 Real fair = impliedQuote(p.second);
356 auto base = parRatesBase.find(p.first);
357 QL_REQUIRE(base != parRatesBase.end(), "internal error: did not find parRatesBase[" << p.first << "]");
358
359 Real tmp = (fair - base->second) / shiftSize;
360
361 // special treatments for certain risk factors
362
363 // for curves with survival probabilities / discount factors going to zero quickly we might see a
364 // sensitivity that is close to zero, which we sanitise here in order to prevent the Jacobi matrix
365 // getting ill-conditioned or even singular
366
367 if (survivalAndRateCurveTypes.find(p.first.keytype) != survivalAndRateCurveTypes.end() &&
368 p.first == desc[i].key1() && std::abs(tmp) < 0.01) {
369 WLOG("Setting Diagonal Sensi " << p.first << " w.r.t. " << desc[i].key1() << " to 0.01 (got " << tmp
370 << ")");
371 tmp = 0.01;
372 }
373
374 // YoY diagnoal entries are 1.0
375
376 if (p.first.keytype == RiskFactorKey::KeyType::YoYInflationCurve && p.first == desc[i].key1() &&
377 close_enough(tmp, 0.0)) {
378 tmp = 1.0;
379 }
380
381 // write sensitivity
382
383 writeSensitivity(p.first, desc[i].key1(), tmp, parSensi_, parKeysNonZero, rawKeysNonZero);
384 }
385
386 // process par caps
387
388 for (auto const& p : instruments_.parCaps_) {
389
390 if (p.second->isCalculated() && p.first != desc[i].key1())
391 continue;
392
393 auto fair = impliedVolatility(p.first, instruments_);
394 auto base = parCapVols.find(p.first);
395 QL_REQUIRE(base != parCapVols.end(), "internal error: did not find parCapVols[" << p.first << "]");
396
397 Real tmp = (fair - base->second) / shiftSize;
398
399 // ensure Jacobi matrix is regular and not (too) ill-conditioned, this is necessary because
400 // a) the shift size used to compute dpar / dzero might be close to zero and / or
401 // b) the implied vol calculation has numerical inaccuracies
402
403 if (p.first == desc[i].key1() && std::abs(tmp) < 0.01) {
404 WLOG("Setting Diagonal CapFloorVol Sensi " << p.first << " w.r.t. " << desc[i].key1()
405 << " to 0.01 (got " << tmp << ")");
406 tmp = 0.01;
407 }
408
409 // write sensitivity
410
411 writeSensitivity(p.first, desc[i].key1(), tmp, parSensi_, parKeysNonZero, rawKeysNonZero);
412 }
413
414 // process par yoy caps
415
416 for (auto const& p : instruments_.parYoYCaps_) {
417
418 if (p.second->isCalculated() && p.first != desc[i].key1())
419 continue;
420
421 auto fair = impliedVolatility(p.first, instruments_);
422 auto base = parCapVols.find(p.first);
423 QL_REQUIRE(base != parCapVols.end(), "internal error: did not find parCapVols[" << p.first << "]");
424
425 Real tmp = (fair - base->second) / shiftSize;
426
427 // ensure Jacobi matrix is regular and not (too) ill-conditioned, this is necessary because
428 // a) the shift size used to compute dpar / dzero might be close to zero and / or
429 // b) the implied vol calculation has numerical inaccuracies
430
431 if (p.first == desc[i].key1() && std::abs(tmp) < 0.01) {
432 WLOG("Setting Diagonal CapFloorVol Sensi " << p.first << " w.r.t. " << desc[i].key1()
433 << " to 0.01 (got " << tmp << ")");
434 tmp = 0.01;
435 }
436
437 // write sensitivity
438
439 writeSensitivity(p.first, desc[i].key1(), tmp, parSensi_, parKeysNonZero, rawKeysNonZero);
440 }
441
442 } // end of loop over samples
443
444 // check for
445 // a) par instruments which have no sensitivity to any of the risk factors
446 // b) risk factors w.r.t. which no par instrument has a sensitivity
447 std::set<RiskFactorKey> parKeysZero, rawKeysZero;
448 std::set_difference(parKeysCheck.begin(), parKeysCheck.end(), parKeysNonZero.begin(), parKeysNonZero.end(),
449 std::inserter(parKeysZero, parKeysZero.begin()));
450 std::set_difference(rawKeysCheck.begin(), rawKeysCheck.end(), rawKeysNonZero.begin(), rawKeysNonZero.end(),
451 std::inserter(rawKeysZero, rawKeysZero.begin()));
452 std::set<RiskFactorKey> problematicKeys;
453 problematicKeys.insert(parKeysZero.begin(), parKeysZero.end());
454 problematicKeys.insert(rawKeysZero.begin(), rawKeysZero.end());
455 for (auto const& k : problematicKeys) {
456 std::string type;
457 if (parKeysZero.find(k) != parKeysZero.end())
458 type = "par instrument is insensitive to all zero risk factors";
459 else if (rawKeysZero.find(k) != rawKeysZero.end())
460 type = "zero risk factor that does not affect an par instrument";
461 else
462 type = "unknown";
463 Real parHelperValue = Null<Real>();
464 if (auto tmp = instruments_.parHelpers_.find(k); tmp != instruments_.parHelpers_.end())
465 parHelperValue = impliedQuote(tmp->second);
466 else if (auto tmp = instruments_.parCaps_.find(k); tmp != instruments_.parCaps_.end())
467 parHelperValue = tmp->second->NPV();
468 else if (auto tmp = instruments_.parYoYCaps_.find(k); tmp != instruments_.parYoYCaps_.end())
469 parHelperValue = tmp->second->NPV();
470 Real zeroFactorValue = Null<Real>();
471 if (simMarket->baseScenarioAbsolute()->has(k))
472 zeroFactorValue = simMarket->baseScenarioAbsolute()->get(k);
473 WLOG("zero/par relation problem for key '"
474 << k << "', type " + type + ", par value = "
475 << (parHelperValue == Null<Real>() ? "na" : std::to_string(parHelperValue))
476 << ", zero value = " << (zeroFactorValue == Null<Real>() ? "na" : std::to_string(zeroFactorValue)));
477 }
478
479 LOG("Computing par rate and flat vol sensitivities done");
480} // compute par instrument sensis
ParContainer parSensi_
sensitivity of par rates w.r.t. raw rate shifts (including optionlet/cap volatility)
void augmentRelevantRiskFactors()
Augment relevant risk factors.
static bool isParType(ore::analytics::RiskFactorKey::KeyType type)
Returns true if risk factor type is applicable for par conversion.
void populateShiftSizes(const ore::analytics::RiskFactorKey &key, QuantLib::Real parRate, const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket)
Populate shiftSizes_ for key given the implied fair par rate parRate.
#define LOG(text)
#define DLOG(text)
#define ALOG(text)
#define WLOG(text)
#define TLOG(text)
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Volatility impliedVolatility(const QuantLib::CapFloor &cap, Real targetValue, const Handle< YieldTermStructure > &d, Volatility guess, VolatilityType type, Real displacement)
Real getShiftSize(const RiskFactorKey &key, const SensitivityScenarioData &sensiParams, const QuantLib::ext::shared_ptr< ScenarioSimMarket > &simMarket, const string &marketConfiguration)
Real impliedQuote(const QuantLib::ext::shared_ptr< Instrument > &i)
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantExt::YoYOptionletVolatilitySurface > > parYoYCapsVts_
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::YieldTermStructure > > parYoYCapsYts_
par helpers: YoY cap / floors
std::map< ore::analytics::RiskFactorKey, QuantLib::ext::shared_ptr< QuantLib::Instrument > > parHelpers_
par helpers (all except cap/floors)
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::YieldTermStructure > > parCapsYts_
std::map< ore::analytics::RiskFactorKey, QuantLib::ext::shared_ptr< QuantLib::CapFloor > > parCaps_
par helpers: IR cap / floors
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::OptionletVolatilityStructure > > parCapsVts_
std::map< ore::analytics::RiskFactorKey, QuantLib::ext::shared_ptr< QuantLib::YoYInflationCapFloor > > parYoYCaps_
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantLib::YoYInflationIndex > > parYoYCapsIndex_
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ parSensitivities()

const ParContainer & parSensitivities ( ) const

Return computed par sensitivities. Empty if they have not been computed yet.

Definition at line 75 of file parsensitivityanalysis.hpp.

75{ return parSensi_; }
+ Here is the caller graph for this function:

◆ alignPillars()

void alignPillars ( )

align pillars in scenario simulation market parameters with those of the par instruments

Definition at line 482 of file parsensitivityanalysis.cpp.

482 {
483 LOG("Align simulation market pillars to actual latest relevant dates of par instruments");
484 // If any of the yield curve types are still active, align the pillars.
488 for (auto const& p : instruments_.yieldCurvePillars_) {
489 simMarketParams_->setYieldCurveTenors(p.first, p.second);
490 DLOG("yield curve tenors for " << p.first << " set (" << p.second.size() << ")");
491 for (auto const& t : p.second)
492 TLOG("set tenor " << t.length() << " " << t.units())
493 }
494 }
496 for (auto const& p : instruments_.capFloorPillars_) {
497 simMarketParams_->setCapFloorVolExpiries(p.first, p.second);
498 DLOG("cap floor expiries for " << p.first << " set (" << p.second.size() << ")");
499 for (auto const& t : p.second)
500 TLOG("set tenor " << t.length() << " " << t.units())
501 }
502 }
504 for (auto const& p : instruments_.yoyCapFloorPillars_) {
505 simMarketParams_->setYoYInflationCapFloorVolExpiries(p.first, p.second);
506 DLOG("yoy cap floor expiries for " << p.first << " set (" << p.second.size() << ")");
507 for (auto const& t : p.second)
508 TLOG("set tenor " << t.length() << " " << t.units())
509 }
510 }
512 for (auto const& p : instruments_.cdsPillars_) {
513 simMarketParams_->setDefaultTenors(p.first, p.second);
514 DLOG("default expiries for " << p.first << " set (" << p.second.size() << ")");
515 for (auto const& t : p.second)
516 TLOG("set tenor " << t.length() << " " << t.units())
517 }
518 }
520 for (auto const& p : instruments_.zeroInflationPillars_) {
521 simMarketParams_->setZeroInflationTenors(p.first, p.second);
522 DLOG("zero inflation expiries for " << p.first << " set (" << p.second.size() << ")");
523 for (auto const& t : p.second)
524 TLOG("set tenor " << t.length() << " " << t.units())
525 }
526 }
528 for (auto const& p : instruments_.yoyInflationPillars_) {
529 simMarketParams_->setYoyInflationTenors(p.first, p.second);
530 DLOG("yoy inflation expiries for " << p.first << " set (" << p.second.size() << ")");
531 for (auto const& t : p.second)
532 TLOG("set tenor " << t.length() << " " << t.units())
533 }
534 }
535 LOG("Alignment of pillars done.");
536}
std::map< std::string, std::vector< QuantLib::Period > > zeroInflationPillars_
std::map< std::string, std::vector< QuantLib::Period > > yieldCurvePillars_
par QuantLib::Instrument pillars
std::map< std::string, std::vector< QuantLib::Period > > yoyCapFloorPillars_
std::map< std::string, std::vector< QuantLib::Period > > capFloorPillars_
std::map< std::string, std::vector< QuantLib::Period > > cdsPillars_
std::map< std::string, std::vector< QuantLib::Period > > yoyInflationPillars_
+ Here is the caller graph for this function:

◆ isParType()

bool isParType ( ore::analytics::RiskFactorKey::KeyType  type)
static

Returns true if risk factor type is applicable for par conversion.

Definition at line 538 of file parsensitivityanalysis.cpp.

538{ return parTypes_.find(type) != parTypes_.end(); }
+ Here is the caller graph for this function:

◆ relevantRiskFactors() [1/2]

const std::set< ore::analytics::RiskFactorKey > & relevantRiskFactors ( ) const

get / set the relevant scenarios (if empty, these are ignored)

Definition at line 84 of file parsensitivityanalysis.hpp.

84{ return relevantRiskFactors_; }

◆ relevantRiskFactors() [2/2]

std::set< ore::analytics::RiskFactorKey > & relevantRiskFactors ( )

Definition at line 85 of file parsensitivityanalysis.hpp.

85{ return relevantRiskFactors_; }

◆ shiftSizes()

std::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > shiftSizes ( ) const

Return the zero rate and par rate absolute shift size for each risk factor key.

Definition at line 88 of file parsensitivityanalysis.hpp.

88 {
89 return shiftSizes_;
90 }
std::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > shiftSizes_
+ Here is the caller graph for this function:

◆ disable()

void disable ( const std::set< ore::analytics::RiskFactorKey::KeyType > &  types)

Disable par conversion for the given set of risk factor key types. May be called multiple times in order to add key types that should not be considered for par conversion.

Definition at line 540 of file parsensitivityanalysis.cpp.

540 {
541 // Insert only types that are available for par sensitivity analysis in to the set of disabled types.
542 for (const auto& type : types) {
543 if (isParType(type)) {
544 typesDisabled_.insert(type);
545 }
546 }
547}
boost::bimap< std::string, TRS::FundingData::NotionalType > types
+ Here is the call graph for this function:

◆ typesDisabled()

const std::set< ore::analytics::RiskFactorKey::KeyType > & typesDisabled ( ) const

Return the set of key types disabled for this instance of ParSensitivityAnalysis.

Definition at line 98 of file parsensitivityanalysis.hpp.

98{ return typesDisabled_; }

◆ parInstruments()

const ParSensitivityInstrumentBuilder::Instruments & parInstruments ( ) const

Definition at line 100 of file parsensitivityanalysis.hpp.

100{ return instruments_; }

◆ augmentRelevantRiskFactors()

void augmentRelevantRiskFactors ( )
private

Augment relevant risk factors.

Definition at line 103 of file parsensitivityanalysis.cpp.

103 {
104 LOG("Augment relevant risk factors, starting with " << relevantRiskFactors_.size() << " risk factors.");
105 std::set<ore::analytics::RiskFactorKey> addFactors1 = relevantRiskFactors_, addFactors2, tmp;
106 do {
107 // DLOG("new pass with " << addFactors1.size() << " risk factors.");
108 for (auto const& r : addFactors1) {
109 // DLOG("candidate risk factor " << r);
110 for (auto const& s : instruments_.parHelpers_) {
111 if (riskFactorKeysAreSimilar(s.first, r)) {
112 tmp.insert(s.first);
113 // DLOG("factor " << r << ": found similar risk factor " << s.first);
114 for (auto const& d : instruments_.parHelperDependencies_[s.first]) {
115 if (std::find(relevantRiskFactors_.begin(), relevantRiskFactors_.end(), d) ==
117 addFactors2.insert(d);
118 }
119 }
120 }
121 for (auto const& s : instruments_.parCaps_) {
122 if (riskFactorKeysAreSimilar(s.first, r)) {
123 tmp.insert(s.first);
124 // DLOG("factor " << r << ": found similar risk factor " << s.first);
125 for (auto const& d : instruments_.parHelperDependencies_[s.first]) {
126 if (std::find(relevantRiskFactors_.begin(), relevantRiskFactors_.end(), d) ==
128 addFactors2.insert(d);
129 }
130 }
131 }
132 }
133 addFactors1.swap(addFactors2);
134 addFactors2.clear();
135 relevantRiskFactors_.insert(tmp.begin(), tmp.end());
136 tmp.clear();
137 } while (addFactors1.size() > 0);
138 LOG("Done, relevant risk factor size now " << relevantRiskFactors_.size());
139}
bool riskFactorKeysAreSimilar(const ore::analytics::RiskFactorKey &x, const ore::analytics::RiskFactorKey &y)
true if key type and name are equal, do not care about the index though
std::map< ore::analytics::RiskFactorKey, std::set< ore::analytics::RiskFactorKey > > parHelperDependencies_
list of (raw) risk factors on which a par helper depends
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ populateShiftSizes()

void populateShiftSizes ( const ore::analytics::RiskFactorKey key,
QuantLib::Real  parRate,
const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &  simMarket 
)
private

Populate shiftSizes_ for key given the implied fair par rate parRate.

Definition at line 549 of file parsensitivityanalysis.cpp.

550 {
551
552 // Get zero and par shift size for the key
553 Real zeroShiftSize = getShiftSize(key, sensitivityData_, simMarket);
554 auto shiftData = sensitivityData_.shiftData(key.keytype, key.name);
555 Real parShiftSize = shiftData.shiftSize;
556 if (shiftData.shiftType == ShiftType::Relative)
557 parShiftSize *= parRate;
558
559 // Update the map
560 shiftSizes_[key] = make_pair(zeroShiftSize, parShiftSize);
561
562 TLOG("Zero and par shift size for risk factor '" << key << "' is (" << std::fixed << std::setprecision(12)
563 << zeroShiftSize << "," << parShiftSize << ")");
564}
KeyType keytype
Key type.
Definition: scenario.hpp:89
std::string name
Key name.
Definition: scenario.hpp:94
const ShiftData & shiftData(const ore::analytics::RiskFactorKey::KeyType &keyType, const std::string &name) const
Give back the shift data for the given risk factor type, keyType, with the given name.
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Member Data Documentation

◆ asof_

QuantLib::Date asof_
private

As of date for the calculation of the par sensitivities.

Definition at line 111 of file parsensitivityanalysis.hpp.

◆ simMarketParams_

QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarketParameters> simMarketParams_
private

Simulation market parameters.

Definition at line 113 of file parsensitivityanalysis.hpp.

◆ sensitivityData_

ore::analytics::SensitivityScenarioData sensitivityData_
private

Sensitivity data.

Definition at line 115 of file parsensitivityanalysis.hpp.

◆ parSensi_

ParContainer parSensi_
private

sensitivity of par rates w.r.t. raw rate shifts (including optionlet/cap volatility)

Definition at line 117 of file parsensitivityanalysis.hpp.

◆ instruments_

Definition at line 118 of file parsensitivityanalysis.hpp.

◆ marketConfiguration_

std::string marketConfiguration_
private

Definition at line 120 of file parsensitivityanalysis.hpp.

◆ continueOnError_

bool continueOnError_
private

Definition at line 121 of file parsensitivityanalysis.hpp.

◆ relevantRiskFactors_

std::set<ore::analytics::RiskFactorKey> relevantRiskFactors_
private

Definition at line 122 of file parsensitivityanalysis.hpp.

◆ parTypes_

set< RiskFactorKey::KeyType > parTypes_
staticprivate

◆ typesDisabled_

std::set<ore::analytics::RiskFactorKey::KeyType> typesDisabled_
private

Set of risk factor types disabled for this instance of ParSensitivityAnalysis.

Definition at line 127 of file parsensitivityanalysis.hpp.

◆ shiftSizes_

std::map<ore::analytics::RiskFactorKey, std::pair<QuantLib::Real, QuantLib::Real> > shiftSizes_
private

Store the zero rate and par rate absolute shift size for each risk factor key

The first element in the pair is the zero or raw rate absolute shift size. The second element in the pair is the corresponding par rate absolute shift size.

In the case of the zero rate shift being configured as Absolute in sensitivityData_, then the par rate absolute shift size is just equal to the configured zero rate shift size. In the case of the zero rate shift being configured as Relative in sensitivityData_, we take the fair implied par rate and multiply it by the configured relative zero rate shift size to give the par rate absolute shift size.

Definition at line 139 of file parsensitivityanalysis.hpp.