Class ExtremeValueTheory

java.lang.Object
com.quantfinlib.risk.ExtremeValueTheory

public final class ExtremeValueTheory extends Object
Extreme value theory via peaks-over-threshold — the statistically principled way to ask about quantiles beyond the sample. Historical VaR at 99.9% from 500 observations is reading the worst half-observation; EVT instead fits the Generalized Pareto Distribution to the exceedances over a high threshold (the Pickands-Balkema-de Haan theorem says the tail of any well-behaved distribution converges to a GPD), then extrapolates along the fitted tail:
  VaR_p = u + (β/ξ)·[((n/Nᵤ)(1−p))^{−ξ} − 1]

The shape ξ is the number to stare at: ξ ≈ 0 is an exponential tail (Gaussian-ish), ξ > 0 is a power-law tail (fat; equity returns typically fit ξ ≈ 0.2-0.4), and ξ ≥ 1 means the tail mean does not even exist (expectedShortfall refuses rather than returning a finite lie). fitPot(double[], double) uses probability-weighted moments (Hosking and Wallis 1987): closed form, good for ξ < 0.5 but biased and inefficient beyond. fitPotMle(double[], double) maximises the GPD likelihood through Grimshaw's (1993, Technometrics 35, 185-191) one-dimensional profile in θ = ξ/β and reports the asymptotic standard errors of Smith (1987, Ann. Statist. 15, 1174-1207), valid for ξ > −0.5. meanExcess(double[], double[]) gives the mean-excess function used to choose the threshold (linear in u above a valid threshold). The threshold choice is the caller's judgment call — the classic diagnostic is fitting at several thresholds and checking ξ stability; a quantile between 0.90 and 0.95 of the losses is the usual start. Research lane, deterministic.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static final record 
    A fitted POT tail model.
    static final record 
    A maximum-likelihood GPD fit with asymptotic standard errors Var ξ̂ = (1+ξ)²/m, Var β̂ = 2β²(1+ξ)/m (Smith 1987).
  • Method Summary

    Modifier and Type
    Method
    Description
    fitPot(double[] losses, double thresholdQuantile)
    Fits a GPD to the losses exceeding the thresholdQuantile of the sample (e.g. 0.90), via probability-weighted moments.
    fitPotMle(double[] losses, double thresholdQuantile)
    Maximum-likelihood GPD fit to the exceedances over the thresholdQuantile of the sample.
    static double
    gpdLogLikelihood(double[] y, double shape, double scale)
    GPD log-likelihood of exceedances y at (ξ, β); −∞ outside the support.
    static double[]
    meanExcess(double[] losses, double[] thresholds)
    Empirical mean-excess function e(u) = mean(L − u | L > u) at each threshold (NaN where no loss exceeds u).

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • fitPot

      public static ExtremeValueTheory.GpdFit fitPot(double[] losses, double thresholdQuantile)
      Fits a GPD to the losses exceeding the thresholdQuantile of the sample (e.g. 0.90), via probability-weighted moments. Losses are positive numbers (feed -returns or a loss series directly).
    • fitPotMle

      public static ExtremeValueTheory.GpdMle fitPotMle(double[] losses, double thresholdQuantile)
      Maximum-likelihood GPD fit to the exceedances over the thresholdQuantile of the sample. The log-likelihood of exceedances y is −m·ln β − (1 + 1/ξ)·Σ ln(1 + ξ·y/β); with θ = ξ/β the maximising ξ for fixed θ is (1/m)·Σ ln(1 + θ·y) and the profile −m·ln(ξ(θ)/θ) − m·(1 + ξ(θ)) is maximised over θ > −1/max(y) by a grid scan followed by golden-section search.
    • gpdLogLikelihood

      public static double gpdLogLikelihood(double[] y, double shape, double scale)
      GPD log-likelihood of exceedances y at (ξ, β); −∞ outside the support.
    • meanExcess

      public static double[] meanExcess(double[] losses, double[] thresholds)
      Empirical mean-excess function e(u) = mean(L − u | L > u) at each threshold (NaN where no loss exceeds u). For a GPD tail it is linear in u with slope ξ/(1−ξ); the threshold should be chosen where the plot becomes linear.