Value at Risk & Python

Value at Risk & Python

1. Introduction to Financial Market Risks

Market risk is defined as the risk of losses due to movements in financial instruments and in market variables, as stock prices, commodities, interest rates, foreign exchange rates, and volatility of these variables. Positions can include cash or derivative instruments. Market risk measurements give a quantification of losses. In the past, the risks were measured through non-satisfaction tools, not figuring out the downside risk for the total portfolio, and failing to deem risk factors correlation. The attempt to overcome these problems led to develop models which compare and aggregate risks with different positions and portfolios. One of the first institutions has developed a VaR model was the US bank J.P. Morgan, because at the end of the eighties, the Chairman of the bank, Mr. Dennis Weatherstone requested every day a summary piece of information in a single monetary value, concerning the whole bank’s market risks in the main market segments. So, it was introduced the VaR, a measure of the maximum loss whose a position or portfolio can suffer, given a certain confidence level, over a predetermined time horizon, answering a pillar question:

“What is the maximum loss which could be suffered over a certain time horizon, so that there is a very low probability – for instance 1 % – that the actual loss will exceed this amount?”

Therefore, a VaR model picks up 3 elements:

  1. It shows a maximum potential loss suffered by a position or portfolio;
  2. Within a certain confidence level, highlighting the probability of the loss;
  3. In a certain time horizon.

Hence, VaR is a probabilistic measure, taking different values for different time horizon and confidence level. In probabilistic terms, with the probability of event E, α the confidence level, and L the loss, we obtain:

prob (L > VaR) = 1 - α
Non è stato fornito nessun testo alternativo per questa immagine

The lowest value of the portfolio return at the chosen time horizon with a certain probability is determined from the distribution of return: 

Non è stato fornito nessun testo alternativo per questa immagine

In order to display this downside risk measure, several methods are available. Here, we are going to show three of them. The Historical Simulation Approach and Parametric Approach are the most widespread ones, and the Semi-Parametric Approach, could be defined as an extension of the parametric one.

2.1 Historical Simulation Approach

Following the pillar history tells us, the past movements can be seen as possible future ones. The historical returns have to be picked up and ranked from the minimum to the maximum one, achieving an empirical distribution. For a required confidence level, a cut-off should be made on the corresponding value of return. In few points:

  1. Selecting a sample of daily returns of the instrument or portfolio, relating to a given historical period.
  2. Extracting the empirical frequency distribution of the values.
  3. Cutting the distribution at the percentile of the desired confidence level.
  4. Computing VaR as the difference between the above percentile and the current value.

2.2 Parametric Approach (Variance-Covariance)

Among the different approaches, the variance-covariance approach is undoubtedly one of the most recognized, although the disadvantages of the market factors’ returns distribution, and the sensitivity of portfolio positions when market factors change. Assuming daily log-returns of a stock: 

Non è stato fornito nessun testo alternativo per questa immagine

It is:

VaR = MV ∙ (μ + z ∙ σ)  

So, in this first simplified example, we have obtained the VaR of a position depending on four elements:

  1. Its market value (MV);
  2. The average return (μ);
  3. The relevant market factor’s estimated return volatility (σ);
  4. A scaling factor (z) which – given the hypothesis of a normal distribution of market factor returns – allows to obtain a risk measure corresponding to the desired confidence level.

Note that the product of the terms z and σ represents a potential unfavorable change in the market factor obtained by making reference to the th percentile of the distribution of Rt.

2.3 Semi-Parametric Approach (Cornish-Fisher) (1937)

Assuming Gaussian distribution is not a right idea whether the focus is on the tails, due to the thin tails of the Gaussian distribution, therefore, Cornish-Fisher VaR does not force to assume any particular return distribution. Now, Z of Alpha is equal to the Z of a normal distribution plus an extension of skewness and the excess kurtosis of the distribution.

Non è stato fornito nessun testo alternativo per questa immagine

When the skewness is zero, and the kurtosis is three we find the same results of a normal distribution, but many times with a negative skewness and a kurtosis higher than three, our downside risk measure figures a different result and the CFVaR is, typically, higher than the parametric VaR, showing higher chances of negative results. The Cornish-Fisher VaR has become a very commonly used methodology for computing of VaR estimates in no Gaussian setting.

3. One Asset Computation with Python

This first script allows us to prepare the data in order to compute a daily VaR within all the different approaches shown above. In summary, it is essential to import the different libraries available in Python and, the data for an asset, i.e. Apple daily close prices as here, transforming them into returns and eliminating the NaN first element.

# Import Libraries and Data

import mplfinance as mpf
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt
from scipy.stats import norm
import pandas as pd
import numpy as np 
%load_ext autoreload
%autoreload 2 

# APPLE stock

aapl = pd.read_csv('AAPL.csv', index_col=0, parse_dates=True)
aapl.index.name = 'Date'
returns = aapl.Close.pct_change()
rets = returns['2020-01-03':'2020-12-11'] 
st_dev = rets.std()
exp_ret = rets.mean()
rets.head()

3.1 Historical simulation approach

Following the Historical Approach, we are going to create a function working with Series as Data Frame, where the inputs are the returns and the confidence level chosen. The output will be a picture of returns and the VaR calculated for different confidence levels.

# Function 

def historical_var(returns, confidence_level):
    """
    Historical Value at Risk
    """

    if isinstance(returns, pd.DataFrame): 
        return returns.aggregate(historical_var, confidence_level=confidence_level)
    elif isinstance(returns, pd.Series):
        return -np.percentile(returns, confidence_level)
    else: 
        raise TypeError("Returns have to be DataFrame or Series")


  
# Results

VaR_99 = historical_var(rets, confidence_level=1)
VaR_95 = historical_var(rets, confidence_level=5)
VaR_90 = historical_var(rets, confidence_level=10)

# Plot

rets.plot.hist(bins=60, histtype="stepfilled", alpha=0.9, label='Returns', figsize=(12, 6))
plt.xlabel('return')
plt.ylabel('frequency')
x = np.linspace(exp_ret - 3*st_dev, exp_ret + 3*st_dev,100)
plt.plot(x, norm.pdf(x, exp_ret, st_dev), "r")
                                    
plt.axvline(x=-VaR_99, color='k', linestyle='-', label='VaR 99%')
plt.axvline(x=-VaR_95, color='k', linestyle='--', label='VaR 95%')
plt.axvline(x=-VaR_90, color='k', linestyle='-.', label='VaR 90%')


plt.legend()
plt.title("AAPL returns")
plt.show()

print('VaR 99% Confidence Level:', VaR_99)
print('VaR 95% Confidence Level:', VaR_95)
print('VaR 90% Confidence Level:', VaR_90)

The output of this script is going to be:

Non è stato fornito nessun testo alternativo per questa immagine

3.2 Parametric Approach (Variance-Covariance)

As far as the Parametric Approach is concerned, it is essential to understand our z-score for any confidence level. The function returns a VaR which depends on the mean and standard deviation of our asset returns, i.e. the expected return and the volatility. Calculating a daily VaR, with the assumption of returns moving as a standard normal distribution, the mean could be omitted in the formula. Anyway, we decide to keep it here for a more accurate empirical estimation.

# Cutoff point depending on a confidence level

z_99 = norm.ppf(.01)
z_95 = norm.ppf(.05)
z_90 = norm.ppf(.10)

# Function

def parametric_var(returns, confidence_level):
    """
    Returns the Parametric Gauusian VaR of a Series or DataFrame
    """

    # compute the Z score assuming it was Gaussian

    z = norm.ppf(confidence_level/100)
    return -(returns.mean() + z*returns.std(ddof=0))

# Results

VaR_99 = parametric_var(rets, 1)
VaR_95 = parametric_var(rets, 5)
VaR_90 = parametric_var(rets, 10)

# Plot

rets.plot.hist(bins=60, histtype="stepfilled",alpha=0.9, label='Returns', figsize=(12, 6))
plt.xlabel('return')
plt.ylabel('frequency')
x = np.linspace(exp_ret - 3*st_dev, exp_ret + 3*st_dev,100)
plt.plot(x, norm.pdf(x, exp_ret, st_dev), "r")
                                    
plt.axvline(x=-VaR_99, color='k', linestyle='-', label='VaR 99%')
plt.axvline(x=-VaR_95, color='k', linestyle='--', label='VaR 95%')
plt.axvline(x=-VaR_90, color='k', linestyle='-.', label='VaR 90%')


plt.legend()
plt.title("AAPL returns")
plt.show()

print('VaR 99% Confidence Level:', VaR_99)
print('VaR 95% Confidence Level:', VaR_95)
print('VaR 90% Confidence Level:', VaR_90)


The output of this script is going to be:

Non è stato fornito nessun testo alternativo per questa immagine

3.3 Semi-Parametric Approach (Cornish-Fisher - CFVaR)

By this kind of approach, i.e. an extension of the Parametric Approach, we are able to not assume returns moving as a normal standard distribution. The reason to deem this approach is to see the cup of tea of the third and fourth momentums (skewness and kurtosis) affects our forecasts. Anyway, if log-returns are normally distributed, then the CFVaR and the VaR estimations figure the same results, which clearly is not the case for Apple stock. Indeed, the CFVaR computation is higher than the Parametric VaR, i.e. our stock is negatively skewed with fat tails.

# Cutoff point depending on a confidence level

z_99 = norm.ppf(.01)
z_95 = norm.ppf(.05)
z_90 = norm.ppf(.10)

# Function

def CF_var(returns, confidence_level):
    """
    Cornish-Fisher Value at Risk
    """

    # compute the Gaussian Z score and then the modified

    z = norm.ppf(confidence_level/100)
    s = skewness(returns)
    k = kurtosis(returns)
    z = (z + (z**2 - 1)*s/6 + (z**3 -3*z)*(k-3)/24 - (2*z**3 - 5*z)*(s**2)/36)
    return -(returns.mean() + z*returns.std(ddof=0))

# Results

VaR_99 = CF_var(rets, 1)
VaR_95 = CF_var(rets, 5)
VaR_90 = CF_var(rets, 10)

# Plot

rets.plot.hist(bins=60, histtype="stepfilled",alpha=0.9, label='Returns', figsize=(12, 6))
plt.xlabel('return')
plt.ylabel('frequency')
x = np.linspace(exp_ret - 3*st_dev, exp_ret + 3*st_dev,100)
plt.plot(x, norm.pdf(x, exp_ret, st_dev), "r")
                                    
plt.axvline(x=-VaR_99, color='k', linestyle='-', label='VaR 99%')
plt.axvline(x=-VaR_95, color='k', linestyle='--', label='VaR 95%')
plt.axvline(x=-VaR_90, color='k', linestyle='-.', label='VaR 90%')


plt.legend()
plt.title("AAPL returns")
plt.show()

print('VaR 99% Confidence Level:', VaR_99)
print('VaR 95% Confidence Level:', VaR_95)
print('VaR 90% Confidence Level:', VaR_90)

The output of this script is going to be:

Non è stato fornito nessun testo alternativo per questa immagine

4. Conclusions

It is worth noticing that we do not replace the scripts for the entire multi-asset portfolios, because they would be too long for the three models, and we do not take into account the Monte Carlo Simulation Approach due to a focus in Semi-Parametric Approach that could be seen as a more rare model. Anyway, generally speaking, there are several reasons for choosing one model over another one, for instance the movement of a particular stock (i.e. the particular distribution they follow), or the past returns affected by a particular scenario (i.e. the coronavirus scenario, where historical simulation approaches could be mostly affected), and many other factors as correlations, volatility and so on. To sum up, it should be divided into a sample risk and model risk. The Parametric Approach, for example, has less sample risk, but introduces the model risk. The Cornish-Fisher expansion overcomes it, recognizing not normally distributed asset returns, and not specifying any particular distribution. That tends to provide relatively robust VaR estimates. However, basically, the VaR as a downside risk measure has two real problems, i.e. non-subadditivity and non-consideration of the size of excess losses. Finally, it can be said that an alternative risk measure overcoming these limitations, i.e. Expected Shortfall (ES).

Filippo Gustavo Niccolini

To view or add a comment, sign in

Others also viewed

Explore content categories