30template <std::
floating_po
int Real>
33 if (sample.size() < 2)
34 throw std::invalid_argument(
"Tail-index estimation requires at least two observations");
35 if (std::ranges::any_of(sample, [](Real value) {
return !(value > 0) || !std::isfinite(value); }))
36 throw std::invalid_argument(
"Tail-index estimation requires positive finite observations");
37 std::vector<Real>
sorted(sample.begin(), sample.end());
42template <std::
floating_po
int Real>
45 if (order == 0 || order >=
sorted.size())
46 throw std::invalid_argument(
"Hill estimator order should be between one and sample size minus one");
51 return static_cast<double>(
sum / order);
56template <std::
floating_po
int Real>
63template <std::ranges::contiguous_range Range>
64 requires std::floating_point<std::remove_cv_t<std::ranges::range_value_t<Range>>> &&
65 (!std::same_as<std::remove_cvref_t<Range>,
66 std::span<const std::remove_cv_t<std::ranges::range_value_t<Range>>>>)
69 using Real = std::remove_cv_t<std::ranges::range_value_t<Range>>;
73template <std::
floating_po
int Real>
74std::vector<TailIndexEstimate>
hill_plot(std::span<const Real> sample, std::size_t maximumOrder = 0)
77 if (maximumOrder == 0)
78 maximumOrder = sorted.size() - 1;
79 if (maximumOrder >= sorted.size())
80 throw std::invalid_argument(
"Maximum Hill order should be smaller than the sample size");
82 std::vector<TailIndexEstimate> result;
83 result.reserve(maximumOrder);
84 for (std::size_t order = 1; order <= maximumOrder; ++order) {
85 result.push_back({order,
static_cast<double>(sorted[sorted.size() - order - 1]),
91template <std::ranges::contiguous_range Range>
92 requires std::floating_point<std::remove_cv_t<std::ranges::range_value_t<Range>>> &&
93 (!std::same_as<std::remove_cvref_t<Range>,
94 std::span<const std::remove_cv_t<std::ranges::range_value_t<Range>>>>)
95std::vector<TailIndexEstimate>
hill_plot(
const Range &sample, std::size_t maximumOrder = 0)
97 using Real = std::remove_cv_t<std::ranges::range_value_t<Range>>;
98 return hill_plot(std::span<const Real>(sample), maximumOrder);
101template <std::
floating_po
int Real>
105 if (order == 0 || order > sorted.size() / 4)
106 throw std::invalid_argument(
107 "Pickands estimator order should be positive with four times the order at most the sample size");
108 const double upper =
static_cast<double>(sorted[sorted.size() - order]);
109 const double middle =
static_cast<double>(sorted[sorted.size() - 2 * order]);
110 const double lower =
static_cast<double>(sorted[sorted.size() - 4 * order]);
111 const double numerator = upper - middle;
112 const double denominator = middle - lower;
113 if (!(numerator > 0) || !(denominator > 0))
114 throw std::invalid_argument(
"Pickands estimator requires distinct upper order statistics");
115 return std::log(numerator / denominator) / std::log(2.0);
118template <std::ranges::contiguous_range Range>
119 requires std::floating_point<std::remove_cv_t<std::ranges::range_value_t<Range>>> &&
120 (!std::same_as<std::remove_cvref_t<Range>,
121 std::span<const std::remove_cv_t<std::ranges::range_value_t<Range>>>>)
124 using Real = std::remove_cv_t<std::ranges::range_value_t<Range>>;
128template <std::
floating_po
int Real>
132 if (!std::isfinite(threshold))
133 throw std::invalid_argument(
"Peaks-over-threshold fitting requires a finite threshold");
134 std::vector<Real> exceedances;
135 exceedances.reserve(sample.size());
136 for (Real value : sample) {
137 if (!std::isfinite(value))
139 if (value > threshold)
140 exceedances.push_back(value - threshold);
142 auto result = fit<GeneralizedParetoRand<Real>>(std::span<const Real>(exceedances), std::move(options));
143 result.distribution = GeneralizedParetoRand<Real>(result.distribution.GetShape(), result.distribution.GetScale(),
144 static_cast<double>(threshold));
148template <std::ranges::contiguous_range Range>
149 requires std::floating_point<std::remove_cv_t<std::ranges::range_value_t<Range>>> &&
150 (!std::same_as<std::remove_cvref_t<Range>,
151 std::span<const std::remove_cv_t<std::ranges::range_value_t<Range>>>>)
154 using Real = std::remove_cv_t<std::ranges::range_value_t<Range>>;
double hillFromSorted(std::span< const Real > sorted, std::size_t order)
Definition tail.hpp:43
std::vector< Real > sortedTailSample(std::span< const Real > sample)
Definition tail.hpp:31
Real standardNormal(G &g)
Ziggurat algorithm of Marsaglia and Tsang with 256 layers and an explicit sign bit.
Definition variates.hpp:45
Definition bivariate_normal.hpp:10
@ WrongSample
the sample could not have been drawn from this distribution
FitResult< GeneralizedParetoRand< Real > > fit_peaks_over_threshold(std::span< const Real > sample, Real threshold, FitOptions options={})
Definition tail.hpp:129
double pickands_estimator(std::span< const Real > sample, std::size_t order)
Definition tail.hpp:102
double hill_estimator(std::span< const Real > sample, std::size_t order)
Definition tail.hpp:57
std::vector< TailIndexEstimate > hill_plot(std::span< const Real > sample, std::size_t maximumOrder=0)
Definition tail.hpp:74
double threshold
Definition tail.hpp:23
double estimate
Definition tail.hpp:24
std::size_t order
Definition tail.hpp:22