Home / Tools / Value at Risk (VaR) calculator
Value at Risk (VaR) calculator
By Sitraka Forler · Lecturer, Durham Business SchoolUpdated 16 October 2026 About this site
Value at Risk is the loss a position should not exceed on all but the worst (1 − α) share of days. Paste a history of daily returns to get it two ways, from the returns themselves (historical) and from a normal distribution fitted to them (parametric), with the expected shortfall beside each, at the confidence level and horizon you choose.
Free, no sign-up. Everything is computed in your browser: nothing you type is sent anywhere. Educational tool, not investment advice.
1. Calculator
Paste a column of simple returns, oldest first. Commas, spaces or new lines all work. Use 250 days or more for a real estimate.
Above 1 day, both VaRs scale with √days.
Any currency; the money figures come out in the same one.
| Measure | Value | Unit |
|---|---|---|
| Historical VaR | 2.625 | % of position |
| in money | 26,250 | currency units |
| Parametric (normal) VaR | 2.127 | % of position |
| in money | 21,272 | currency units |
| Historical expected shortfall | 3.100 | % of position |
| in money | 31,000 | currency units |
| Parametric expected shortfall | 2.637 | % of position |
| in money | 26,371 | currency units |
| Mean daily return | −0.120 | % |
| Daily volatility (sample) | 1.220 | % |
| z-score at 95% | −1.6449 | standard deviations |
Only 1 of your 20 returns lies in the 5.0% tail, so the historical figures rest on one or two points. Paste a longer history before relying on them.
Historical VaR is well above the normal one: your returns have a fatter left tail than a normal distribution with the same mean and volatility.
2. The formulas
VaR_hist = −q_(1−α)(r) × √h
VaR_norm = −(μ·h + z_(1−α) · σ · √h)
ES_hist = −mean(r | r ≤ q_(1−α)) × √h ES_norm = −(μ·h − σ·√h · φ(z_(1−α)) / (1 − α))
q is the quantile with linear interpolation between sorted returns, the default of numpy.percentile and pandas .quantile(). z is the standard normal quantile (−1.6449 at 95%, −2.3263 at 99%) and φ the normal density. Losses are reported as positive numbers, as risk reports quote them.
Above one day, both VaRs follow the square-root-of-time rule, which assumes independent days. It is the convention regulators allowed for scaling one-day VaR to ten days, and it understates risk when volatility clusters. Historical VaR reads the tail you actually had; parametric VaR assumes it is normal, which usually makes it too thin. The VaR page has an interactive chart of the tail.
3. Worked example
- Take 20 daily returns (the calculator's example) and a €1,000,000 position at 95%. Sorted, the two worst days are −3.1% and −2.6%.
- Historical: the 5th percentile sits at rank (20 − 1) × 0.05 = 0.95, that is 95% of the way from the worst return to the second worst: −3.1 + 0.95 × (−2.6 + 3.1) = −3.1 + 0.475 = −2.625%. VaR = 2.625%, or €26,250.
- Parametric: the returns sum to −2.4%, so μ = −0.12% a day, and their sample standard deviation is σ = 1.220267%.
- With z = −1.644854: μ + zσ = −0.0012 − 1.644854 × 0.01220267 = −0.0012 − 0.0200716 = −0.0212716. VaR = 2.1272%, or €21,272.
- Expected shortfall: only one return, −3.1%, lies at or below the −2.625% cut-off, so historical ES = 3.1% (€31,000). Under the normal, φ(1.644854) / 0.05 = 0.103136 / 0.05 = 2.062713, and ES = −(−0.0012 − 0.01220267 × 2.062713) = 0.0263706, or 2.6371%.
- Over 10 days: historical 2.625% × √10 = 2.625% × 3.162278 = 8.3010%; parametric −(−0.012 − 1.644854 × 0.01220267 × 3.162278) = 0.012 + 0.063472 = 7.5472%.
Historical VaR (2.625%) is above the normal one (2.127%) because the worst day, −3.1%, is 2.44 standard deviations below the mean, while the lowest of 20 normal draws averages about 1.87. With 20 days the whole historical tail is one or two observations: use 250 days or more for a figure you would report.
4. The Python behind it
import numpy as np
from scipy.stats import norm
r = np.array([0.8, -1.2, 0.3, -0.4, 1.1, -2.6, 0.5, 0.2, -0.9, 1.4,
-0.1, 0.6, -3.1, 0.9, -0.7, 0.4, 1.0, -1.5, 0.2, 0.7]) / 100
alpha, h = 0.95, 1 # confidence level, horizon in days
q = np.percentile(r, 100 * (1 - alpha)) # linear interpolation, numpy's default
var_hist = -q * np.sqrt(h)
es_hist = -r[r <= q].mean() * np.sqrt(h)
mu, sigma = r.mean(), r.std(ddof=1)
z = norm.ppf(1 - alpha) # -1.6449 at 95%
var_param = -(mu * h + z * sigma * np.sqrt(h))
es_param = -(mu * h - sigma * np.sqrt(h) * norm.pdf(z) / (1 - alpha))
print(f"Historical VaR {var_hist:.4%}, ES {es_hist:.4%}") # 2.6250%, 3.1000%
print(f"Parametric VaR {var_param:.4%}, ES {es_param:.4%}") # 2.1272%, 2.6371%5. Reading the result
- A 95% one-day VaR is breached about one day in 20. It marks where the bad days begin, not how bad they get: that is the expected shortfall.
- Historical VaR uses only the history you paste: a calm year gives a small VaR however fragile the position is.
- VaR is not subadditive: two desks merged can show more VaR than the sum of both. Expected shortfall does not have this defect.
- This calculator treats the series as the returns of one position. A portfolio needs the returns of the portfolio, which carry the correlations between its assets.
Learn the concept
- Value at Risk (VaR): Worst expected loss over a horizon at a confidence level.
- Expected Shortfall (CVaR): Average loss in the worst tail beyond VaR.