Logo
Fully annotated reference manual - version 1.8.12
Loading...
Searching...
No Matches
parsensitivityanalysis.hpp
Go to the documentation of this file.
1/*
2 Copyright (C) 2017 Quaternion Risk Management Ltd
3 All rights reserved.
4
5 This file is part of ORE, a free-software/open-source library
6 for transparent pricing and risk analysis - http://opensourcerisk.org
7
8 ORE is free software: you can redistribute it and/or modify it
9 under the terms of the Modified BSD License. You should have received a
10 copy of the license along with this program.
11 The license is also available online at <http://opensourcerisk.org>
12
13 This program is distributed on the basis that it will form a useful
14 contribution to risk analytics and model standardisation, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the license for more details.
17*/
18
19/*! \file orea/engine/parsensitivityanalysis.hpp
20 \brief Perfrom sensitivity analysis for a given portfolio
21 \ingroup simulation
22*/
23
24#pragma once
25
26#include <orea/cube/npvcube.hpp>
36
37#include <ql/instruments/inflationcapfloor.hpp>
38#include <ql/math/matrixutilities/sparsematrix.hpp>
39
40#include <boost/numeric/ublas/vector.hpp>
41
42#include <map>
43#include <set>
44#include <tuple>
45
46namespace ore {
47namespace analytics {
48using namespace std;
49using namespace QuantLib;
50using namespace ore::data;
51
52//! Par Sensitivity Analysis
53/*!
54 This class adds par sensitivity conversion to the base class functionality
55 \ingroup simulation
56*/
58public:
59 typedef std::map<std::pair<ore::analytics::RiskFactorKey, ore::analytics::RiskFactorKey>, Real> ParContainer;
60
61 //! Constructor
62 ParSensitivityAnalysis(const QuantLib::Date& asof,
63 const QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarketParameters>& simMarketParams,
64 const ore::analytics::SensitivityScenarioData& sensitivityData,
65 const string& marketConfiguration = Market::defaultConfiguration,
66 const bool continueOnError = false,
67 const std::set<ore::analytics::RiskFactorKey::KeyType>& typesDisabled = {});
68
70
71 //! Compute par instrument sensitivities
72 void computeParInstrumentSensitivities(const QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket);
73
74 //! Return computed par sensitivities. Empty if they have not been computed yet.
75 const ParContainer& parSensitivities() const { return parSensi_; }
76
77 //! align pillars in scenario simulation market parameters with those of the par instruments
78 void alignPillars();
79
80 //! Returns true if risk factor type is applicable for par conversion
82
83 //! get / set the relevant scenarios (if empty, these are ignored)
84 const std::set<ore::analytics::RiskFactorKey>& relevantRiskFactors() const { return relevantRiskFactors_; }
85 std::set<ore::analytics::RiskFactorKey>& relevantRiskFactors() { return relevantRiskFactors_; }
86
87 //! Return the zero rate and par rate absolute shift size for each risk factor key
88 std::map<ore::analytics::RiskFactorKey, std::pair<QuantLib::Real, QuantLib::Real>> shiftSizes() const {
89 return shiftSizes_;
90 }
91
92 /*! Disable par conversion for the given set of risk factor key types. May be called multiple times in order to
93 add key types that should not be considered for par conversion.
94 */
95 void disable(const std::set<ore::analytics::RiskFactorKey::KeyType>& types);
96
97 //! Return the set of key types disabled for this instance of ParSensitivityAnalysis.
98 const std::set<ore::analytics::RiskFactorKey::KeyType>& typesDisabled() const { return typesDisabled_; }
99
101
102private:
103 //! Augment relevant risk factors
105
106 //! Populate `shiftSizes_` for \p key given the implied fair par rate \p parRate
107 void populateShiftSizes(const ore::analytics::RiskFactorKey& key, QuantLib::Real parRate,
108 const QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarket>& simMarket);
109
110 //! As of date for the calculation of the par sensitivities
111 QuantLib::Date asof_;
112 //! Simulation market parameters
113 QuantLib::ext::shared_ptr<ore::analytics::ScenarioSimMarketParameters> simMarketParams_;
114 //! Sensitivity data
116 //! sensitivity of par rates w.r.t. raw rate shifts (including optionlet/cap volatility)
119
122 std::set<ore::analytics::RiskFactorKey> relevantRiskFactors_;
123
124 static std::set<ore::analytics::RiskFactorKey::KeyType> parTypes_;
125
126 //! Set of risk factor types disabled for this instance of ParSensitivityAnalysis.
127 std::set<ore::analytics::RiskFactorKey::KeyType> typesDisabled_;
128
129 /*! Store the zero rate and par rate absolute shift size for each risk factor key
130
131 The first element in the pair is the zero or raw rate absolute shift size. The second element in the pair is
132 the corresponding par rate absolute shift size.
133
134 In the case of the zero rate shift being configured as `Absolute` in `sensitivityData_`, then the par rate
135 absolute shift size is just equal to the configured zero rate shift size. In the case of the zero rate
136 shift being configured as `Relative` in `sensitivityData_`, we take the fair implied par rate and multiply it
137 by the configured relative zero rate shift size to give the par rate absolute shift size.
138 */
139 std::map<ore::analytics::RiskFactorKey, std::pair<QuantLib::Real, QuantLib::Real>> shiftSizes_;
140};
141
142//! ParSensitivityConverter class
143/*!
144 1) Build Jacobi matrix containing sensitivities of par rates (first index) w.r.t. zero shifts (second index)
145 2) Convert zero rate and optionlet vol sensitivities into par rate/vol sensitivities
146
147 Let: p_ij denote curve i's par instrument j (curve may be a discount or an index curve)
148 z_kl denote curve k's zero shift l (curve may be a discount or an index curve)
149 i,k run from 0 to I
150 j,l run from 0 to J
151
152 Organisation of the matrix:
153 z_00 z_01 z_02 ... z_0J ... z_10 z_11 ... z_1J ... z_I0 z_I1 ... z_IJ
154 p_00
155 p_01
156 p_02
157 ...
158 p_0J
159 p_10
160 p_11
161 ...
162 p_1J
163 ...
164 p_I0
165 p_I1
166 ...
167 p_IJ
168
169 The curve numbering starts with discount curves (by ccy), followed by index curves (by index name).
170 The number J of par instruments respectively zero shifts can differ between discount and index curves.
171 The number of zero shifts matches the number of par instruments.
172 The Jacobi matrix is therefore quadratic by construction.
173 */
175public:
176 /*! Constructor where \p parSensitivities is the par rate sensitivities w.r.t. zero shifts \p shiftSizes gives
177 the absolute zero and par shift sizes for each risk factor key.
178 */
180 const ParSensitivityAnalysis::ParContainer& parSensitivities,
181 const std::map<ore::analytics::RiskFactorKey, std::pair<QuantLib::Real, QuantLib::Real>>& shiftSizes);
182
183 //! Inspectors
184 //@{
185 //! Return the set of raw, i.e. zero, risk factor keys
186 //! The ordering in this set defines the order of the columns in the Jacobi matrix
187 const std::set<ore::analytics::RiskFactorKey>& rawKeys() { return rawKeys_; }
188 //! Return the set of par risk factor keys
189 //! The ordering in this set defines the order of the rows in the Jacobi matrix
190 const std::set<ore::analytics::RiskFactorKey>& parKeys() { return parKeys_; }
191 //@}
192
193 //! Takes an array of zero sensitivities and returns an array of par sensitivities
194 /*! \param zeroSensitivities array of zero sensitivities ordered according to rawKeys()
195
196 \return array of par sensitivities ordered according to parKeys()
197
198 \todo should we use a compressed_vector for the input / output parameter or both ?
199 */
200 boost::numeric::ublas::vector<Real>
201 convertSensitivity(const boost::numeric::ublas::vector<Real>& zeroSensitivities);
202
203 //! Write the inverse of the transposed Jacobian to the \p reportOut
204 void writeConversionMatrix(ore::data::Report& reportOut) const;
205
207 Size parIdx = 0;
208 for (const auto& parKey : parKeys_) {
209 Size rawIdx = 0;
210 for (const auto& rawKey : rawKeys_) {
211 results[{rawKey, parKey}] = jacobi_transp_inv_(parIdx, rawIdx);
212 rawIdx++;
213 }
214 parIdx++;
215 }
216 return results;
217 }
218
219private:
220 std::set<ore::analytics::RiskFactorKey> rawKeys_;
221 std::set<ore::analytics::RiskFactorKey> parKeys_;
222 // transposed inverse Jacobian, i.e. the matrix we use for the zero-par conversion effectively
223 QuantLib::SparseMatrix jacobi_transp_inv_;
224 //! Vector of absolute zero shift sizes
225 boost::numeric::ublas::vector<QuantLib::Real> zeroShifts_;
226 //! Vector of absolute par shift sizes
227 boost::numeric::ublas::vector<QuantLib::Real> parShifts_;
228};
229
230//! Write par instrument sensitivity report
232 ore::data::Report& reportOut);
233
234} // namespace analytics
235} // namespace ore
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)
const ParSensitivityInstrumentBuilder::Instruments & parInstruments() const
QuantLib::ext::shared_ptr< ore::analytics::ScenarioSimMarketParameters > simMarketParams_
Simulation market parameters.
std::set< ore::analytics::RiskFactorKey > & relevantRiskFactors()
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_
const ParContainer & parSensitivities() const
Return computed par sensitivities. Empty if they have not been computed yet.
const std::set< ore::analytics::RiskFactorKey > & relevantRiskFactors() const
get / set the relevant scenarios (if empty, these are ignored)
std::set< ore::analytics::RiskFactorKey > relevantRiskFactors_
ParSensitivityInstrumentBuilder::Instruments instruments_
void augmentRelevantRiskFactors()
Augment relevant risk factors.
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.
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_
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.
const std::set< ore::analytics::RiskFactorKey::KeyType > & typesDisabled() const
Return the set of key types disabled for this instance of ParSensitivityAnalysis.
void writeConversionMatrix(ore::data::Report &reportOut) const
Write the inverse of the transposed Jacobian to the reportOut.
std::set< ore::analytics::RiskFactorKey > parKeys_
const 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.
boost::numeric::ublas::vector< QuantLib::Real > parShifts_
Vector of absolute par shift sizes.
const std::set< ore::analytics::RiskFactorKey > & rawKeys()
Inspectors.
ParSensitivityAnalysis::ParContainer inverseJacobian() const
Data types stored in the scenario class.
Definition: scenario.hpp:48
KeyType
Risk Factor types.
Definition: scenario.hpp:51
Description of sensitivity shift scenarios.
static const string defaultConfiguration
void writeParConversionMatrix(const ParSensitivityAnalysis::ParContainer &parSensitivities, Report &report)
Write par instrument sensitivity report.
boost::bimap< std::string, TRS::FundingData::NotionalType > types
The base NPV cube class.
A Market class that can be updated by Scenarios.
A class to hold Scenario parameters for scenarioSimMarket.
Perform sensitivity analysis for a given portfolio.
A class to hold the parametrisation for building sensitivity scenarios.
Sensitivity scenario generation.
Date asof(14, Jun, 2018)