50#include <ql/cashflows/capflooredinflationcoupon.hpp>
51#include <ql/cashflows/indexedcashflow.hpp>
52#include <ql/cashflows/overnightindexedcoupon.hpp>
53#include <ql/errors.hpp>
54#include <ql/indexes/ibor/libor.hpp>
55#include <ql/instruments/creditdefaultswap.hpp>
56#include <ql/instruments/forwardrateagreement.hpp>
57#include <ql/instruments/makecapfloor.hpp>
58#include <ql/instruments/makeois.hpp>
59#include <ql/instruments/makevanillaswap.hpp>
60#include <ql/instruments/yearonyearinflationswap.hpp>
61#include <ql/instruments/zerocouponinflationswap.hpp>
62#include <ql/math/solvers1d/newtonsafe.hpp>
63#include <ql/pricingengines/capfloor/bacheliercapfloorengine.hpp>
64#include <ql/pricingengines/capfloor/blackcapfloorengine.hpp>
65#include <ql/pricingengines/credit/midpointcdsengine.hpp>
66#include <ql/pricingengines/swap/discountingswapengine.hpp>
67#include <ql/quotes/derivedquote.hpp>
68#include <ql/termstructures/yield/flatforward.hpp>
69#include <ql/termstructures/yield/oisratehelper.hpp>
72#include <boost/lexical_cast.hpp>
73#include <boost/numeric/ublas/operation.hpp>
74#include <boost/numeric/ublas/vector.hpp>
82using boost::numeric::ublas::element_div;
83using boost::numeric::ublas::element_prod;
90 const QuantLib::ext::shared_ptr<ScenarioSimMarketParameters>& simMarketParams,
92 const string& marketConfiguration,
const bool continueOnError,
93 const set<RiskFactorKey::KeyType>& typesDisabled)
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");
108 for (
auto const& r : addFactors1) {
117 addFactors2.insert(d);
128 addFactors2.insert(d);
133 addFactors1.swap(addFactors2);
137 }
while (addFactors1.size() > 0);
143 std::map<std::pair<RiskFactorKey, RiskFactorKey>, Real>& parSensi,
144 std::set<RiskFactorKey>& parKeysNonZero, std::set<RiskFactorKey>& rawKeysNonZero) {
147 parKeysNonZero.insert(a);
148 rawKeysNonZero.insert(b);
149 parSensi[std::make_pair(a, b)] =
value;
150 DLOG(
"ParInstrument Sensi " << a <<
" w.r.t. " << b <<
" " << setprecision(6) << value);
156 LOG(
"Cache base scenario par rates and flat vols");
159 DLOG(
"Relevant risk factors not provided");
161 DLOG(
"Relevant risk factors provided:");
163 DLOG(
"Relevant risk factor " << rf);
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);
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);
189 std::set<std::pair<std::string, Real>> savedFixings_;
194 QuantLib::ext::shared_ptr<ScenarioGenerator> simMarketScenGen = simMarket->scenarioGenerator();
195 QuantLib::ext::shared_ptr<ShiftScenarioGenerator> scenarioGenerator =
196 QuantLib::ext::dynamic_pointer_cast<ShiftScenarioGenerator>(simMarketScenGen);
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);
205 scenarioGenerator->reset();
206 simMarket->update(
asof_);
214 map<RiskFactorKey, Real> parRatesBase, parCapVols;
219 parRatesBase[p.first] = parRate;
224 }
catch (
const std::exception& e) {
225 QL_FAIL(
"could not imply quote for par helper " << p.first <<
": " << e.what());
232 "computeParInstrumentSensitivities(): no cap yts found for key " << c.first);
234 "computeParInstrumentSensitivities(): no cap vts found for key " << c.first);
236 Real price = c.second->NPV();
240 parCapVols[c.first] = parVol;
241 TLOG(
"Fair implied cap volatility for key " << c.first <<
" is " << std::fixed << std::setprecision(12)
251 "computeParInstrumentSensitivities(): no cap yts found for key " << c.first);
253 "computeParInstrumentSensitivities(): no cap index found for key " << c.first);
255 "computeParInstrumentSensitivities(): no cap vts found for key " << c.first);
257 Real price = c.second->NPV();
262 parCapVols[c.first] = parVol;
263 TLOG(
"Fair implied yoy cap volatility for key " << c.first <<
" is " << std::fixed << std::setprecision(12)
270 LOG(
"Caching base scenario par rates and float vols done.");
282 LOG(
"Compute par rate and flat vol sensitivities");
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());
288 std::set<RiskFactorKey> parKeysCheck, parKeysNonZero;
289 std::set<RiskFactorKey> rawKeysCheck, rawKeysNonZero;
292 parKeysCheck.insert(p.first);
296 parKeysCheck.insert(p.first);
300 parKeysCheck.insert(p.first);
303 for (Size i = 1; i < scenarioGenerator->samples(); ++i) {
305 simMarket->update(
asof_);
319 it.second->deepUpdate();
321 it.second->deepUpdate();
323 it.second->deepUpdate();
326 rawKeysCheck.insert(desc[i].key1());
333 ALOG(
"Shift size for " << desc[i].key1() <<
" is zero, skipping");
339 std::set<RiskFactorKey::KeyType> survivalAndRateCurveTypes = {
347 if (p.second->isCalculated() &&
348 (survivalAndRateCurveTypes.find(p.first.keytype) == survivalAndRateCurveTypes.end() ||
349 p.first != desc[i].key1())) {
356 auto base = parRatesBase.find(p.first);
357 QL_REQUIRE(base != parRatesBase.end(),
"internal error: did not find parRatesBase[" << p.first <<
"]");
359 Real tmp = (fair - base->second) / shiftSize;
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
383 writeSensitivity(p.first, desc[i].key1(), tmp,
parSensi_, parKeysNonZero, rawKeysNonZero);
390 if (p.second->isCalculated() && p.first != desc[i].key1())
394 auto base = parCapVols.find(p.first);
395 QL_REQUIRE(base != parCapVols.end(),
"internal error: did not find parCapVols[" << p.first <<
"]");
397 Real tmp = (fair - base->second) / shiftSize;
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 <<
")");
411 writeSensitivity(p.first, desc[i].key1(), tmp,
parSensi_, parKeysNonZero, rawKeysNonZero);
418 if (p.second->isCalculated() && p.first != desc[i].key1())
422 auto base = parCapVols.find(p.first);
423 QL_REQUIRE(base != parCapVols.end(),
"internal error: did not find parCapVols[" << p.first <<
"]");
425 Real tmp = (fair - base->second) / shiftSize;
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 <<
")");
439 writeSensitivity(p.first, desc[i].key1(), tmp,
parSensi_, parKeysNonZero, rawKeysNonZero);
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) {
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";
463 Real parHelperValue = Null<Real>();
467 parHelperValue = tmp->second->NPV();
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)));
479 LOG(
"Computing par rate and flat vol sensitivities done");
483 LOG(
"Align simulation market pillars to actual latest relevant dates of par instruments");
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())
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())
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())
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())
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())
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())
535 LOG(
"Alignment of pillars done.");
542 for (
const auto& type :
types) {
550 const QuantLib::ext::shared_ptr<ScenarioSimMarket>& simMarket) {
557 parShiftSize *= parRate;
560 shiftSizes_[key] = make_pair(zeroShiftSize, parShiftSize);
562 TLOG(
"Zero and par shift size for risk factor '" << key <<
"' is (" << std::fixed << std::setprecision(12)
563 << zeroShiftSize <<
"," << parShiftSize <<
")");
576 for (
auto parEntry : parSensitivities) {
577 parKeys_.insert(parEntry.first.first);
578 rawKeys_.insert(parEntry.first.second);
583 SparseMatrix jacobi_transp(n_raw, n_par);
584 LOG(
"Transposed Jacobi matrix dimension " << n_raw <<
" x " << n_par);
586 std::set<RiskFactorKey> parMinusRaw, rawMinusPar;
588 std::inserter(parMinusRaw, parMinusRaw.begin()));
590 std::inserter(rawMinusPar, rawMinusPar.begin()));
591 for (
auto const& p : parMinusRaw) {
592 ALOG(
"par key '" << p <<
"' not in raw key set");
594 for (
auto const& p : rawMinusPar) {
595 ALOG(
"raw key '" << p <<
"' not in par key set");
597 QL_FAIL(
"Zero and par keys should be equal for par conversion, see log for differences");
599 QL_REQUIRE(n_raw > 0,
"Transposed Jacobi matrix has size 0");
601 LOG(
"Populating the vector of zero and par shift sizes");
606 QL_REQUIRE(shiftSizes.count(key) == 1,
"ParSensitivityConverter is missing shift sizes for key " << key);
609 zeroShifts_[i] = std::max(shiftSizes.at(key).first, 1E-10);
614 LOG(
"Populating Transposed Jacobi matrix");
615 for (
auto const& p : parSensitivities) {
616 Size parIdx = std::distance(
parKeys_.begin(),
parKeys_.find(p.first.first));
617 Size rawIdx = std::distance(
rawKeys_.begin(),
rawKeys_.find(p.first.second));
618 QL_REQUIRE(parIdx < n_par,
"internal error: parKey " << p.first.first <<
" not found in parKeys_");
619 QL_REQUIRE(rawIdx < n_raw,
"internal error: rawKey " << p.first.second <<
" not found in parKeys_");
620 jacobi_transp(rawIdx, parIdx) = p.second;
621 TLOG(
"Matrix entry [" << rawIdx <<
", " << parIdx <<
"] ~ [raw:" << p.first.second <<
", par:" << p.first.first
622 <<
"]: " << p.second);
624 LOG(
"Finished populating transposed Jacobi matrix, non-zero entries = "
625 << parSensitivities.size() <<
" ("
626 << 100.0 *
static_cast<Real
>(parSensitivities.size()) /
static_cast<Real
>(n_par * n_raw) <<
"%)");
628 LOG(
"Populating block indices");
629 vector<Size> blockIndices;
635 pair<RiskFactorKey::KeyType, string> thisGroup(r.keytype, r.name);
636 if (blockIndex > 0 && previousGroup != thisGroup) {
637 blockIndices.push_back(blockIndex);
638 TLOG(
"Adding block index " << blockIndex);
643 previousGroup = thisGroup;
645 blockIndices.push_back(blockIndex);
646 TLOG(
"Adding block index " << blockIndex);
647 LOG(
"Finished Populating block indices.");
649 LOG(
"Invert Transposed Jacobi matrix");
653 }
catch (
const std::exception& e) {
659 LOG(
"Running extended matrix diagnostics (looking for zero or linearly dependent rows / columns...)");
660 constexpr Size nOp = 1000;
661 LOG(
"Checking for zero rows...");
662 for (
auto it1 = jacobi_transp.begin1(); it1 != jacobi_transp.end1(); ++it1) {
664 for (
auto it2 = it1.begin(); it2 != it1.end(); ++it2) {
665 tmp += (*it2) * (*it2);
668 WLOG(
"row " << it1.index1() <<
" is zero");
671 LOG(
"Checking for zero columns...");
672 for (
auto it2 = jacobi_transp.begin2(); it2 != jacobi_transp.end2(); ++it2) {
674 for (
auto it1 = it2.begin(); it1 != it2.end(); ++it1) {
675 tmp += (*it1) * (*it1);
678 WLOG(
"column " << it2.index2() <<
" is zero");
681 LOG(
"Checking for linearly dependent rows...");
682 for (
auto it1 = jacobi_transp.begin1(); it1 != jacobi_transp.end1(); ++it1) {
683 for (
auto it1b = jacobi_transp.begin1(); it1b != jacobi_transp.end1(); ++it1b) {
684 if (it1b.index1() <= it1.index1())
686 Real ratio = Null<Real>();
687 if (it1.begin() != it1.end() && it1b.begin() != it1b.end()) {
688 bool dependent =
true;
689 auto it2b = it1b.begin();
690 for (
auto it2 = it1.begin(); it2 != it1.end() && dependent; ++it2) {
693 bool foundMatchingIndex =
false;
694 while (it2b != it1b.end() && it2b.index2() <= it2.index2() && dependent) {
695 if (it2b.index2() < it2.index2()) {
699 foundMatchingIndex =
true;
702 }
else if (ratio == Null<Real>()) {
703 ratio = *it2b / *it2;
710 if (!foundMatchingIndex)
713 while (it2b != it1b.end() && dependent) {
719 WLOG(
"rows " << it1.index1() <<
" and " << it1b.index1() <<
" are linearly dependent.");
724 LOG(
"Checking for linearly dependent columns...");
725 for (
auto it1 = jacobi_transp.begin2(); it1 != jacobi_transp.end2(); ++it1) {
726 for (
auto it1b = jacobi_transp.begin2(); it1b != jacobi_transp.end2(); ++it1b) {
727 if (it1b.index2() <= it1.index2())
729 Real ratio = Null<Real>();
730 if (it1.begin() != it1.end() && it1b.begin() != it1b.end()) {
731 bool dependent =
true;
732 auto it2b = it1b.begin();
733 for (
auto it2 = it1.begin(); it2 != it1.end() && dependent; ++it2) {
736 bool foundMatchingIndex =
false;
737 while (it2b != it1b.end() && it2b.index1() <= it2.index1() && dependent) {
738 if (it2b.index1() < it2.index1()) {
742 foundMatchingIndex =
true;
745 }
else if (ratio == Null<Real>()) {
746 ratio = *it2b / *it2;
753 if (!foundMatchingIndex)
756 while (it2b != it1b.end() && dependent) {
762 WLOG(
"columns " << it1.index2() <<
" and " << it1b.index2() <<
" are linearly dependent.");
767 LOG(
"Extended matrix diagnostics done. Exiting application.");
770 QL_REQUIRE(success,
"Jacobi matrix inversion failed, see log file for more details.");
772 LOG(
"Inverse Jacobi done, condition number of Jacobi matrix is " << conditionNumber);
773 DLOG(
"Diagonal entries of Jacobi and inverse Jacobi:");
774 DLOG(
"row/col Jacobi Inverse");
775 for (Size j = 0; j < jacobi_transp.size1(); ++j) {
780boost::numeric::ublas::vector<Real>
783 DLOG(
"Start sensitivity conversion");
785 Size dim = zeroSensitivities.size();
786 QL_REQUIRE(
jacobi_transp_inv_.size1() == dim,
"Size mismatch between Transoposed Jacobi inverse matrix ["
792 boost::numeric::ublas::vector<Real> zeroDerivs(dim);
793 zeroDerivs = element_div(zeroSensitivities,
zeroShifts_);
796 boost::numeric::ublas::vector<Real> parSensitivities(dim);
797 boost::numeric::ublas::axpy_prod(
jacobi_transp_inv_, zeroDerivs, parSensitivities,
true);
801 parSensitivities = element_prod(parSensitivities,
parShifts_);
803 DLOG(
"Sensitivity conversion done");
805 return parSensitivities;
811 report.
addColumn(
"RawFactor(z)",
string());
812 report.
addColumn(
"ParFactor(c)",
string());
817 for (
const auto& parKey :
parKeys_) {
819 for (
const auto& rawKey :
rawKeys_) {
840 report.
addColumn(
"ParSensitivity",
double(), 12);
843 for (
const auto& parSensitivity : parSensitivities) {
846 Real sensi = parSensitivity.second;
std::string marketConfiguration_
ore::analytics::SensitivityScenarioData sensitivityData_
Sensitivity data.
void disable(const std::set< ore::analytics::RiskFactorKey::KeyType > &types)
std::set< ore::analytics::RiskFactorKey::KeyType > typesDisabled_
Set of risk factor types disabled for this instance of ParSensitivityAnalysis.
void alignPillars()
align pillars in scenario simulation market parameters with those of the par instruments
ParContainer parSensi_
sensitivity of par rates w.r.t. raw rate shifts (including optionlet/cap volatility)
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::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > shiftSizes_
std::set< ore::analytics::RiskFactorKey > relevantRiskFactors_
ParSensitivityInstrumentBuilder::Instruments instruments_
void augmentRelevantRiskFactors()
Augment relevant risk factors.
void computeParInstrumentSensitivities(const QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarket > &simMarket)
Compute par instrument sensitivities.
std::map< std::pair< ore::analytics::RiskFactorKey, ore::analytics::RiskFactorKey >, Real > ParContainer
static bool isParType(ore::analytics::RiskFactorKey::KeyType type)
Returns true if risk factor type is applicable for par conversion.
static std::set< ore::analytics::RiskFactorKey::KeyType > parTypes_
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.
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.
void writeConversionMatrix(ore::data::Report &reportOut) const
Write the inverse of the transposed Jacobian to the reportOut.
std::set< ore::analytics::RiskFactorKey > parKeys_
boost::numeric::ublas::vector< Real > convertSensitivity(const boost::numeric::ublas::vector< Real > &zeroSensitivities)
Takes an array of zero sensitivities and returns an array of par sensitivities.
std::set< ore::analytics::RiskFactorKey > rawKeys_
boost::numeric::ublas::vector< QuantLib::Real > zeroShifts_
Vector of absolute zero shift sizes.
ParSensitivityConverter(const ParSensitivityAnalysis::ParContainer &parSensitivities, const std::map< ore::analytics::RiskFactorKey, std::pair< QuantLib::Real, QuantLib::Real > > &shiftSizes)
boost::numeric::ublas::vector< QuantLib::Real > parShifts_
Vector of absolute par shift sizes.
QuantLib::SparseMatrix jacobi_transp_inv_
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.
Data types stored in the scenario class.
std::string name
Key name.
KeyType
Risk Factor types.
@ YoYInflationCapFloorVolatility
Description of sensitivity shift scenarios.
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.
virtual Report & add(const ReportType &rt)=0
virtual Report & next()=0
virtual Report & addColumn(const string &name, const ReportType &, Size precision=0)=0
SafeStack< ValueType > value
A cube implementation that stores the cube in memory.
Filter close_enough(const RandomVariable &x, const RandomVariable &y)
Real modifiedMaxNorm(const QuantLib::SparseMatrix &A)
Matrix blockMatrixInverse(const Matrix &A, const std::vector< Size > &blockIndices)
Volatility impliedVolatility(const QuantLib::CapFloor &cap, Real targetValue, const Handle< YieldTermStructure > &d, Volatility guess, VolatilityType type, Real displacement)
bool close(const Real &t_1, const Real &t_2)
void writeParConversionMatrix(const ParSensitivityAnalysis::ParContainer &parSensitivities, Report &report)
Write par instrument sensitivity report.
Real getShiftSize(const RiskFactorKey &key, const SensitivityScenarioData &sensiParams, const QuantLib::ext::shared_ptr< ScenarioSimMarket > &simMarket, const string &marketConfiguration)
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
Real impliedQuote(const QuantLib::ext::shared_ptr< Instrument > &i)
std::string to_string(const LocationInfo &l)
boost::bimap< std::string, TRS::FundingData::NotionalType > types
Singleton class to hold global Observation Mode.
Perfrom sensitivity analysis for a given portfolio.
A class to hold the parametrisation for building sensitivity scenarios.
factory classes for simple scenarios
std::map< ore::analytics::RiskFactorKey, QuantLib::Handle< QuantExt::YoYOptionletVolatilitySurface > > parYoYCapsVts_
std::map< std::string, std::vector< QuantLib::Period > > zeroInflationPillars_
std::set< std::string > removeTodaysFixingIndices_
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, std::set< ore::analytics::RiskFactorKey > > parHelperDependencies_
list of (raw) risk factors on which a par helper depends
std::map< std::string, std::vector< QuantLib::Period > > yieldCurvePillars_
par QuantLib::Instrument pillars
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_
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_
Structured analytics error.