1 ///////////////////////////////////////////////////////////////////////////////
2 // pot_tail_mean.hpp
3 //
4 //  Copyright 2006 Daniel Egloff, Olivier Gygi. Distributed under the Boost
5 //  Software License, Version 1.0. (See accompanying file
6 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #ifndef BOOST_ACCUMULATORS_STATISTICS_POT_TAIL_MEAN_HPP_DE_01_01_2006
9 #define BOOST_ACCUMULATORS_STATISTICS_POT_TAIL_MEAN_HPP_DE_01_01_2006
10 
11 #include <vector>
12 #include <limits>
13 #include <numeric>
14 #include <functional>
15 #include <boost/range.hpp>
16 #include <boost/parameter/keyword.hpp>
17 #include <boost/tuple/tuple.hpp>
18 #include <boost/mpl/if.hpp>
19 #include <boost/mpl/placeholders.hpp>
20 #include <boost/type_traits/is_same.hpp>
21 #include <boost/accumulators/framework/accumulator_base.hpp>
22 #include <boost/accumulators/framework/extractor.hpp>
23 #include <boost/accumulators/numeric/functional.hpp>
24 #include <boost/accumulators/framework/parameters/sample.hpp>
25 #include <boost/accumulators/statistics_fwd.hpp>
26 #include <boost/accumulators/statistics/peaks_over_threshold.hpp>
27 #include <boost/accumulators/statistics/weighted_peaks_over_threshold.hpp>
28 #include <boost/accumulators/statistics/pot_quantile.hpp>
29 #include <boost/accumulators/statistics/tail_mean.hpp>
30 
31 namespace boost { namespace accumulators
32 {
33 
34 namespace impl
35 {
36     ///////////////////////////////////////////////////////////////////////////////
37     // pot_tail_mean_impl
38     //
39     /**
40         @brief Estimation of the (coherent) tail mean based on the peaks over threshold method (for both left and right tails)
41 
42         Computes an estimate for the (coherent) tail mean
43         \f[
44             \widehat{CTM}_{\alpha} = \hat{q}_{\alpha} - \frac{\bar{\beta}}{\xi-1}(1-\alpha)^{-\xi},
45         \f]
46         where \f$\bar[u]\f$, \f$\bar{\beta}\f$ and \f$\xi\f$ are the parameters of the
47         generalized Pareto distribution that approximates the right tail of the distribution (or the
48         mirrored left tail, in case the left tail is used). In the latter case, the result is mirrored
49         back, yielding the correct result.
50     */
51     template<typename Sample, typename Impl, typename LeftRight>
52     struct pot_tail_mean_impl
53       : accumulator_base
54     {
55         typedef typename numeric::functional::fdiv<Sample, std::size_t>::result_type float_type;
56         // for boost::result_of
57         typedef float_type result_type;
58 
pot_tail_mean_implboost::accumulators::impl::pot_tail_mean_impl59         pot_tail_mean_impl(dont_care)
60           : sign_((is_same<LeftRight, left>::value) ? -1 : 1)
61         {
62         }
63 
64         template<typename Args>
resultboost::accumulators::impl::pot_tail_mean_impl65         result_type result(Args const &args) const
66         {
67             typedef
68                 typename mpl::if_<
69                     is_same<Impl, weighted>
70                   , tag::weighted_peaks_over_threshold<LeftRight>
71                   , tag::peaks_over_threshold<LeftRight>
72                 >::type
73             peaks_over_threshold_tag;
74 
75             typedef
76                 typename mpl::if_<
77                     is_same<Impl, weighted>
78                   , tag::weighted_pot_quantile<LeftRight>
79                   , tag::pot_quantile<LeftRight>
80                 >::type
81             pot_quantile_tag;
82 
83             extractor<peaks_over_threshold_tag> const some_peaks_over_threshold = {};
84             extractor<pot_quantile_tag> const some_pot_quantile = {};
85 
86             float_type beta_bar = some_peaks_over_threshold(args).template get<1>();
87             float_type xi_hat   = some_peaks_over_threshold(args).template get<2>();
88 
89             return some_pot_quantile(args) - this->sign_ * beta_bar/( xi_hat - 1. ) * std::pow(
90                 is_same<LeftRight, left>::value ? args[quantile_probability] : 1. - args[quantile_probability]
91               , -xi_hat);
92         }
93 
94         // make this accumulator serializeable
95         template<class Archive>
serializeboost::accumulators::impl::pot_tail_mean_impl96         void serialize(Archive & ar, const unsigned int file_version)
97         {
98             ar & sign_;
99         }
100 
101     private:
102         short sign_; // if the fit parameters from the mirrored left tail extreme values are used, mirror back the result
103     };
104 } // namespace impl
105 
106 ///////////////////////////////////////////////////////////////////////////////
107 // tag::pot_tail_mean
108 // tag::pot_tail_mean_prob
109 //
110 namespace tag
111 {
112     template<typename LeftRight>
113     struct pot_tail_mean
114       : depends_on<peaks_over_threshold<LeftRight>, pot_quantile<LeftRight> >
115     {
116         /// INTERNAL ONLY
117         ///
118         typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, unweighted, LeftRight> impl;
119     };
120     template<typename LeftRight>
121     struct pot_tail_mean_prob
122       : depends_on<peaks_over_threshold_prob<LeftRight>, pot_quantile_prob<LeftRight> >
123     {
124         /// INTERNAL ONLY
125         ///
126         typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, unweighted, LeftRight> impl;
127     };
128     template<typename LeftRight>
129     struct weighted_pot_tail_mean
130       : depends_on<weighted_peaks_over_threshold<LeftRight>, weighted_pot_quantile<LeftRight> >
131     {
132         /// INTERNAL ONLY
133         ///
134         typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, weighted, LeftRight> impl;
135     };
136     template<typename LeftRight>
137     struct weighted_pot_tail_mean_prob
138       : depends_on<weighted_peaks_over_threshold_prob<LeftRight>, weighted_pot_quantile_prob<LeftRight> >
139     {
140         /// INTERNAL ONLY
141         ///
142         typedef accumulators::impl::pot_tail_mean_impl<mpl::_1, weighted, LeftRight> impl;
143     };
144 }
145 
146 // pot_tail_mean<LeftRight>(with_threshold_value) -> pot_tail_mean<LeftRight>
147 template<typename LeftRight>
148 struct as_feature<tag::pot_tail_mean<LeftRight>(with_threshold_value)>
149 {
150     typedef tag::pot_tail_mean<LeftRight> type;
151 };
152 
153 // pot_tail_mean<LeftRight>(with_threshold_probability) -> pot_tail_mean_prob<LeftRight>
154 template<typename LeftRight>
155 struct as_feature<tag::pot_tail_mean<LeftRight>(with_threshold_probability)>
156 {
157     typedef tag::pot_tail_mean_prob<LeftRight> type;
158 };
159 
160 // weighted_pot_tail_mean<LeftRight>(with_threshold_value) -> weighted_pot_tail_mean<LeftRight>
161 template<typename LeftRight>
162 struct as_feature<tag::weighted_pot_tail_mean<LeftRight>(with_threshold_value)>
163 {
164     typedef tag::weighted_pot_tail_mean<LeftRight> type;
165 };
166 
167 // weighted_pot_tail_mean<LeftRight>(with_threshold_probability) -> weighted_pot_tail_mean_prob<LeftRight>
168 template<typename LeftRight>
169 struct as_feature<tag::weighted_pot_tail_mean<LeftRight>(with_threshold_probability)>
170 {
171     typedef tag::weighted_pot_tail_mean_prob<LeftRight> type;
172 };
173 
174 // for the purposes of feature-based dependency resolution,
175 // pot_tail_mean<LeftRight> and pot_tail_mean_prob<LeftRight> provide
176 // the same feature as tail_mean
177 template<typename LeftRight>
178 struct feature_of<tag::pot_tail_mean<LeftRight> >
179   : feature_of<tag::tail_mean>
180 {
181 };
182 
183 template<typename LeftRight>
184 struct feature_of<tag::pot_tail_mean_prob<LeftRight> >
185   : feature_of<tag::tail_mean>
186 {
187 };
188 
189 // So that pot_tail_mean can be automatically substituted
190 // with weighted_pot_tail_mean when the weight parameter is non-void.
191 template<typename LeftRight>
192 struct as_weighted_feature<tag::pot_tail_mean<LeftRight> >
193 {
194     typedef tag::weighted_pot_tail_mean<LeftRight> type;
195 };
196 
197 template<typename LeftRight>
198 struct feature_of<tag::weighted_pot_tail_mean<LeftRight> >
199   : feature_of<tag::pot_tail_mean<LeftRight> >
200 {
201 };
202 
203 // So that pot_tail_mean_prob can be automatically substituted
204 // with weighted_pot_tail_mean_prob when the weight parameter is non-void.
205 template<typename LeftRight>
206 struct as_weighted_feature<tag::pot_tail_mean_prob<LeftRight> >
207 {
208     typedef tag::weighted_pot_tail_mean_prob<LeftRight> type;
209 };
210 
211 template<typename LeftRight>
212 struct feature_of<tag::weighted_pot_tail_mean_prob<LeftRight> >
213   : feature_of<tag::pot_tail_mean_prob<LeftRight> >
214 {
215 };
216 
217 }} // namespace boost::accumulators
218 
219 #endif
220