mixle.inference.risk module¶
Risk / tail metrics over a Monte-Carlo outcome distribution (e.g. J2’s NPV samples).
A distribution’s mean says nothing about how bad the bad outcomes are. This module turns a plain
sample array – typically NPVDistribution’s samples, but any
array of scalar outcomes works – into the two standard tail-risk summaries plus a scenario ranking:
value_at_risk()– the loss not exceeded with probabilityalpha(a quantile).
conditional_value_at_risk()– the expected loss given that the VaR threshold is breached (expected shortfall); always at least as large as VaR. A Generalized Pareto tail extrapolation is available by OPT-IN only (gpd_tail=True): measured on sparse tails it was strictly noisier than the raw tail mean it replaced (audit R-1), so sparse tails default to the honest sample statistic.
stress_rank()– named stress scenarios (low-grade, price-crash, carbon-spike, …) ranked from worst to least-bad loss.
Throughout, loss is -outcome – a positive loss means a bad (low/negative NPV) draw, so VaR and
CVaR come back as positive numbers when the distribution has meaningful downside.
- value_at_risk(samples, alpha=0.95)[source]
Value-at-Risk at confidence
alpha.VaR_alpha = -quantile(samples, 1 - alpha): losses are-outcome, so the(1-alpha)lower tail of the outcome distribution (rare, bad draws) becomes the loss exceeded only(1-alpha)of the time.
- conditional_value_at_risk(samples, alpha=0.95, *, min_tail=20, gpd_tail=False)[source]
Conditional Value-at-Risk (expected shortfall) at confidence
alpha.The empirical estimator is the mass-weighted mean over the worst
1 - alphaprobability mass (NOT the docstring formula-mean(samples <= -VaR), which overweights observations tied at VaR – audit R-3 pinned the mismatch between the stated and computed estimator). Because the tail mean is at least as extreme as the threshold bounding it,CVaR >= VaR.gpd_tail=Trueopts in to a Generalized Pareto refinement of a sparse tail (fewer thanmin_tailexceedances). It is OFF by default because it is measurably WORSE exactly where it fires (audit R-1): fitting a two-parameter heavy-tail MLE to the same 5-19 points it is meant to rescue, then plugging the estimates intoVaR + scale/(1 - shape), multiplied the estimator’s spread instead of shrinking it – the estimand of that measurement is the estimator’s own sampling uncertainty: on lognormal losses at n = 100 (true ES 8.54), the raw tail mean’s sampling sd was 2.36 while the GPD path’s was 46.4 with a worst case of 663. Use the refinement only with an exogenous reason to trust a GPD tail (e.g. a threshold chosen from much more data), and treat its output as a model extrapolation, not a sample statistic; its parameters are plug-in MLEs with no interval attached (audit R-2).- Parameters:
- Returns:
The CVaR as a loss; always
>= value_at_risk(samples, alpha).- Return type:
- stress_rank(scenarios)[source]
Rank named stress scenarios (e.g. low-grade, price-crash, carbon-spike) by loss.
Each scenario’s value may be a scalar outcome (e.g. a single stressed NPV) or an array of outcomes (e.g. NPV samples drawn under that stress); the ranking key is
-mean(value)either way, so a bare float and a 1-sample array behave identically.