QuantLib: a free/open-source library for quantitative finance
fully annotated source code - version 1.38
Loading...
Searching...
No Matches
sensitivityanalysis.cpp
Go to the documentation of this file.
1/* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3/*
4 Copyright (C) 2008 Ferdinando Ametrano
5
6 This file is part of QuantLib, a free-software/open-source library
7 for financial quantitative analysts and developers - http://quantlib.org/
8
9 QuantLib is free software: you can redistribute it and/or modify it
10 under the terms of the QuantLib license. You should have received a
11 copy of the license along with this program; if not, please email
12 <quantlib-dev@lists.sf.net>. The license is also available online at
13 <http://quantlib.org/license.shtml>.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the license for more details.
18*/
19
22#include <ql/instrument.hpp>
23
24using std::vector;
25using std::pair;
26
27namespace QuantLib {
28
30
31 std::ostream& operator<<(std::ostream& out,
33 switch (s) {
34 case OneSide:
35 return out << "OneSide";
36 case Centered:
37 return out << "Centered";
38 default:
39 QL_FAIL("unknown SensitivityAnalysis (" << Integer(s) << ")");
40 }
41 }
42
43 Real aggregateNPV(const vector<ext::shared_ptr<Instrument> >& instruments,
44 const vector<Real>& quant) {
45 Size n = instruments.size();
46 Real npv = 0.0;
47 if (quant.empty() || (quant.size()==1 && quant[0]==1.0)) {
48 for (Size k=0; k<n; ++k)
49 npv += instruments[k]->NPV();
50 } else {
51 QL_REQUIRE(quant.size()==n,
52 "dimension mismatch between instruments (" << n <<
53 ") and quantities (" << quant.size() << ")");
54 for (Size k=0; k<n; ++k)
55 npv += quant[k] * instruments[k]->NPV();
56 }
57 return npv;
58 }
59
60 pair<Real, Real>
61 parallelAnalysis(const vector<Handle<SimpleQuote> >& quotes,
62 const vector<ext::shared_ptr<Instrument> >& instruments,
63 const vector<Real>& quantities,
64 Real shift,
66 Real referenceNpv)
67 {
68 QL_REQUIRE(!quotes.empty(), "empty SimpleQuote vector");
69 Size n = quotes.size();
70
71 QL_REQUIRE(shift!=0.0, "zero shift not allowed");
72
73 pair<Real, Real> result(0.0, 0.0);
74 if (instruments.empty()) return result;
75
76 if (referenceNpv==Null<Real>())
77 referenceNpv = aggregateNPV(instruments, quantities);
78
79 vector<Real> quoteValues(n, Null<Real>());
80 for (Size i=0; i<n; ++i)
81 if (quotes[i]->isValid())
82 quoteValues[i] = quotes[i]->value();
83 try {
84 for (Size i=0; i<n; ++i)
85 if (quotes[i]->isValid())
86 quotes[i]->setValue(quoteValues[i]+shift);
87 Real npv = aggregateNPV(instruments, quantities);
88 switch (type) {
89 case OneSide:
90 result.first = (npv-referenceNpv)/shift;
91 result.second = Null<Real>();
92 break;
93 case Centered:
94 {
95 for (Size i=0; i<n; ++i)
96 if (quotes[i]->isValid())
97 quotes[i]->setValue(quoteValues[i]-shift);
98 Real npv2 = aggregateNPV(instruments, quantities);
99 result.first = (npv-npv2)/(2.0*shift);
100 result.second = (npv-2.0*referenceNpv+npv2)/(shift*shift);
101 }
102 break;
103 default:
104 QL_FAIL("unknown SensitivityAnalysis (" <<
105 Integer(type) << ")");
106 }
107 for (Size i=0; i<n; ++i)
108 if (quotes[i]->isValid())
109 quotes[i]->setValue(quoteValues[i]);
110 } catch (...) {
111 for (Size i=0; i<n; ++i)
112 if (quoteValues[i]!=Null<Real>())
113 quotes[i]->setValue(quoteValues[i]);
114 throw;
115 }
116
117 return result;
118 }
119
120 pair<Real, Real> bucketAnalysis(const Handle<SimpleQuote>& quote,
121 const vector<ext::shared_ptr<Instrument> >& instruments,
122 const vector<Real>& quantities,
123 Real shift,
125 Real referenceNpv) {
126 QL_REQUIRE(shift!=0.0, "zero shift not allowed");
127
128 pair<Real, Real> result(0.0, 0.0);
129 if (instruments.empty()) return result;
130
131 if (referenceNpv==Null<Real>())
132 referenceNpv = aggregateNPV(instruments, quantities);
133
134 if (!quote->isValid()) return result;
135 Real quoteValue = quote->value();
136
137 try {
138 quote->setValue(quoteValue+shift);
139 Real npv = aggregateNPV(instruments, quantities);
140 switch (type) {
141 case OneSide:
142 result.first = (npv-referenceNpv)/shift;
143 result.second = Null<Real>();
144 break;
145 case Centered:
146 {
147 quote->setValue(quoteValue-shift);
148 Real npv2 = aggregateNPV(instruments, quantities);
149 result.first = (npv-npv2)/(2.0*shift);
150 result.second = (npv-2.0*referenceNpv+npv2)/(shift*shift);
151 }
152 break;
153 default:
154 QL_FAIL("unknown SensitivityAnalysis (" <<
155 Integer(type) << ")");
156 }
157 quote->setValue(quoteValue);
158 } catch (...) {
159 quote->setValue(quoteValue);
160 throw;
161 }
162
163 return result;
164 }
165
166
167 void bucketAnalysis(vector<Real>& deltaVector, // delta result
168 vector<Real>& gammaVector, // gamma result
169 vector<Real>& refVals,
170 const Handle<SimpleQuote>& quote,
171 const vector<Handle<Quote> >& params,
172 Real shift,
173 SensitivityAnalysis type) {
174 QL_REQUIRE(shift!=0.0, "zero shift not allowed");
175
176 QL_REQUIRE(!params.empty(), "empty parameters vector");
177 Size m = params.size();
178 deltaVector.resize(m);
179 gammaVector.resize(m);
180
181 if (!quote->isValid()) {
182 for (Size j=0; j<m; ++j) {
183 deltaVector[j]=Null<Real>();
184 gammaVector[j]=Null<Real>();
185 }
186 return;
187 }
188 Real quoteValue = quote->value();
189
190 if (!refVals.empty()) {
191 QL_REQUIRE(refVals.size()==m,
192 "referenceValues has size " <<
193 refVals.size() << ", instead of " << m);
194 } else {
195 // calculate parameters' reference values
196 refVals = vector<Real>(m, Null<Real>());
197 for (Size j=0; j<m; ++j) {
198 if (params[j]->isValid()) // fault tolerant
199 refVals[j] = params[j]->value();
200 }
201 }
202
203 try {
204 switch (type) {
205 case OneSide:
206 {
207 quote->setValue(quoteValue+shift);
208 for (Size j=0; j<m; ++j) {
209 gammaVector[j] = Null<Real>();
210 if (refVals[j] != Null<Real>())
211 deltaVector[j] = (params[j]->value()-refVals[j])/shift;
212 else
213 deltaVector[j] = Null<Real>();
214 }
215 }
216 break;
217 case Centered:
218 {
219 quote->setValue(quoteValue+shift);
220 vector<Real> plus(m);
221 for (Size j=0; j<m; ++j) {
222 if (refVals[j] != Null<Real>())
223 plus[j] = params[j]->value();
224 }
225 quote->setValue(quoteValue-shift);
226 for (Size j=0; j<m; ++j) {
227 if (refVals[j] != Null<Real>()) {
228 Real minus = params[j]->value();
229 deltaVector[j] = (plus[j]-minus)/(2.0*shift);
230 gammaVector[j] = (plus[j]-2.0*refVals[j]+minus)/(shift*shift);
231 } else {
232 deltaVector[j] = Null<Real>();
233 gammaVector[j] = Null<Real>();
234 }
235 }
236 }
237 break;
238 default:
239 QL_FAIL("unknown SensitivityAnalysis (" <<
240 Integer(type) << ")");
241 } // end switch
242
243 // restore the quote to its original state
244 quote->setValue(quoteValue);
245
246 return;
247 } catch (...) {
248 // restore the quote to its original state
249 quote->setValue(quoteValue);
250 throw;
251 }
252
253 }
254
255
256
257
258
259 pair<vector<Real>, vector<Real> >
260 bucketAnalysis(const vector<Handle<SimpleQuote> >& quotes,
261 const vector<ext::shared_ptr<Instrument> >& instr,
262 const vector<Real>& quant,
263 Real shift,
265 {
266 QL_REQUIRE(!quotes.empty(), "empty SimpleQuote vector");
267 Size n = quotes.size();
268 pair<vector<Real>, vector<Real> > result(vector<Real>(n, 0.0),
269 vector<Real>(n, 0.0));
270
271 if (instr.empty()) return result;
272
273 Real npv = aggregateNPV(instr, quant);
274
275 pair<Real, Real> tmp;
276 for (Size i=0; i<n; ++i) {
277 tmp = bucketAnalysis(quotes[i], instr, quant, shift, type, npv);
278 result.first[i] = tmp.first;
279 result.second[i] = tmp.second;
280 }
281
282 return result;
283 }
284
285 void
286 bucketAnalysis(std::vector<std::vector<Real> >& deltaMatrix, // result
287 std::vector<std::vector<Real> >& gammaMatrix, // result
288 const vector<Handle<SimpleQuote> >& quotes,
289 const vector<Handle<Quote> >& parameters,
290 Real shift,
292 {
293 QL_REQUIRE(!quotes.empty(), "empty SimpleQuote vector");
294 QL_REQUIRE(!parameters.empty(), "empty parameters vector");
295
296 Size n = quotes.size();
297 deltaMatrix.resize(n);
298 gammaMatrix.resize(n);
299
300 Size m = parameters.size();
301 vector<Real> referenceValues(m, Null<Real>());
302 for (Size i=0; i<m; ++i) {
303 if (parameters[i]->isValid())
304 referenceValues[i] = parameters[i]->value();
305 }
306
307 for (Size i=0; i<n; ++i) {
308 bucketAnalysis(deltaMatrix[i], gammaMatrix[i], referenceValues,
309 quotes[i], parameters, shift, type);
310 }
311 }
312
313 pair<vector<vector<Real> >, vector<vector<Real> > >
314 bucketAnalysis(const vector<vector<Handle<SimpleQuote> > >& quotes,
315 const vector<ext::shared_ptr<Instrument> >& instr,
316 const vector<Real>& quant,
317 Real shift,
319 {
320 QL_REQUIRE(!quotes.empty(), "empty SimpleQuote range");
321 Size n = quotes.size();
322 vector<vector<Real> > first(n);
323 vector<vector<Real> > second(n);
324 for (Size i=0; i<n; ++i) {
325 Size tmp = quotes[i].size();
326 first[i] = vector<Real>(tmp, 0.0);
327 second[i] = vector<Real>(tmp, 0.0);
328 }
329
330 pair<vector<vector<Real> >, vector<vector<Real> > >
331 result(first, second);
332
333 if (instr.empty()) return result;
334
335 Real npv = aggregateNPV(instr, quant);
336
337 pair<Real, Real> tmp;
338 for (Size i=0; i<n; ++i) {
339 for (Size j=0; j<quotes[i].size(); ++j) {
340 tmp = bucketAnalysis(quotes[i][j], instr, quant, shift, type, npv);
341 result.first[i][j] = tmp.first;
342 result.second[i][j] = tmp.second;
343 }
344 }
345
346 return result;
347 }
348
350}
Shared handle to an observable.
Definition: handle.hpp:41
template class providing a null value for a given type.
Definition: null.hpp:59
#define QL_REQUIRE(condition, message)
throw an error if the given pre-condition is not verified
Definition: errors.hpp:117
#define QL_FAIL(message)
throw an error (possibly with file and line information)
Definition: errors.hpp:92
QL_REAL Real
real number
Definition: types.hpp:50
QL_INTEGER Integer
integer number
Definition: types.hpp:35
std::size_t Size
size of a container
Definition: types.hpp:58
Abstract instrument class.
Definition: any.hpp:37
Real aggregateNPV(const vector< ext::shared_ptr< Instrument > > &instruments, const vector< Real > &quant)
utility fuction for weighted sum of NPVs
pair< Real, Real > parallelAnalysis(const vector< Handle< SimpleQuote > > &quotes, const vector< ext::shared_ptr< Instrument > > &instruments, const vector< Real > &quantities, Real shift, SensitivityAnalysis type, Real referenceNpv)
parallel shift PV01 sensitivity analysis for a SimpleQuote vector
std::ostream & operator<<(std::ostream &out, GFunctionFactory::YieldCurveModel type)
pair< Real, Real > bucketAnalysis(const Handle< SimpleQuote > &quote, const vector< ext::shared_ptr< Instrument > > &instruments, const vector< Real > &quantities, Real shift, SensitivityAnalysis type, Real referenceNpv)
(bucket) PV01 sensitivity analysis for a (single) SimpleQuote
SensitivityAnalysis
Finite differences calculation.
#define QL_DEPRECATED_DISABLE_WARNING
Definition: qldefines.hpp:216
#define QL_DEPRECATED_ENABLE_WARNING
Definition: qldefines.hpp:217
sensitivity analysis function
simple quote class