By considering the same Value at Risk measure, $\varrho$, applied to two or more portfolios (credit loss distributions, profit-and-loss distributions, etc.) one desires to have a subadditivity property in place:
$$
\varrho(X_1 + X_2) \le \varrho(X_1) + \varrho(X_2)
$$ i.e. meaning that two combined portfolios should never be more risky than the sum of the risk of two portfolios separately. Unfortunately, the Value-at-Risk risk measure does not obey this rule. In my previous post I addressed that case with a practical example.
To overcome the conceptual deficiencies of the VaR related to non-subadditivity, many risk managers prefer the use of the Expected Shortfall (ES). Given VaR defined as:
$$
VaR_{\beta}(X) = \pm F^{-1}(\beta)
$$ depending on distribution $F$, where for the case of positively-described $F$, $\beta$ is the confidence level ($\beta = 1 – \alpha$; $\alpha$ denotes the significance level; $\alpha < \beta$). One defines the ES as follows:
$$
ES_{\beta}(X) = \frac{1}{1-\beta} \int_{0}^{1-\beta} VaR_u(X) du
$$ which inherits the properties of translation invariance, monotonicity, and homogeneity from VaR. However and furthermore, it is also subadditive what makes ES the coherent measure of risk.
In this short post you will find a Python code showing how to make a switch between VaR and ES such that $ES_{\beta’}(X) = VaR_{\beta}$ what requires solving for new $\beta’$. Since there is no close formula for getting $\beta’$, a numerical procedure does the job. Such calibration appears to be pretty handy when it comes to the problem of ES allocation for a portfolio of assets or credit loans.
1. Value at Risk and Expected Shortfall for Normal Distribution
For $X$ to be normally distributed, $X\sim N(\mu, \sigma)$, the VaR can be quickly found by
$$ VaR_{\beta}(X) = \mu \pm \sigma \Phi^{-1}(\beta)
$$ where $\Phi(x)$ is the standard normal cumulative distribution. In Python we get the same by:
alpha = 0.01 # confidence level beta = 1- alpha # significance level mu, sigma = 0, 1 # ~N(0,1) VaR = mu - sigma * stats.norm.ppf(alpha) print(VaR)
2.32634787404
It can be shown that for $X\sim N(\mu, \sigma)$, the corresponding ES is:
$$ ES_\alpha(X) = \mu + \frac{\sigma}{\alpha} \int_{0}^{\alpha} \Phi^{-1} (1-u) du \\
= \mu + \frac{\sigma}{\alpha} \int_{1-\alpha}^{1} \Phi^{-1} (u) du
$$
By changing variables, setting the percent point function (inverse of CDF) $q=\Phi^{-1}(u)$, and integrating by substitution we get:
$$
= \mu + \frac{\sigma}{\alpha} \int_{\phi^{-1}(1-\alpha)}^{\infty} q\phi(q) dq \\
= \mu + \frac{\sigma}{\alpha}\left[ -\frac{1}{2\pi} \exp(-q^2/2) \right]_{\Phi^{-1}(1-\alpha)}^{\infty} \\
= \mu + \frac{\sigma}{\alpha}\left[ \frac{1}{2\pi} \exp(-q^2/2) \right]_{\infty}^{\Phi^{-1}(1-\alpha)}
$$ i.e.
$$
ES_\alpha(X) = \mu + \frac{\sigma}{\alpha} \phi\left( \Phi^{-1} (1-\alpha) \right)
$$ where $\phi$ denotes the standardized normal density function, what in Python takes form of:
mu + sigma * stats.norm.pdf(stats.norm.ppf(1-alpha))/alpha
2.665214220345808
In practice, we work more often with empirical data that can display distributions not exactly normal. It is good to have a quick recipe for estimation VaR and ES in any case.
2. Estimation of VaR and ES using Order Statistics
Suppose that a sample of $X_1, …, X_n$ of some recorded losses (profits) is available (discrete distribution of $X$’s) and we aim to find the corresponding VaR and ES at $\beta$ confidence level. We create a sample that is ordered in an increasing fashion, $X_{(1)} < X_{(2)} < … < X_{(n)}$. The number of elements that we need to retain for further calculations is $\lfloor n\beta \rfloor$ which is the integer part of $n\beta$. Therefore, the data-based estimator of VaR and ES is:
$$
\widetilde{VaR(X)} = X_{(\lfloor n\beta \rfloor])}
$$ and
$$
\widetilde{ES(X)} = \frac{ \sum_{i=[n\beta]}^n x_{(i)} } { n\alpha + 1 }
$$ respectively. Again, in Python, for a sample of $n=10^6$ random variables $X\sim N(0,1)$, we derive both estimators as follows:
n = int(1e6) rvs = np.hstack([stats.norm.rvs(size=n)]) x = np.sort(rvs) estVaR = x[int(n*beta)] estES = np.sum(x[int(n*beta) : n+1]) / (int(n*alpha) + 1) print(estVaR) print(estES)
2.32995588245 2.66350868108
to be in a very good agreement with the “analytical” values (see above).
3. Finding Expected Shortfall to match Value-at-Risk
Eventually, addressing the main problem of solving for new $\beta’$ such to satisfy $ES_{\beta’}(X) = VaR_{\beta}$ requires a few extra lines of code, for instance:
for newbeta in np.arange(0.50, 1, step=0.0001): var = x[int(n*newbeta)] es = np.sum(x[int(n*newbeta) : n+1]) / (int(n*(1-newbeta)) + 1) if(es > estVaR): print(beta, newbeta, VaR, es, np.percentile(rvs, newbeta*100)) break
0.99 0.9746 2.32634787404 2.33263505863 1.95517826448
where for our exemplary set of data $X \sim N(0,1)$ at $n=10^6$ and the confidence level of $\beta = 0.99$ we find $ES_{\beta’}(X)$ equal $VaR_{\beta}$ for $\beta’ = 0.9746$.
It is easy to check that $VaR_{\beta’} < VaR_{\beta}$ as expected and $VaR_{\beta}(X) \cong ES_{\beta’}(X) \cong 2.33$.
Simple as that.
1 comment