/src/quantlib/ql/math/statistics/generalstatistics.cpp
Line | Count | Source (jump to first uncovered line) |
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) 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 | | <http://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 | | #include <ql/math/statistics/generalstatistics.hpp> |
22 | | |
23 | | namespace QuantLib { |
24 | | |
25 | 0 | Real GeneralStatistics::weightSum() const { |
26 | 0 | Real result = 0.0; |
27 | 0 | std::vector<std::pair<Real,Real> >::const_iterator it; |
28 | 0 | for (it=samples_.begin(); it!=samples_.end(); ++it) { |
29 | 0 | result += it->second; |
30 | 0 | } |
31 | 0 | return result; |
32 | 0 | } |
33 | | |
34 | 0 | Real GeneralStatistics::mean() const { |
35 | 0 | Size N = samples(); |
36 | 0 | QL_REQUIRE(N != 0, "empty sample set"); |
37 | 0 | return expectationValue([](Real x) { return x; }).first; |
38 | 0 | } |
39 | | |
40 | 0 | Real GeneralStatistics::variance() const { |
41 | 0 | Size N = samples(); |
42 | 0 | QL_REQUIRE(N > 1, |
43 | 0 | "sample number <=1, unsufficient"); |
44 | | // Subtract the mean and square. Repeat on the whole range. |
45 | | // Hopefully, the whole thing will be inlined in a single loop. |
46 | 0 | Real m = mean(); |
47 | 0 | Real s2 = expectationValue([=](Real x) -> Real { |
48 | 0 | Real d = x - m; |
49 | 0 | return d * d; |
50 | 0 | }).first; |
51 | 0 | return s2*N/(N-1.0); |
52 | 0 | } |
53 | | |
54 | 0 | Real GeneralStatistics::skewness() const { |
55 | 0 | Size N = samples(); |
56 | 0 | QL_REQUIRE(N > 2, |
57 | 0 | "sample number <=2, unsufficient"); |
58 | | |
59 | 0 | Real m = mean(); |
60 | 0 | Real X = expectationValue([=](Real x) -> Real { |
61 | 0 | Real d = x - m; |
62 | 0 | return d * d * d; |
63 | 0 | }).first; |
64 | 0 | Real sigma = standardDeviation(); |
65 | |
|
66 | 0 | return (X/(sigma*sigma*sigma))*(N/(N-1.0))*(N/(N-2.0)); |
67 | 0 | } |
68 | | |
69 | 0 | Real GeneralStatistics::kurtosis() const { |
70 | 0 | Size N = samples(); |
71 | 0 | QL_REQUIRE(N > 3, |
72 | 0 | "sample number <=3, unsufficient"); |
73 | | |
74 | 0 | Real m = mean(); |
75 | 0 | Real X = expectationValue([=](Real x) -> Real { |
76 | 0 | Real d = x - m; |
77 | 0 | Real d2 = d * d; |
78 | 0 | return d2 * d2; |
79 | 0 | }).first; |
80 | 0 | Real sigma2 = variance(); |
81 | |
|
82 | 0 | Real c1 = (N/(N-1.0)) * (N/(N-2.0)) * ((N+1.0)/(N-3.0)); |
83 | 0 | Real c2 = 3.0 * ((N-1.0)/(N-2.0)) * ((N-1.0)/(N-3.0)); |
84 | |
|
85 | 0 | return c1*(X/(sigma2*sigma2))-c2; |
86 | 0 | } |
87 | | |
88 | 0 | Real GeneralStatistics::percentile(Real percent) const { |
89 | |
|
90 | 0 | QL_REQUIRE(percent > 0.0 && percent <= 1.0, |
91 | 0 | "percentile (" << percent << ") must be in (0.0, 1.0]"); |
92 | | |
93 | 0 | Real sampleWeight = weightSum(); |
94 | 0 | QL_REQUIRE(sampleWeight>0.0, |
95 | 0 | "empty sample set"); |
96 | | |
97 | 0 | sort(); |
98 | |
|
99 | 0 | std::vector<std::pair<Real,Real> >::iterator k, l; |
100 | 0 | k = samples_.begin(); |
101 | 0 | l = samples_.end()-1; |
102 | | /* the sum of weight is non null, therefore there's |
103 | | at least one sample */ |
104 | 0 | Real integral = k->second, target = percent*sampleWeight; |
105 | 0 | while (integral < target && k != l) { |
106 | 0 | ++k; |
107 | 0 | integral += k->second; |
108 | 0 | } |
109 | 0 | return k->first; |
110 | 0 | } |
111 | | |
112 | 0 | Real GeneralStatistics::topPercentile(Real percent) const { |
113 | |
|
114 | 0 | QL_REQUIRE(percent > 0.0 && percent <= 1.0, |
115 | 0 | "percentile (" << percent << ") must be in (0.0, 1.0]"); |
116 | | |
117 | 0 | Real sampleWeight = weightSum(); |
118 | 0 | QL_REQUIRE(sampleWeight > 0.0, |
119 | 0 | "empty sample set"); |
120 | | |
121 | 0 | sort(); |
122 | |
|
123 | 0 | std::vector<std::pair<Real,Real> >::reverse_iterator k, l; |
124 | 0 | k = samples_.rbegin(); |
125 | 0 | l = samples_.rend()-1; |
126 | | /* the sum of weight is non null, therefore there's |
127 | | at least one sample */ |
128 | 0 | Real integral = k->second, target = percent*sampleWeight; |
129 | 0 | while (integral < target && k != l) { |
130 | 0 | ++k; |
131 | 0 | integral += k->second; |
132 | 0 | } |
133 | 0 | return k->first; |
134 | 0 | } |
135 | | |
136 | | } |