extremeloss¶
Extreme-value tail estimation for large claims: peaks-over-threshold with the
generalized Pareto distribution (GPD), tail analytics, and large-claim loading.
Matplotlib is optional via the plot extra, and lossmodels
integration via the splice extra.
The package covers threshold selection, GPD estimation, and the analytics built
on a fitted tail — return levels, exceedance probabilities, and excess-layer
charges — plus integration helpers for splicing an empirical body to a fitted
tail. It composes with lossmodels and the pooling primitives in actuarialpy.
Empirical tail measures follow the ecosystem VaR/TVaR estimators, and
simulation-backed quantities accept the shared rng argument — see
Conventions.
See the API reference below for the full surface; each object’s docstring carries its own usage.
Threshold selection¶
Scan candidate thresholds before committing to one. threshold_diagnostic_table
returns a ThresholdScan with the exceedance counts, GPD parameter estimates,
and mean excesses at each candidate; mean_excess returns the same diagnostics
for plotting (matplotlib via the plot extra):
import numpy as np
import extremeloss as xl
scan = xl.threshold_diagnostic_table(
losses, np.quantile(losses, [0.90, 0.925, 0.95, 0.975])
)
scan.thresholds, scan.n_exceedances, scan.xi, scan.beta, scan.mean_excess
Take the lowest threshold above which the shape estimate \(\hat\xi\) is stable and the mean-excess function is roughly linear — the classic peaks-over-threshold trade between bias (threshold too low) and variance (too few exceedances).
Fitting the tail¶
fit_pot(data, threshold) selects the exceedances of the threshold and fits
the GPD to their excesses; fit_gpd(excesses) is the same fit when the
excesses are already in hand:
fit = xl.fit_pot(losses, threshold=u)
fit.xi, fit.beta, fit.exceedance_fraction
# unconditional, ground-up tail metrics — the fit carries the exceedance rate
xl.gpd_var(0.995, fit.threshold, fit.xi, fit.beta, fit.exceedance_fraction)
xl.gpd_tvar(0.995, fit.threshold, fit.xi, fit.beta, fit.exceedance_fraction)
xl.return_level(200, fit) # the 1-in-200 claim == gpd_var(0.995, ...)
tail = xl.GPDTail.from_fit(fit) # conditional law on [u, inf), for splicing
GPDFit quotes unconditional quantities; GPDTail is the conditional
excess law a splice consumes. The distinction, and the \((\xi, \beta)\)
parameterization, are pinned in
Conventions. Sampling accepts the
shared rng argument.
Uncertainty and return levels¶
fit_gpd and fit_pot now populate GPDFit.covariance with the
observed-information covariance of (xi, beta) (None when the
information matrix is not positive definite — the MLE is irregular for
xi <= -1/2, and a covariance that means nothing is worse than none).
That uncertainty flows into the two places it matters most.
Threshold selection with error bands. The scan reports xi and the
modified scale beta* = beta - xi*u — the quantity that is actually
constant above a valid threshold (raw beta drifts linearly in u even
under a perfect GPD) — with standard errors, so the question becomes
“where do these flatten within their bands”:
scan = el.threshold_diagnostic_table(losses, thresholds)
# ... xi | xi_se | modified_scale | modified_scale_se | n_exceedances
Return levels with confidence intervals. The loss exceeded once per
T periods, with delta-method intervals over (zeta_u, xi, beta)
including the binomial variance of the exceedance rate (Coles §4.3.3):
el.gpd_return_level(fit, [10, 50, 200], observations_per_period=1200)
# return_period | return_level | se | ci_low | ci_high
Point estimates agree exactly with the scalar fit.return_level(n), which
remains the shorthand. A fitted tail also exposes sf and a closed-form
mean_excess, so it plugs directly into
ratingmodels.pooling_charge_from_severity.
The same treatment covers block maxima: fit_gev populates
GEVFit.covariance, and gev_return_level carries delta-method bands
(periods in blocks). Switching between the POT and block-maxima workflows
no longer changes how much uncertainty you get to see.
Did the fit succeed? qq_points / pp_points give the diagnostic
point sets headlessly, and parametric_bootstrap_gof tests the fit with
p-values that are honest about estimation – every bootstrap replicate is
refit before scoring, because comparing an estimated-parameter statistic
against the known-parameter null is anti-conservative:
el.parametric_bootstrap_gof(fit, losses, n_boot=500)
# {"ks": ..., "ks_pvalue": ..., "ad": ..., "ad_pvalue": ...}
With the plot extra, plot_gpd_diagnostics(fit, losses) and
plot_gev_diagnostics(fit, maxima) draw the Coles four-panel exhibit –
probability, quantile, return level with its band and empirical points,
density.
Splicing onto a fitted body¶
The handoff runs one direction: extremeloss fits the tail and returns a
lossmodels.SplicedSeverity, so every downstream consumer holds the same
severity class whether or not it carries an EVT tail:
sev = xl.splice_gpd_tail(body, fit) # weight from the fit
sev = xl.fit_spliced_gpd(body, losses, threshold=u) # weight from the data
Splicing is mass-matching, never density-continuity; pass weight= to
override the empirical body mass.
From simulated portfolios¶
A risksim.SimulationResult feeds straight back into the tail toolkit:
res = portfolio.simulate(100_000, contract=treaty, rng=7) # risksim
xl.tail_summary_from_risksim(res)
# n / mean / std / min / max and VaR/TVaR at (0.95, 0.99, 0.995)
API reference¶
- class BootstrapResult(estimate: float, bootstrap_estimates: ndarray, method: str = 'percentile', ci: tuple[float, float] | None = None, stderr: float | None = None, alpha: float | None = None)[source]¶
Bases:
objectBootstrap uncertainty summary for a scalar statistic.
- class GEVFit(xi: float, loc: float, scale: float, n_blocks: int, block_size: int | None = None, fit_method: str = 'mle', covariance: ndarray | None = None)[source]¶
Bases:
objectFitted generalized extreme value distribution for block maxima.
- property se¶
Standard errors of
(xi, loc, scale), orNone.
- class GPDFit(threshold: float, xi: float, beta: float, exceedance_fraction: float, n_exceedances: int, fit_method: str = 'mle', covariance: ndarray | None = None)[source]¶
Bases:
objectFitted generalized Pareto distribution above a threshold.
- mean_excess(d: float) float[source]¶
Mean excess
E[X - d | X > d]above the threshold, closed form.For the GPD, \(e(d) = (\beta + \xi\,(d - u)) / (1 - \xi)\) for \(d \ge u\) and \(\xi < 1\); infinite for \(\xi \ge 1\) (the tail has no mean). Below the threshold the GPD says nothing – a
ValueErrorrather than a silent extrapolation.
- property se¶
Standard errors of
(xi, beta), orNonewithout covariance.
- sf(x: float) float[source]¶
Unconditional survival
P(X > x); alias oftail_probability.Half of the small tail protocol (with
mean_excess()) consumed by e.g.ratingmodels.pooling_charge_from_severity.
- class GPDTail(threshold: float, xi: float, beta: float)[source]¶
Bases:
objectConditional generalized-Pareto tail on
[threshold, inf), for splicing.A thin distribution object wrapping
scipy.stats.genparetowith shapexi, scalebetaand locationthreshold. UnlikeGPDFit(which carries the exceedance rate and reports unconditional VaR/TVaR), this represents the tail conditional onX > threshold:cdf(threshold) == 0and the density integrates to one over[threshold, inf). It exposes thecdf/pdf/sample/quantile/mean/varianceinterface thatlossmodels.SplicedSeverityconsumes as a tail. Moments raise when they do not exist (xi >= 1for the mean,xi >= 1/2for the variance), mirroring heavy-tailed severities.
- class TailEstimateResult(estimate: float, method: str, stderr: float | None = None, ci: tuple[float, float] | None = None, n: int | None = None, effective_n: float | None = None, threshold: float | None = None, quantile: float | None = None, diagnostics: dict[str, ~typing.Any] = <factory>)[source]¶
Bases:
objectContainer for tail-estimation results.
- class ThresholdScan(thresholds: ndarray, mean_excess: ndarray, xi: ndarray, beta: ndarray, n_exceedances: ndarray, xi_se: ndarray | None = None, modified_scale: ndarray | None = None, modified_scale_se: ndarray | None = None)[source]¶
Bases:
objectThreshold-diagnostic results across a grid of thresholds.
modified_scaleis \(\beta^* = \beta - \xi u\): above any valid GPD threshold both \(\xi\) and \(\beta^*\) are constant inu, so the threshold-selection question is “where do these flatten within their confidence bands” – which is why the standard-error columns exist. Raw \(\beta\) drifts linearly inueven under a perfect GPD and diagnoses nothing.
- block_return_level(period: float, fit: GEVFit) float[source]¶
The
period-block GEV return level (the quantile at1 - 1/period).Thin wrapper over
GEVFit.return_level()with the domain check thatperiodexceeds one block. Periods are in blocks: with annual maxima,period=100is the 100-year level. For confidence intervals usegev_return_level().
- bootstrap_statistic(data, statistic, *, n_resamples: int = 1000, alpha: float = 0.05, random_state: int | Generator | None = None) BootstrapResult[source]¶
Nonparametric bootstrap of an arbitrary statistic, with a percentile CI.
Resamples
datawith replacementn_resamplestimes, evaluatesstatisticon each resample, and summarizes the bootstrap distribution with a point estimate (the statistic on the original sample), a percentile confidence interval, and a bootstrap standard error. The interval is the equal-tailed percentile interval with endpoints at thealpha/2and1 - alpha/2quantiles of the resampled statistics.- Parameters:
data (array-like) – The sample to resample.
statistic (callable) – A function mapping a 1-D array to a float, e.g.
np.meanor a tail measure. It is called once on the original data for the point estimate and once per resample.n_resamples (int, optional) – Number of bootstrap resamples (default 1000). Must be positive.
alpha (float, optional) – Significance level for the two-sided percentile interval (default 0.05, i.e. a 95% interval). Must lie in
(0, 1).random_state (int, numpy.random.Generator, or None, optional) – Seed or generator controlling the resampling. An existing
Generatoris used as given; anything else is passed tonumpy.random.default_rng(). Fix it for reproducible intervals.
- Returns:
Carries
estimate(statistic on the original sample),bootstrap_estimates(the array of resampled values),ci(the(low, high)percentile bounds),stderr(standard deviation of the resampled values,ddof=1),method("percentile"), andalpha.- Return type:
- Raises:
ValueError – If
n_resamplesis not positive oralphais not in(0, 1).
Notes
The percentile interval is simple and distribution-free but can under-cover for strongly skewed sampling distributions – the same caveat that applies to Wald tail intervals elsewhere in the package.
See also
bootstrap_varBootstrap CI for value-at-risk.
bootstrap_tvarBootstrap CI for tail value-at-risk.
bootstrap_tail_probabilityBootstrap CI for an exceedance probability.
- bootstrap_tail_probability(losses, threshold: float, **kwargs) BootstrapResult[source]¶
Bootstrap confidence interval for an exceedance probability.
Convenience wrapper over
bootstrap_statistic()with the statistic fixed to the empirical probability \(P(X > u)\) of exceedingthreshold.- Parameters:
losses (array-like) – Loss sample to resample.
threshold (float) – The level \(u\) whose exceedance probability is bootstrapped.
**kwargs – Forwarded to
bootstrap_statistic()(n_resamples,alpha,random_state).
- Returns:
As returned by
bootstrap_statistic(), for the exceedance probability.- Return type:
See also
bootstrap_statisticThe general routine this delegates to.
- bootstrap_tvar(losses, q: float, **kwargs) BootstrapResult[source]¶
Bootstrap confidence interval for tail value-at-risk.
Convenience wrapper over
bootstrap_statistic()with the statistic fixed to the empirical tail value-at-risk at levelq– the mean loss in the worst1 - qfraction of outcomes (also called CVaR or expected shortfall).- Parameters:
losses (array-like) – Loss sample to resample.
q (float) – TVaR level in
(0, 1), e.g.0.99for the 99% TVaR.**kwargs – Forwarded to
bootstrap_statistic()(n_resamples,alpha,random_state).
- Returns:
As returned by
bootstrap_statistic(), for the TVaR.- Return type:
See also
bootstrap_varBootstrap CI for the value-at-risk at the same level.
bootstrap_statisticThe general routine this delegates to.
- bootstrap_var(losses, q: float, **kwargs) BootstrapResult[source]¶
Bootstrap confidence interval for value-at-risk (a loss quantile).
Convenience wrapper over
bootstrap_statistic()with the statistic fixed to the empirical value-at-risk at levelq– theq-quantile of the loss distribution.- Parameters:
losses (array-like) – Loss sample to resample.
q (float) – VaR level in
(0, 1), e.g.0.99for the 99% VaR.**kwargs – Forwarded to
bootstrap_statistic()(n_resamples,alpha,random_state).
- Returns:
As returned by
bootstrap_statistic(), for the VaR.- Return type:
See also
bootstrap_tvarBootstrap CI for the tail value-at-risk at the same level.
bootstrap_statisticThe general routine this delegates to.
- component_tail_metrics(result, *, q: float = 0.99, threshold: float | None = None) dict[str, dict[str, float]][source]¶
Per-component empirical VaR/TVaR from a risksim result’s component losses.
Reads the
(n_sims, n_components)arrayresult.component_losses(names fromcomponent_nameswhen present) and returns, per component, the empirical VaR and TVaR at levelq, plus the exceedance probability ofthresholdwhen one is given. These are marginal, per-component metrics – diversified totals belong to the portfolio-level summary.- Returns:
{name: {"var", "tvar"[, "exceedance_probability"]}}.- Return type:
dict of str -> dict of str -> float
- effective_sample_size(weights) float[source]¶
Kish effective sample size of a set of importance weights.
\(\mathrm{ESS} = 1 / \sum_i \bar w_i^2\) for normalized weights \(\bar w_i\): equal to
nwhen all weights are equal, approaching one as a single weight dominates. The headline diagnostic for weight degeneracy – the importance-sampling standard errors in this module scale by \(\sqrt{\mathrm{ESS}}\), not \(\sqrt{n}\).
- empirical_tvar(losses, q)[source]¶
Empirical TVaR via the average-quantile (Acerbi-Tasche) plug-in.
Implements
TVaR_q = (1/(1-q)) * integral_q^1 VaR_u duexactly on the empirical distribution: with sorted losses andk = ceil(n*q),TVaR_q = [ sum_{i>k} x_(i) + x_(k) * (k - n*q) ] / (n * (1 - q)).
Correct in the presence of ties/atoms and always
>= empirical_var. Ecosystem-standard estimator shared withrisksimandlossmodels.qmay be scalar (returnsfloat) or array-like (returns array).
- empirical_var(losses, q)[source]¶
Empirical VaR: the order statistic
x_(ceil(n*q)).Implements
VaR_q = inf{x : F(x) >= q}on the empirical distribution (identical tonp.quantile(..., method="inverted_cdf")). This is the ecosystem-standard estimator shared withrisksimandlossmodels; it serves as the crude-Monte-Carlo baseline that the variance-reduced estimators in this subpackage are compared against.qmay be scalar (returnsfloat) or array-like (returns array).
- estimate_exceedance_curve_is(losses, weights, thresholds) dict[str, ndarray][source]¶
Weighted exceedance curve: self-normalized
P(X > u)over a threshold grid.The importance-sampling analogue of the empirical exceedance curve – each probability is the normalized-weight mass strictly above the threshold. Returns
{"thresholds", "probabilities"}as arrays. Point estimates only; for a standard error at a single threshold useestimate_tail_probability_is().
- estimate_mean_is(values, weights, *, alpha: float = 0.05) TailEstimateResult[source]¶
Self-normalized importance-sampling estimate of a mean, with a Wald CI.
\(\hat\mu = \sum_i \bar w_i x_i\) for normalized weights \(\bar w_i\). The standard error uses the weighted second moment about \(\hat\mu\) scaled by the effective sample size (Kish ESS), not
n– degenerate weights widen the interval as they should.- Parameters:
values (array-like) – Sampled values and their importance weights (normalization not required); equal lengths.
weights (array-like) – Sampled values and their importance weights (normalization not required); equal lengths.
alpha (float, optional) – Two-sided Wald level (default
0.05, a 95% interval).
- Returns:
estimate,stderr,ci,n,effective_n, and the weight diagnostics.- Return type:
- estimate_tail_probability(data, threshold: float, *, size: int | None = None, alpha: float = 0.05) TailEstimateResult[source]¶
Estimate P(X > threshold) from simulated or observed losses.
- estimate_tail_probability_cmc(conditional_probabilities, *, threshold: float | None = None, alpha: float = 0.05) TailEstimateResult[source]¶
Estimate an exceedance probability from conditional exceedance probabilities.
- Parameters:
conditional_probabilities – Samples of P(X > u | Y) from a conditioning variable Y.
threshold – Optional tail threshold associated with the conditional probabilities.
- estimate_tail_probability_is(losses, weights, threshold: float, *, alpha: float = 0.05) TailEstimateResult[source]¶
Self-normalized importance-sampling estimate of \(P(X > u)\), with a Wald CI.
The weighted exceedance-indicator mean \(\sum_i \bar w_i \, 1\{x_i > u\}\), with the standard error scaled by the effective sample size exactly as in
estimate_mean_is(). This is the payoff case for importance sampling: a proposal tilted into the tail makes rare exceedances common, so far fewer simulations are needed for a given precision. The raw exceedance count rides indiagnostics.- Parameters:
losses (array-like) – Sampled losses and their importance weights; equal lengths.
weights (array-like) – Sampled losses and their importance weights; equal lengths.
threshold (float) – The level \(u\) whose exceedance probability is estimated.
alpha (float, optional) – Two-sided Wald level (default
0.05).
- Returns:
estimate,stderr,ci,n,effective_n,threshold, and the weight diagnostics.- Return type:
- estimate_tvar(data, q: float, *, size: int | None = None, alpha: float = 0.05) TailEstimateResult[source]¶
Empirical tail value-at-risk with a normal-approximation confidence interval.
The ecosystem empirical TVaR at level
qwrapped in aTailEstimateResult. The standard error treats the observations at or above the empirical VaR as a sample and uses their standard deviation over \(\sqrt{n_{\text{tail}}}\) – a first-order approximation that ignores the variability of the VaR threshold itself, so read the interval as indicative when the tail sample is small.datamay be an array or a lossmodels-style model to sample (passsize); the tail sample size rides indiagnostics.
- estimate_tvar_cmc(conditional_tail_expectations, *, q: float, threshold: float | None = None, alpha: float = 0.05) TailEstimateResult[source]¶
Estimate TVaR from conditional expectations of tail losses.
conditional_tail_expectations should contain draws of E[X | X >= VaR_q, Y] or another conditionally unbiased TVaR contribution.
- estimate_tvar_is(losses, weights, q: float) TailEstimateResult[source]¶
Weighted TVaR under the ecosystem average-quantile convention.
Implements the weighted Acerbi-Tasche plug-in for
TVaR_q = (1/(1-q)) * integral_q^1 VaR_u du: with values sorted, weights normalized, cumulative weightsW_iandkthe weighted-VaR index,TVaR_q = [ sum_{i>k} w_i x_i + x_k (W_k - q) ] / (1 - q).
The atom at VaR contributes only the weight mass above level
q, which keeps the estimator coherent with ties and makes it reduce exactly toempirical_tvarwhen all weights are equal.
- estimate_var(data, q: float, *, size: int | None = None, alpha: float = 0.05) TailEstimateResult[source]¶
Empirical value-at-risk of simulated or observed losses, as a result object.
The ecosystem lower-quantile VaR wrapped in a
TailEstimateResultwithnand the quantile recorded.datamay be an array of losses or a lossmodels-style model to sample (passsize). No standard error is attached for the plain empirical quantile;alphais accepted for signature symmetry withestimate_tvar().
- estimate_var_is(losses, weights, q: float) TailEstimateResult[source]¶
Weighted value-at-risk: the
q-quantile under the importance weights.The weighted analogue of the ecosystem VaR convention \(\inf\{x : F(x) \ge q\}\): with values sorted and weights normalized, the first value whose cumulative weight reaches
q. Reduces exactly to the empirical VaR under equal weights. No standard error is attached (quantile standard errors under importance sampling require a density estimate); the effective sample size and weight diagnostics ride along.
- estimate_var_tvar_is(losses, weights, q: float) dict[str, TailEstimateResult][source]¶
Weighted VaR and TVaR at level
qin one call.Returns
{"var": estimate_var_is(...), "tvar": estimate_tvar_is(...)}– the pair share the sorting and weighting conventions, so the TVaR always sits at or above the VaR.
- exceedance_probability(losses, threshold: float) float[source]¶
Empirical exceedance probability: the fraction of losses strictly above
threshold.The plug-in estimator
mean(losses > threshold)forP(X > threshold). Strict inequality, matching the exceedance convention used across the package.
- extract_exceedances(data, threshold: float) ndarray[source]¶
Excesses of the data over a threshold (peaks-over-threshold data).
Returns the positive excesses \(X_i - u\) for every observation above the threshold \(u\) – the exceedance data on which a generalized Pareto tail is fitted. Note the return is excesses (measured from the threshold), not the raw exceeding values, matching the convention of the GPD fitters, which take excesses with location fixed at zero.
- Parameters:
data (array-like) – Observations to threshold.
threshold (float) – The threshold \(u\). Only strictly-exceeding observations (
x > threshold) contribute.
- Returns:
The excesses
x - thresholdfor allx > threshold, in the original data order.- Return type:
numpy.ndarray
- Raises:
ValueError – If
thresholdis invalid, or if no observation exceeds it (an empty exceedance set cannot support a tail fit).
See also
fit_gpdFit a GPD to a set of excesses.
- extreme_loss_summary(losses, *, thresholds=None, quantiles=(0.95, 0.99, 0.995)) dict[str, object][source]¶
One-call tail summary of a loss sample: moments, VaR/TVaR table, exceedances.
Returns
n/mean/std/min/maxplus avar_tvarrow per quantile – empirical VaR, TVaR, and their tail ratio, under the ecosystem estimators; passthresholdsto add the empiricalexceedance_curve. This is the summarytail_summary_from_risksim()produces for a simulation result.- Parameters:
losses (array-like) – The loss sample.
thresholds (array-like, optional) – Grid for the exceedance curve; omitted when
None.quantiles (tuple of float, optional) – Levels for the VaR/TVaR rows (default
(0.95, 0.99, 0.995)).
- Returns:
Summary statistics as above.
- Return type:
dict
- fit_block_maxima(data, block_size: int, method: str = 'mle', *, drop_last: bool = True) GEVFit[source]¶
Block the data and fit the GEV in one call.
Equivalent to
fit_gev(make_blocks(data, block_size, drop_last=drop_last), block_size=block_size); arguments as for those two functions.
- fit_gev(block_maxima, method: str = 'mle', *, block_size: int | None = None) GEVFit[source]¶
Fit a generalized extreme value distribution to block maxima.
Maximum-likelihood GEV fit in the package’s parameterization –
xipositive for heavy tails (SciPy’sgenextremeshape isc = -xi). The observed-information covariance of(xi, loc, scale)is attached when the information matrix is positive definite (Noneotherwise; the MLE is irregular for \(\xi \le -1/2\)).- Parameters:
block_maxima (array-like) – The per-block maxima (see
make_blocks()); at least two.method (str, optional) – Only
"mle"is currently supported.block_size (int, optional) – Recorded on the result for bookkeeping; not used by the fit.
- Returns:
Fitted
(xi, loc, scale)withn_blocksand, when available, the parametercovariance.- Return type:
See also
fit_block_maximaBlocking and fitting in one call.
gev_return_levelReturn levels with delta-method intervals.
- fit_gpd(excesses, threshold: float = 0.0, method: str = 'mle') GPDFit[source]¶
Fit a generalized Pareto distribution to excess losses.
- fit_pot(data, threshold: float, method: str = 'mle') GPDFit[source]¶
Peaks-over-threshold fit: a GPD for the excesses of
dataoverthreshold.Selects the observations strictly above the threshold \(u\), fits a generalized Pareto distribution to their excesses \(x - u\) by maximum likelihood (location fixed at zero), and returns a
GPDFitcarrying the empirical exceedance raten_exceedances / n– so the fit quotes unconditional, ground-up tail quantities (sf, VaR/TVaR, return levels) out of the box. The observed-information covariance of(xi, beta)is attached when the information matrix is positive definite (Noneotherwise; the MLE is irregular for \(\xi \le -1/2\)).- Parameters:
data (array-like) – Ground-up loss observations (the full sample, not pre-extracted excesses – for excesses already in hand use
fit_gpd()).threshold (float) – The POT threshold \(u\). Choose it with
threshold_diagnostic_table().method (str, optional) – Only
"mle"is currently supported.
- Returns:
Fitted
(xi, beta)abovethreshold, withexceedance_fraction,n_exceedances, and (when available) the parametercovariance.- Return type:
- Raises:
ValueError – If no observation exceeds the threshold, or
methodis not"mle".
See also
fit_gpdThe same fit when the excesses are already extracted.
threshold_diagnostic_tableScan candidate thresholds before committing.
- fit_pot_from_lossmodel(model, *, size: int, threshold: float)[source]¶
Sample a lossmodels-style severity and POT-fit its tail in one call.
Draws
sizelosses frommodel(anythingsample_lossmodel()accepts) and returnsfit_pot(losses, threshold=threshold)– how a fitted severity’s tail reads through the peaks-over-threshold lens.
- fit_spliced_gpd(body, data, *, threshold: float, weight: float | None = None)[source]¶
Fit a GPD tail above
threshold(peaks-over-threshold) and splice it ontobody, returning alossmodels.SplicedSeverity.- Parameters:
body (severity model) – Any fitted body severity (e.g. a
lossmodelsLognormal).data (array-like) – Loss sample used to fit the tail and, by default, to set the body mass.
threshold (float) – Peaks-over-threshold cutoff
u.weight (float, optional) – Body mass
P(X <= u). Defaults to1 - exceedance_fractionfrom the POT fit (the empirical fraction at or below the threshold), consistent with the fitted exceedance rate.package. (Requires the lossmodels)
- splice_gpd_tail(body, fit, *, weight: float | None = None)[source]¶
Splice an already-fitted GPD tail (a
GPDFit) ontobody.Returns a
lossmodels.SplicedSeveritywhose body isbody(any fitted body severity) and whose tail is the conditional GPD offitabove its threshold. The mixing weight defaults to the body mass implied by the fit,1 - fit.exceedance_fraction(i.e.P(X <= threshold)).
- gev_return_level(fit, return_periods, confidence_level: float = 0.95)[source]¶
Block-maxima return levels with confidence intervals.
The
T-block return level is the GEV quantile at1 - 1/T– identically whatGEVFit.return_level()computes for a single period. Confidence intervals are by the delta method over(xi, loc, scale)(Coles, 2001, section 3.3.3); they require the fit to carry a parametercovariance(populated byfit_gev()when the information matrix is positive definite). Periods are in blocks: with annual maxima,T = 100is the 100-year level.- Returns:
return_period,return_level,se,ci_low,ci_high(se/bounds arenanwithout a covariance).- Return type:
dict of str -> numpy.ndarray
- qq_points(fit, data) dict[str, ndarray][source]¶
Quantile-quantile point set for a fitted tail.
For a
GPDFit, empirical quantiles are the sorted losses above the threshold and theoretical quantiles are the fitted conditional GPD quantiles at the plotting positions(i - 0.5) / n(both in original loss units, threshold included). For aGEVFit, the block maxima against fitted GEV quantiles. A good fit puts the points on the 45-degree line – deviations in the upper corner are exactly where a tail model earns or loses its keep.- Returns:
theoretical,empirical(equal-length arrays),n.- Return type:
dict
- pp_points(fit, data) dict[str, ndarray][source]¶
Probability-probability point set: model cdf vs plotting positions.
Complements
qq_points(): PP is most sensitive in the body of the fitted range, QQ in the tail. Both on the unit square.
- parametric_bootstrap_gof(fit, data, n_boot: int = 500, rng=None) dict[source]¶
Goodness-of-fit test for a fitted GPD or GEV, done honestly.
Kolmogorov-Smirnov and Anderson-Darling statistics of the data against the fitted model, with p-values from a parametric bootstrap that refits inside every replicate (see the module docstring for why the refit is not optional). A-D weights the tails, K-S the body; report both, because a tail model can pass one and fail the other.
- Returns:
ks,ks_pvalue,ad,ad_pvalue,n,n_boot.- Return type:
dict
- gpd_return_level(fit, return_periods, observations_per_period: float = 1.0, confidence_level: float = 0.95)[source]¶
Return levels with confidence intervals from a POT/GPD fit.
The
T-period return level is the loss exceeded once perTperiods on average: with exceedance rate \(\zeta_u\) andmobservations per period, it solves \(P(X > r) = 1/(T\,m)\):\[r_T = u + \frac{\beta}{\xi}\left[(T\,m\,\zeta_u)^{\xi} - 1\right]\](\(u + \beta\log(T m \zeta_u)\) as \(\xi \to 0\)). Confidence intervals are by the delta method over \((\zeta_u, \xi, \beta)\), including the binomial variance of the exceedance rate (Coles, 2001, §4.3.3); they require the fit to carry a parameter
covariance(populated byfit_gpd()/fit_potwhen the information matrix is positive definite).- Parameters:
fit (GPDFit) – A fit whose
exceedance_fractionreflects the full dataset (i.e. fromfit_pot, not rawfit_gpdon excesses alone).return_periods (float or array-like) – Periods
Tin the same period unit asobservations_per_period.observations_per_period (float) – Observations per period (e.g. claims per year), so
T * observations_per_period * exceedance_fractionis the expected number of threshold exceedances inTperiods – it must exceed 1 for the return level to sit above the threshold.confidence_level (float) – Wald interval level.
- Returns:
return_period,return_level,se,ci_low,ci_high(se/bounds arenanwithout a covariance).- Return type:
dict of str -> numpy.ndarray
- gpd_tail_probability(x: float, threshold: float, xi: float, beta: float, exceedance_fraction: float) float[source]¶
Unconditional GPD tail probability \(P(X > x)\) above a POT threshold.
For \(x > u\), returns \(\zeta_u \, (1 + \xi (x - u)/\beta)^{-1/\xi}\) (exponential form as \(\xi \to 0\)), where \(\zeta_u\) is the exceedance rate; for \(x \le u\) it returns \(\zeta_u\) itself – the GPD says nothing below its threshold. Zero beyond the finite upper endpoint when \(\xi < 0\).
- Parameters:
x (float) – The loss level.
threshold (float) – POT threshold \(u\) and the fitted GPD shape and scale.
xi (float) – POT threshold \(u\) and the fitted GPD shape and scale.
beta (float) – POT threshold \(u\) and the fitted GPD shape and scale.
exceedance_fraction (float) – The exceedance rate \(\zeta_u = P(X > u)\), e.g.
GPDFit.exceedance_fraction.
- Returns:
Ground-up (unconditional) \(P(X > x)\).
- Return type:
float
- gpd_tvar(p: float, threshold: float, xi: float, beta: float, exceedance_fraction: float) float[source]¶
Unconditional GPD tail value-at-risk (expected shortfall) at level
p.Closed form on top of
gpd_var():\[\mathrm{TVaR}_p = \frac{\mathrm{VaR}_p + \beta - \xi u}{1 - \xi}, \qquad \xi < 1.\]Infinite for \(\xi \ge 1\) (the tail has no mean) – a
ValueErrorrather than a silentinf. Arguments as forgpd_var().
- gpd_var(p: float, threshold: float, xi: float, beta: float, exceedance_fraction: float) float[source]¶
Unconditional GPD value-at-risk: the
p-quantile of the ground-up loss.Inverts the POT tail: with exceedance rate \(\zeta_u\),
\[\mathrm{VaR}_p = u + \frac{\beta}{\xi} \left[\left(\frac{1 - p}{\zeta_u}\right)^{-\xi} - 1\right]\](\(u + \beta \log(\zeta_u / (1 - p))\) as \(\xi \to 0\)). Valid only when the quantile lands in the fitted tail, i.e. \(1 - p < \zeta_u\); otherwise a
ValueError– below the threshold the GPD has nothing to say.- Parameters:
p (float) – Quantile level in
(0, 1), e.g.0.995.threshold (float) – POT threshold \(u\) and the fitted GPD shape and scale.
xi (float) – POT threshold \(u\) and the fitted GPD shape and scale.
beta (float) – POT threshold \(u\) and the fitted GPD shape and scale.
exceedance_fraction (float) – The exceedance rate \(\zeta_u\), e.g.
GPDFit.exceedance_fraction.
- Returns:
The ground-up
p-quantile.- Return type:
float
See also
gpd_tvarThe matching expected shortfall.
gpd_return_levelReturn levels with delta-method intervals.
- hill_curve(data, k_grid=None) dict[str, ndarray][source]¶
Hill tail-index estimate across a grid of
k, for a Hill plot.Evaluates
hill_estimator()at eachkink_grid. Plotting the returnedhillvalues againstkproduces the standard Hill plot; the tail index is read from a region where the estimate is roughly flat, balancing the variance of smallkagainst the bias of largek.- Parameters:
data (array-like) – Strictly positive observations.
k_grid (array-like of int, optional) – Values of
kat which to evaluate the estimator. WhenNone(the default), uses1, 2, ..., max(2, len(data) // 4)so the grid stays within the upper quarter of the sample.
- Returns:
k– the grid of order-statistic counts used, andhill– the corresponding Hill estimates, aligned elementwise.- Return type:
dict of str -> numpy.ndarray
- Raises:
ValueError – If
datacontains a non-positive value, or if anykin the grid violates1 <= k < len(data).
See also
hill_estimatorThe per-
kestimator evaluated here.
- hill_estimator(data, k: int) float[source]¶
Hill estimator of the tail index from the
klargest observations.For positive data with an approximately Pareto upper tail, the Hill estimator of the tail index \(\gamma = 1/\alpha\) (equivalently the shape parameter \(\xi\) of the corresponding GPD) is the mean log spacing of the
klargest order statistics above the(k+1)-th:\[\hat{\gamma}_k = \frac{1}{k} \sum_{i=1}^{k} \bigl(\log X_{(n-i+1)} - \log X_{(n-k)}\bigr)\]where \(X_{(1)} \le \dots \le X_{(n)}\) are the sorted values. The estimate is sensitive to the choice of
k: smallkgives high variance, largekintroduces bias by reaching into the distribution body. Sweepkwithhill_curve()and read the tail index from a stable region of the resulting plot.- Parameters:
data (array-like) – Strictly positive observations. Order is irrelevant; the values are sorted internally.
k (int) – Number of upper order statistics used, satisfying
1 <= k < len(data).
- Returns:
The Hill tail-index estimate \(\hat{\gamma}_k\).
- Return type:
float
- Raises:
ValueError – If
datacontains a non-positive value, or ifkis outside1 <= k < len(data).
See also
hill_curveHill estimate across a grid of
k.pickands_estimatorAlternative tail-index estimator valid for any real tail index.
- importance_sampling_diagnostics(weights) dict[str, float][source]¶
Weight-degeneracy diagnostics for an importance sample.
Normalizes the weights and returns
effective_n(Kish ESS),max_weight/min_weight,coefficient_of_variation, andentropy(natural log). A max weight near one, or an ESS far belown, says the proposal is missing the target’s mass and the estimates carry more uncertainty than their nominalnsuggests. These diagnostics ride along on everyestimate_*_isresult.
- layer_tail_metrics(result, *, q: float = 0.99, threshold: float | None = None) dict[str, dict[str, float]][source]¶
Per-layer empirical VaR/TVaR from a risksim result’s layer losses.
The layer analogue of
component_tail_metrics(): reads the(n_sims, n_layers)arrayresult.layer_losses(names fromlayer_nameswhen present) and returns, per layer, the empirical VaR and TVaR at levelq, plus the exceedance probability ofthresholdwhen one is given.- Returns:
{name: {"var", "tvar"[, "exceedance_probability"]}}.- Return type:
dict of str -> dict of str -> float
- log_importance_weights(log_target_density, log_proposal_density, *, normalize: bool = True) ndarray[source]¶
Importance weights from log-densities, computed stably in log space.
\(w_i \propto \exp(\log f(x_i) - \log g(x_i))\) for target \(f\) and proposal \(g\). With
normalize=True(default) the weights are self-normalized vialogsumexp– the numerically safe route when the densities span many orders of magnitude, exactly the regime importance sampling is used for. Withnormalize=Falsethe raw (exponentiated) ratios are returned.- Parameters:
log_target_density (array-like) – Log-densities of the two distributions at the sampled points; equal lengths.
log_proposal_density (array-like) – Log-densities of the two distributions at the sampled points; equal lengths.
normalize (bool, optional) – Self-normalize the weights to sum to one (default True).
- Returns:
The importance weights.
- Return type:
numpy.ndarray
- losses_from_risksim(result, *, view: str = 'losses') ndarray[source]¶
Extract a 1-D loss array from a risksim-style simulation result.
Accepts any object exposing the requested attribute –
viewmay be"losses","gross"/"gross_losses","retained"/"retained_losses", or"ceded"/"ceded_losses"– and returns it as a float array. Duck-typed: nothing risksim-specific is required beyond the attribute. RaisesValueErrorfor an unknown view or one that isNoneon this result,TypeErrorif the attribute is absent.
- make_blocks(data, block_size: int, *, drop_last: bool = True) ndarray[source]¶
Block maxima: the maximum of each consecutive
block_sizeobservations.Partitions the data, in the given order, into consecutive blocks and returns each block’s maximum – the sample a GEV fit consumes. With
drop_last=True(default) a trailing partial block is discarded, so every maximum comes from a full block;drop_last=Falsekeeps the partial block’s maximum.- Parameters:
data (array-like) – Observations, in block order (e.g. chronological).
block_size (int) – Observations per block.
drop_last (bool, optional) – Whether to drop a trailing partial block (default True).
- Returns:
The block maxima.
- Return type:
numpy.ndarray
- Raises:
ValueError – If
block_sizeexceeds the data length, or fewer than two blocks result (a GEV fit needs at least two maxima).
See also
fit_block_maximaBlocking and fitting in one call.
- mean_excess(data, thresholds) dict[str, ndarray][source]¶
Empirical mean-excess function \(e(u) = E[X - u \mid X > u]\) on a grid.
For each candidate threshold, the average excess of the strictly-exceeding observations, with the exceedance counts alongside (
nanwhere nothing exceeds). Linearity of \(e(u)\) in \(u\) is the classic peaks-over-threshold diagnostic: above any valid GPD threshold the mean excess is linear with slope \(\xi / (1 - \xi)\).- Parameters:
data (array-like) – Loss observations.
thresholds (array-like) – Candidate thresholds \(u\).
- Returns:
thresholds,mean_excess,n_exceedances. With theplotextra, feed this toplot_mean_excess.- Return type:
dict of str -> numpy.ndarray
See also
threshold_diagnostic_tableThe full scan, with GPD fits and error bands.
- pickands_estimator(data, k: int) float[source]¶
Pickands estimator of the tail index from ordered tail spacings.
Unlike the Hill estimator, the Pickands estimator is valid for any real tail index \(\gamma\) (light, heavy, or bounded tails) and requires no positivity of the data beyond the internal ordering. Using the sorted values \(X_{(1)} \le \dots \le X_{(n)}\), it compares spacings at the
k-th,2k-th, and4k-th largest observations:\[\hat{\gamma}_k = \frac{1}{\log 2}\, \log\!\left( \frac{X_{(n-k+1)} - X_{(n-2k+1)}}{X_{(n-2k+1)} - X_{(n-4k+1)}} \right)\]As with any tail-index estimator the result depends on
k; it is typically read from a stable region of a plot overk.- Parameters:
data (array-like) – Strictly positive observations. Order is irrelevant; the values are sorted internally.
k (int) – Order-statistic spacing parameter, satisfying
4k < len(data) + 1so that the4k-th largest observation exists.
- Returns:
The Pickands tail-index estimate \(\hat{\gamma}_k\).
- Return type:
float
- Raises:
ValueError – If
datacontains a non-positive value, ifkviolates4k < len(data) + 1, or if the ordered tail spacings are not both strictly positive (which can occur with ties or a short tail).
See also
hill_estimatorLog-spacing estimator for heavy (positive-index) tails.
- return_level(period: float, fit: GPDFit) float[source]¶
The loss exceeded on average once per
periodobservations, under a POT fit.Thin wrapper over
GPDFit.return_level()– the fit’s unconditional quantile at1 - 1/period– with the domain check thatperiodexceeds one. Point estimates agree exactly withgpd_return_level(), which adds period units (observations_per_period) and delta-method confidence intervals.
- return_period(probability: float) float[source]¶
The return period
1 / pof an event with exceedance probabilityp.The reciprocal convention: an event with per-observation exceedance probability
precurs once per1/pobservations on average. RaisesValueErroroutside0 < p < 1.
- sample_lossmodel(model, size: int) ndarray[source]¶
Sample losses from a lossmodels-style severity or aggregate model.
- stabilize_weights(weights, *, clip_quantile: float | None = None, renormalize: bool = True) ndarray[source]¶
Clip extreme importance weights at an upper quantile, then renormalize.
With
clip_quantile=c, weights are capped at their ownc-quantile – the standard variance-for-bias trade when a few weights dominate the sample;renormalize=True(default) rescales to sum to one afterwards. Withclip_quantile=Nonethis only (optionally) normalizes.- Parameters:
weights (array-like) – Nonnegative importance weights (need not be normalized).
clip_quantile (float, optional) – Cap level in
(0, 1];Nonedisables clipping.renormalize (bool, optional) – Rescale to sum to one after clipping (default True).
- Returns:
The stabilized weights.
- Return type:
numpy.ndarray
See also
importance_sampling_diagnosticsCheck whether stabilization is needed.
- tail_summary_from_risksim(result, *, view: str = 'losses', thresholds=None, quantiles=(0.95, 0.99, 0.995)) dict[str, object][source]¶
Tail summary of a risksim simulation result: extract the view, then summarize.
extreme_loss_summary(losses_from_risksim(result, view=view), ...)in one call:n/mean/std/min/max, empirical VaR/TVaR at each quantile, and the exceedance curve whenthresholdsis given.
- threshold_diagnostic_table(data, thresholds) ThresholdScan[source]¶
Scan candidate POT thresholds: mean excess, GPD fits, and error bands.
For each candidate \(u\) with at least five exceedances, records the exceedance count, the empirical mean excess, the fitted GPD
(xi, beta)(viafit_pot()), and the modified scale \(\beta^* = \beta - \xi u\) with delta-method standard errors from the fit covariance (gradient \((-u, 1)\) over \((\xi, \beta)\)). Above any valid threshold both \(\xi\) and \(\beta^*\) are constant in \(u\) – raw \(\beta\) drifts linearly even under a perfect GPD – so the selection question is where the two flatten within their bands. Candidates with fewer than five exceedances yieldnanrows.- Parameters:
data (array-like) – Ground-up loss observations.
thresholds (array-like) – Candidate thresholds \(u\).
- Returns:
Arrays over the grid:
thresholds,mean_excess,xi,beta,n_exceedances,xi_se,modified_scale,modified_scale_se.- Return type:
Fitting from an Experience¶
extremeloss.integrations.actuarialpy fits GPD tails straight from a
claims-listing Experience (or an ExperienceSet):
fit_gpd_from_experience(exp, threshold=...) – extracting the excesses is
structural; selecting the threshold stays the caller’s judgment. Aggregated
experience tabs are refused. The core package stays array-level; install
the [actuarialpy] extra or the openactuarial meta-package.