Value At Risk With Python

Felipe Cezar
Analytics Vidhya
Published in
3 min readDec 19, 2020

Whether you are an aspiring day trader, a financial market professional or just a data scientist dipping your feet into finance, you are likely to have come across the concept of Value At Risk , commonly referred to as VaR.

How bad can it get?

Regardless of what your objectives are when you make an investment, the risk associated with it is always at the top of your concerns. VaR is one of the ways you measure the magnitude of that risk.

VaR measures how bad things can get in a given investment. The 1% VaR for a given investment tells you the 1% worst outcome you can expect for it.

Let’s imagine that you considering investing in stock XPTO, and in your research you stumble onto a report saying that the 1% VaR for this stock is 5%. What does it mean? I means that out of all possible returns, the worst 1% is a return of -5%.

How could you know all possible outcomes? You can’t. No one knows for certain how the price of an asset will behave in the future, and that is why there is no definitive way to calculate it. Instead, there are multiple types of VaR.

Historical VaR

Even though the past is not an indication of future performance, this is still a insightful indication of downside to bear in mind.

Historical VaR consists in calculating the nth worst outcome out of the historical sample. Below you can see one possible way to calculate it in Python:

def var_historic(r, level=1):
"""
Takes in a series of returns (r), and the percentage level
(level)
Returns the historic Value at Risk at a specified level
i.e. returns the number such that "level" percent of the returns
fall below that number, and the (100-level) percent are above
"""
if isinstance(r, pd.DataFrame):
return r.aggregate(var_historic, level=level)
elif isinstance(r, pd.Series):
return -np.percentile(r, level)
else:
raise TypeError("Expected r to be a Series or DataFrame")

Parametric and Semi-Parametric VaR

Another way to calculate VaR is to assume the set of possible outcomes behaves like a Normal (Gaussian) Distribution.

The Normal Distribution is not necessarily the best way to describe returns. However, it is a very good way to picture the concepts, and it is a good starting point for us to elaborate on more complex and realistic scenarios.

The main drawback of the parametric approach is that real world returns usually have a distribution with “fat tails” (high kurtosis).

To illustrate how this is important, let’s say that you calculate the VAR for 1% using a parametric approach and it comes up as 6%. Then, you look at real historical data, and you see that a -6% return happens way more often then 1% of the time: this would be an indication of fat-tails.

Below you will find some code for parametric and semiparametric VaR:

from scipy.stats import norm
def var_gaussian(r, level=5, modified=False):
"""
Returns the Parametric Gauuian VaR of a Series or DataFrame
If "modified" is True, then the modified VaR is returned,
using the Cornish-Fisher modification
"""
# compute the Z score assuming it was Gaussian
z = norm.ppf(level/100)
if modified:
# modify the Z score based on observed skewness and kurtosis
s = skewness(r)
k = kurtosis(r)
z = (z +
(z**2 - 1)*s/6 +
(z**3 -3*z)*(k-3)/24 -
(2*z**3 - 5*z)*(s**2)/36
)
return -(r.mean() + z*r.std(ddof=0))

Lastly, another method for calculating VaR consists of simulating possible random outcomes and using that as the distribution for the calculation. This is a very interesting topic which I will cover in a future post.

If you are interested in learning more about this topic, I highly recommend a lecture from Kenneth Abbott about VaR models, freely available on MIT’s YouTube channel.

--

--