Portfolio & Market Risk

VaR and Expected Shortfall Calculator

Value at Risk (VaR) is a loss threshold at your chosen confidence level; Expected Shortfall (ES) is the average loss in the worst tail. Compare delta-normal and delta-gamma VaR with empirical VaR and ES from simulated daily P&L.

How to use this VaR / ES calculator

Set the three factor sensitivities, daily volatilities and correlations, choose a confidence level, then run the Java calculation. The model uses equity, a 5-year rate and EURUSD factors with a fixed gamma matrix visible in the source.

MethodWhat the result means
Delta-normal VaRA linear portfolio approximation with jointly Gaussian factor moves.
Delta-gamma VaRA quadratic approximation with a Cornish-Fisher correction for skewness and kurtosis.
Empirical VaR / ESA loss quantile and tail average from the seeded simulated quadratic P&L sample.

Example: 99% VaR versus ES

If one-day 99% VaR is 100,000 and ES is 150,000 in your reporting currency, the model places about 1% of daily losses beyond 100,000; losses in that worst 1% average 150,000. VaR is a threshold, not a maximum possible loss. These are illustrative numbers, not precomputed results for the inputs below.

Run the defaults, then increase confidence or equity volatility and rerun. Compare the two approximations with the empirical tail. With 4,000 observations at 99% confidence, the worst 1% contains only about 40 observations, so changing the seed can noticeably change ES.

The empirical sample is simulated, not an uploaded market history. All three routes share a Gaussian-factor model; their agreement does not validate real-market tails. See Expected Shortfall and Beyond for the risk-measure distinction.

Sensitivities (dP/dx per risk factor)
Daily volatility
CorrelationOptional
VaR settingsOptional

Historical losses are simulated from the same quadratic P&L model with Java's seeded random generator.

Java source
VarEsRiskStudio.java

This exact source runs in TeaVM. Form changes update its Java literals and reset manual edits.

import com.nablatensor.risk.PnlVector;
import com.nablatensor.risk.ValueAtRisk;
import java.util.Random;

public final class VarEsRiskStudio {
  private static final double[][] GAMMA = {
    {
      -9.0e6, 0, 0
    }, {
      0, -4.0e8, 0
    }, {
      0, 0, -1.5e6
    }
  };
  private VarEsRiskStudio() {}

  public static void main(String[] args) {
    double[] delta = {
      2400000, -18000000, 1100000
    };
    double[] vol = {
      1.1 / 100.0, 0.017 / 100.0, 0.5 / 100.0
    };
    double[][] corr = {
      {
        1.0, -0.15, 0.25
      }, {
        -0.15, 1.0, -0.1
      }, {
        0.25, -0.1, 1.0
      }
    };
    double[][] cov = new double[3][3];
    for (int a = 0; a < 3; a++) for (int b = 0; b < 3; b++) cov[a][b] = corr[a][b] * vol[a] * vol[b];
    double alpha = 99 / 100.0;
    double dn1 = ValueAtRisk.deltaNormal(delta, cov, alpha, 1.0), dn10 = ValueAtRisk.deltaNormal(delta,
        cov, alpha, 10.0);
    double dg1 = ValueAtRisk.deltaGammaCornishFisher(delta, GAMMA, cov, alpha, 1.0);
    var cumulants = ValueAtRisk.quadraticCumulants(delta, GAMMA, cov);
    PnlVector sample = simulate(4000, 42L, delta, cov);
    double hvar = ValueAtRisk.historical(sample, alpha), hes = ValueAtRisk.expectedShortfall(sample,
        alpha);
    System.out.println("RESULT|" + dn1 + "|" + dn10 + "|" + dg1 + "|" + cumulants.skewness() + "|"
        + cumulants.excessKurtosis() + "|" + hvar + "|" + hes);
  }

  private static PnlVector simulate(int n, long seed, double[] delta, double[][] cov) {
    double[][] l = new double[3][3];
    for (int a = 0; a < 3; a++) for (int b = 0; b <= a; b++) {
      double q = cov[a][b];
      for (int k = 0; k < b; k++) q -= l[a][k] * l[b][k];
      l[a][b] = a == b ? Math.sqrt(q) : q / l[b][b];
    }
    Random rng = new Random(seed);
    double[] pnl = new double[n];
    for (int t = 0; t < n; t++) {
      double[] z = {
        rng.nextGaussian(), rng.nextGaussian(), rng.nextGaussian()
      }, x = new double[3];
      for (int a = 0; a < 3; a++) for (int b = 0; b <= a; b++) x[a] += l[a][b] * z[b];
      double linear = 0, quadratic = 0;
      for (int a = 0; a < 3; a++) {
        linear += delta[a] * x[a];
        for (int b = 0; b < 3; b++) quadratic += 0.5 * GAMMA[a][b] * x[a] * x[b];
      }
      pnl[t] = linear + quadratic;
    }
    return new PnlVector(pnl);
  }
}
TeaVM compiles and runs the Java source above in this browser.
Implementation guide

Loss quantiles and tail averages

VaR answers a quantile question; expected shortfall answers the severity question beyond that quantile.

Core mechanism

This calculator compares a linear delta-normal approximation, a quadratic delta-gamma Cornish-Fisher approximation, and empirical quantiles of a seeded simulated quadratic P&L sample. Expected shortfall averages the sample tail losses. The empirical route does not use observed market history.

Practical workflow

Set horizon, confidence level, P&amp;L definition and data-cleaning policy; compare approaches; then test stability and explain differences in tails, correlations and distribution assumptions.

Key details

*Keywords: value at risk java, expected shortfall java, delta normal var java, delta gamma cornish fisher java, historical simulation var java, var backtest kupiec christoffersen java*

Feature F3. The pieces were already in the box — a scenario DSL that moves a compiled kernel and re-prices, and an adjoint sweep that returns the sensitivity vector — so this is the thin estimator and backtest layer that turns them into VaR / ES numbers.

Every figure is a positive loss at confidence alpha (e.g. 0.99). Multi-day numbers scale the one-day standard deviation by sqrt(horizonDays).

quadraticCumulants(delta, gamma, sigma) diagonalises Sigma^{1/2} Gamma Sigma^{1/2} (reusing the Jacobi eigensolver from F4's Pca), which turns the quadratic form into a sum of independent a_i y_i + 0.5 b_i y_i^2 terms. The first four cumulants then have closed forms, and the loss quantile comes from a fourth-order Cornish-Fisher expansion. With Gamma = 0 the skew and kurtosis vanish and the result is identical to deltaNormal — a test pins that.

The chi-square reference distributions for one and two degrees of freedom have closed-form survival functions (2 (1 - Phi(sqrt s)) and exp(-s/2)), so there is no incomplete-gamma dependency.

Scope and review point

The three methods are illustrative alternatives, not interchangeable production standards. Data history, liquidity, non-linearity and stressed periods matter materially.