/src/quantlib/ql/math/statistics/gaussianstatistics.hpp
Line | Count | Source |
1 | | /* -*- mode: c++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | |
3 | | /* |
4 | | Copyright (C) 2003 Ferdinando Ametrano |
5 | | Copyright (C) 2000, 2001, 2002, 2003 RiskMap srl |
6 | | |
7 | | This file is part of QuantLib, a free-software/open-source library |
8 | | for financial quantitative analysts and developers - http://quantlib.org/ |
9 | | |
10 | | QuantLib is free software: you can redistribute it and/or modify it |
11 | | under the terms of the QuantLib license. You should have received a |
12 | | copy of the license along with this program; if not, please email |
13 | | <quantlib-dev@lists.sf.net>. The license is also available online at |
14 | | <https://www.quantlib.org/license.shtml>. |
15 | | |
16 | | This program is distributed in the hope that it will be useful, but WITHOUT |
17 | | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
18 | | FOR A PARTICULAR PURPOSE. See the license for more details. |
19 | | */ |
20 | | |
21 | | /*! \file gaussianstatistics.hpp |
22 | | \brief statistics tool for gaussian-assumption risk measures |
23 | | */ |
24 | | |
25 | | #ifndef quantlib_gaussian_statistics_h |
26 | | #define quantlib_gaussian_statistics_h |
27 | | |
28 | | #include <ql/math/distributions/normaldistribution.hpp> |
29 | | #include <ql/math/statistics/generalstatistics.hpp> |
30 | | |
31 | | namespace QuantLib { |
32 | | |
33 | | //! Statistics tool for gaussian-assumption risk measures |
34 | | /*! This class wraps a somewhat generic statistic tool and adds |
35 | | a number of gaussian risk measures (e.g.: value-at-risk, expected |
36 | | shortfall, etc.) based on the mean and variance provided by |
37 | | the underlying statistic tool. |
38 | | */ |
39 | | template<class Stat> |
40 | | class GenericGaussianStatistics : public Stat { |
41 | | public: |
42 | | typedef typename Stat::value_type value_type; |
43 | 0 | GenericGaussianStatistics() = default; |
44 | | explicit GenericGaussianStatistics(const Stat& s) : Stat(s) {} |
45 | | //! \name Gaussian risk measures |
46 | | //@{ |
47 | | /*! returns the downside variance, defined as |
48 | | \f[ \frac{N}{N-1} \times \frac{ \sum_{i=1}^{N} |
49 | | \theta \times x_i^{2}}{ \sum_{i=1}^{N} w_i} \f], |
50 | | where \f$ \theta \f$ = 0 if x > 0 and |
51 | | \f$ \theta \f$ =1 if x <0 |
52 | | */ |
53 | | Real gaussianDownsideVariance() const { |
54 | | return gaussianRegret(0.0); |
55 | | } |
56 | | |
57 | | /*! returns the downside deviation, defined as the |
58 | | square root of the downside variance. |
59 | | */ |
60 | | Real gaussianDownsideDeviation() const { |
61 | | return std::sqrt(gaussianDownsideVariance()); |
62 | | } |
63 | | |
64 | | /*! returns the variance of observations below target |
65 | | \f[ \frac{\sum w_i (min(0, x_i-target))^2 }{\sum w_i}. \f] |
66 | | |
67 | | See Dembo, Freeman "The Rules Of Risk", Wiley (2001) |
68 | | */ |
69 | | Real gaussianRegret(Real target) const; |
70 | | |
71 | | |
72 | | /*! gaussian-assumption y-th percentile, defined as the value x |
73 | | such that \f[ y = \frac{1}{\sqrt{2 \pi}} |
74 | | \int_{-\infty}^{x} \exp (-u^2/2) du \f] |
75 | | */ |
76 | | Real gaussianPercentile(Real percentile) const; |
77 | | Real gaussianTopPercentile(Real percentile) const; |
78 | | |
79 | | //! gaussian-assumption Potential-Upside at a given percentile |
80 | | Real gaussianPotentialUpside(Real percentile) const; |
81 | | |
82 | | //! gaussian-assumption Value-At-Risk at a given percentile |
83 | | Real gaussianValueAtRisk(Real percentile) const; |
84 | | |
85 | | //! gaussian-assumption Expected Shortfall at a given percentile |
86 | | /*! Assuming a gaussian distribution it |
87 | | returns the expected loss in case that the loss exceeded |
88 | | a VaR threshold, |
89 | | |
90 | | \f[ \mathrm{E}\left[ x \;|\; x < \mathrm{VaR}(p) \right], \f] |
91 | | |
92 | | that is the average of observations below the |
93 | | given percentile \f$ p \f$. |
94 | | Also know as conditional value-at-risk. |
95 | | |
96 | | See Artzner, Delbaen, Eber and Heath, |
97 | | "Coherent measures of risk", Mathematical Finance 9 (1999) |
98 | | */ |
99 | | Real gaussianExpectedShortfall(Real percentile) const; |
100 | | |
101 | | //! gaussian-assumption Shortfall (observations below target) |
102 | | Real gaussianShortfall(Real target) const; |
103 | | |
104 | | //! gaussian-assumption Average Shortfall (averaged shortfallness) |
105 | | Real gaussianAverageShortfall(Real target) const; |
106 | | //@} |
107 | | }; |
108 | | |
109 | | //! default gaussian statistic tool |
110 | | typedef GenericGaussianStatistics<GeneralStatistics> GaussianStatistics; |
111 | | |
112 | | |
113 | | //! Helper class for precomputed distributions |
114 | | class StatsHolder { |
115 | | public: |
116 | | typedef Real value_type; |
117 | | StatsHolder(Real mean, |
118 | | Real standardDeviation) |
119 | 0 | : mean_(mean), standardDeviation_(standardDeviation) {} |
120 | | ~StatsHolder() = default; |
121 | 0 | Real mean() const { return mean_; } |
122 | 0 | Real standardDeviation() const { return standardDeviation_; } |
123 | | private: |
124 | | Real mean_, standardDeviation_; |
125 | | }; |
126 | | |
127 | | |
128 | | // inline definitions |
129 | | |
130 | | template<class Stat> |
131 | | inline |
132 | | Real GenericGaussianStatistics<Stat>::gaussianRegret(Real target) const { |
133 | | Real m = this->mean(); |
134 | | Real std = this->standardDeviation(); |
135 | | Real variance = std*std; |
136 | | CumulativeNormalDistribution gIntegral(m, std); |
137 | | NormalDistribution g(m, std); |
138 | | Real firstTerm = variance + m*m - 2.0*target*m + target*target; |
139 | | Real alfa = gIntegral(target); |
140 | | Real secondTerm = m - target; |
141 | | Real beta = variance*g(target); |
142 | | Real result = alfa*firstTerm - beta*secondTerm; |
143 | | return result/alfa; |
144 | | } |
145 | | |
146 | | /*! \pre percentile must be in range (0%-100%) extremes excluded */ |
147 | | template<class Stat> |
148 | | inline Real GenericGaussianStatistics<Stat>::gaussianPercentile( |
149 | | Real percentile) const { |
150 | | |
151 | | QL_REQUIRE(percentile>0.0, |
152 | | "percentile (" << percentile << ") must be > 0.0"); |
153 | | QL_REQUIRE(percentile<1.0, |
154 | | "percentile (" << percentile << ") must be < 1.0"); |
155 | | |
156 | | InverseCumulativeNormal gInverse(Stat::mean(), |
157 | | Stat::standardDeviation()); |
158 | | return gInverse(percentile); |
159 | | } |
160 | | |
161 | | /*! \pre percentile must be in range (0%-100%) extremes excluded */ |
162 | | template<class Stat> |
163 | | inline Real GenericGaussianStatistics<Stat>::gaussianTopPercentile( |
164 | | Real percentile) const { |
165 | | |
166 | | return gaussianPercentile(1.0-percentile); |
167 | | } |
168 | | |
169 | | /*! \pre percentile must be in range [90%-100%) */ |
170 | | template<class Stat> |
171 | | inline Real GenericGaussianStatistics<Stat>::gaussianPotentialUpside( |
172 | | Real percentile) const { |
173 | | |
174 | | QL_REQUIRE(percentile<1.0 && percentile>=0.9, |
175 | | "percentile (" << percentile << ") out of range [0.9, 1)"); |
176 | | |
177 | | Real result = gaussianPercentile(percentile); |
178 | | // potential upside must be a gain, i.e., floored at 0.0 |
179 | | return std::max<Real>(result, 0.0); |
180 | | } |
181 | | |
182 | | |
183 | | /*! \pre percentile must be in range [90%-100%) */ |
184 | | template<class Stat> |
185 | | inline Real GenericGaussianStatistics<Stat>::gaussianValueAtRisk( |
186 | | Real percentile) const { |
187 | | |
188 | | QL_REQUIRE(percentile<1.0 && percentile>=0.9, |
189 | | "percentile (" << percentile << ") out of range [0.9, 1)"); |
190 | | |
191 | | Real result = gaussianPercentile(1.0-percentile); |
192 | | // VAR must be a loss |
193 | | // this means that it has to be MIN(dist(1.0-percentile), 0.0) |
194 | | // VAR must also be a positive quantity, so -MIN(*) |
195 | | return -std::min<Real>(result, 0.0); |
196 | | } |
197 | | |
198 | | |
199 | | /*! \pre percentile must be in range [90%-100%) */ |
200 | | template<class Stat> |
201 | | inline Real GenericGaussianStatistics<Stat>::gaussianExpectedShortfall( |
202 | | Real percentile) const { |
203 | | QL_REQUIRE(percentile<1.0 && percentile>=0.9, |
204 | | "percentile (" << percentile << ") out of range [0.9, 1)"); |
205 | | |
206 | | Real m = this->mean(); |
207 | | Real std = this->standardDeviation(); |
208 | | InverseCumulativeNormal gInverse(m, std); |
209 | | Real var = gInverse(1.0-percentile); |
210 | | NormalDistribution g(m, std); |
211 | | Real result = m - std*std*g(var)/(1.0-percentile); |
212 | | // expectedShortfall must be a loss |
213 | | // this means that it has to be MIN(result, 0.0) |
214 | | // expectedShortfall must also be a positive quantity, so -MIN(*) |
215 | | return -std::min<Real>(result, 0.0); |
216 | | } |
217 | | |
218 | | |
219 | | template<class Stat> |
220 | | inline Real GenericGaussianStatistics<Stat>::gaussianShortfall( |
221 | | Real target) const { |
222 | | CumulativeNormalDistribution gIntegral(this->mean(), |
223 | | this->standardDeviation()); |
224 | | return gIntegral(target); |
225 | | } |
226 | | |
227 | | |
228 | | template<class Stat> |
229 | | inline Real GenericGaussianStatistics<Stat>::gaussianAverageShortfall( |
230 | | Real target) const { |
231 | | Real m = this->mean(); |
232 | | Real std = this->standardDeviation(); |
233 | | CumulativeNormalDistribution gIntegral(m, std); |
234 | | NormalDistribution g(m, std); |
235 | | return ( (target-m) + std*std*g(target)/gIntegral(target) ); |
236 | | } |
237 | | |
238 | | } |
239 | | |
240 | | |
241 | | #endif |