How to calculate value at risk in Python with three methods

How to calculate value at risk in Python with three methods
Value at Risk Explained: How to Calculate and Use It in Python
Value at risk (VaR) estimates a loss threshold for a portfolio over a set time period. If your portfolio has a 95% one-day VaR of $10,000, you expect losses to stay below $10,000 on about 95 out of 100 trading days. The remaining 5 days could be worse, and VaR tells you nothing about how much worse. That gap matters, and we'll come back to it. Our beginner's guide to gauging portfolio risk covers the broader landscape of risk measurement.
A quick note on the 95% number. That's the "confidence level," which just means the estimate is designed to cover the less severe 95% of days. The worst 5% fall outside that boundary. If you're new to Python and want to build these calculations yourself, the course Getting Started with Python for Quant Finance walks through the foundations.
One thing to know before we get into code. In Python, you'll usually calculate VaR as a return first, like -0.02 for a 2% loss, and then convert it to dollars by multiplying by your portfolio value. Keep that distinction in mind as you read the examples below.
How to Calculate Value at Risk in Python
There are a few common ways to calculate value at risk, and each one relies on a different view of how returns behave.
The Historical Method
The historical method uses your portfolio's actual past returns. It sorts them from worst to best and then selects the cutoff that matches your chosen confidence level. If you have 500 days of data and want 95% VaR, you look at the 25th worst return (the bottom 5%). That return is your estimate.
No assumptions about the shape of returns are needed here. You're working with what actually happened. But the estimate can only reflect the market conditions in your data window. If your history doesn't include a crash, your VaR won't account for one.
Here's how that looks in Python.
import numpy as np
returns = np.array([...]) # your daily portfolio returns as decimals
confidence_level = 0.95
# The 5th percentile is the cutoff for the worst 5% of returns
var_historical = np.percentile(returns, 5)
print(f"Historical VaR (95%): {var_historical:.4f}")
The np.percentile(returns, 5) call finds the return below which only 5% of your historical returns fall. That's your loss threshold.
The Parametric Method
The parametric method (also called the variance-covariance method) assumes returns follow a normal distribution, which means they cluster symmetrically around an average with a predictable spread, like a bell curve. You calculate the average return and the typical amount returns move around that average, then use those numbers to estimate a loss threshold.
import numpy as np
from scipy.stats import norm
returns = np.array([...]) # your daily portfolio returns as decimals
mean = np.mean(returns)
std = np.std(returns, ddof=1) # sample standard deviation
confidence_level = 0.95
# norm.ppf gives the z-score for a given probability
z_score = norm.ppf(1 - confidence_level) # about -1.645 for 95%
var_return = mean + z_score * std
portfolio_value = 100000 # example portfolio size in dollars
var_dollar = abs(var_return) * portfolio_value
print(f"Parametric VaR (95%) as return: {var_return:.4f}")
print(f"Parametric VaR (95%) in dollars: ${var_dollar:.2f}")
The formula returns a negative number because it represents a loss. If you want to report VaR as a positive dollar amount, which is the usual convention, take the absolute value before multiplying by portfolio size, as shown above.
Real market returns produce very large losses more often than a bell-curve model assumes. This method can therefore understate the chance of extreme losses. That's its main weakness, and it's worth remembering whenever you use it.
The Monte Carlo Method
Monte Carlo simulation creates many possible future return paths based on assumptions you choose. It then measures the loss cutoff that matches your confidence level. You might generate 10,000 hypothetical one-day returns and find the 5th percentile of those simulated outcomes.
This approach is more flexible than the parametric method because you can model return behavior that doesn't follow a bell curve. But its results depend heavily on the assumptions you feed in, including how much returns tend to move and how different assets in your portfolio move in relation to each other. Our guide on computing value at risk with Monte Carlo shows the full Python implementation.
What Value at Risk Doesn't Tell You
VaR leaves out one important piece of information. It does not tell you how large losses get when they move beyond the cutoff.
If your 95% one-day VaR is $10,000, you know that 5% of days will be worse. But whether those bad days average $11,000 in losses or $50,000, VaR gives you the same number. That's a real problem when you're trying to understand your full downside exposure.
Many firms use VaR together with CVaR to fill this gap. CVaR stands for Conditional Value at Risk (sometimes called Expected Shortfall), and it measures the average loss on the days that are worse than the VaR cutoff. You can read more about how CVaR captures tail risk and see how the two measures complement each other.
Limitations in Real-World Portfolios
The examples above work well for stock portfolios with straightforward daily returns. Real portfolios can be more complicated. Portfolios that include options or highly leveraged positions can behave in non-linear ways, which means the relationship between market moves and portfolio losses isn't a straight line. Basic VaR methods may miss those effects entirely.
Time horizon is another trap. A one-day VaR and a one-month VaR are not interchangeable. Extending VaR to longer periods requires extra assumptions about how returns add up over time, and those assumptions often break during turbulent markets.
Putting Value at Risk to Work
VaR works best as a daily monitoring tool, not a worst-case guarantee. Banks and investment firms use it to cap how much they put into a single trade and to report portfolio risk to regulators. But they don't rely on it alone.
For a fuller picture, firms combine VaR with stress tests, which ask how the portfolio would perform under extreme market moves like the 2008 financial crisis, and with CVaR. If you want a longer Python example covering both measures, the risk metrics guide for VaR and CVaR in Python walks through the full calculation. The scipy.stats documentation is also worth bookmarking for the statistical functions you'll use repeatedly.
Use VaR as a quick daily estimate of likely loss, then check the cases it misses with stress tests and CVaR. That combination gives you a more realistic view of portfolio risk.