%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import PortfolioAnalytics as PortfolioAnalytics
import PortfolioLoadData as PortfolioLoadData
import PortfolioRisk as PortfolioRisk
import PortfolioStatistics as PortfolioStatistics
%load_ext autoreload
%autoreload 2
We're going to look at a few measures of downside risk. We've already seen how to compute drawdowns, but we're going to look at 3 popular measures.
The first measure is the simplest, which is the semideviation, which is nothing more than the volatility of the subset of returns that are negative or below a certain threshold.
hfi = PortfolioLoadData.get_hfi_returns()
PortfolioRisk.semideviation(hfi).sort_values()
We'll look at four different ways to compute Value At Risk
To compute the historic VaR at a certain level, say 5%, all we have to do is to find the number such that 5% of the returns fall below that number and 95% of the returns fall above that number. In other words, we want the 5 percentile return.
Note that for reporting purposes, it is common to invert the sign so we report a positive number to represent the loss i.e. the amount that is at risk.
PortfolioRisk.var_historic(hfi, level=1).sort_values()
Now that we have the VaR, the CVaR is very easy. All we need is to find the mean of the numbers that fell below the VaR!
PortfolioRisk.cvar_historic(hfi, level=1).sort_values()
The idea behind this is very simple. If a set of returns is normally distributed, we know, for instance, that 50% of the returns are below the mean and 50% are above.
We also know that approx two thirds of the returns lie within 1 standard deviation. That means one third lie beyond one standard deviation from the mean. Since the normal distribution is symmetric, approximately one sixth (approx 16%) lie below one standard deviation away from the mean. Therefore, if we know the mean and standard deviation and if we assume that the returns are normally distributed, the 16% VaR would be the mean minus one standard deviation.
In general we can always convert a percentile point to a z-score (which is the number of standard deviations away from the mean that a number is). Therefore, if we can convert the VaR level (such as 1% or 5%) to a z-score, we can calculate the return level where that percent of returns lie below it.
scipy.stat.norm contains a function ppf() which does exactly that. It takes a percentile such as 0.05 or 0.01 and gives you the z-score corresponding to that in the normal distribution.
Therefore, all we need to do to estimate the VaR using this method is to find the z-score corresponding to percentile level, and then add that many standard deviations to the mean, to obtain the VaR.
PortfolioRisk.var_gaussian(hfi).sort_values()
The Cornish-Fisher modification is an elegant and simple adjustment.
The z-score tells us how many standard deviations away from the mean we need to go to find the VaR. If the returns arent normal, we know that z-score will give us an inaccurate number. The basic idea is that since we can observe the skewness and kurtosis of the data, we can adjust the z-score up or down to come up with a modifed z-score. e.g. intuitively, all other things being equal, if the skewness is negative, we'll decrease the z-score further down, and if the skewness is positive, we'll push it up.
The adjusted z-score which we'll call $z_{cornishfisher}$ given by:
$$ z_{cornishfisher} = z +\frac{1}{6}(z^2-1)S + \frac{1}{24}(z^3-3z)(K-3)-\frac{1}{36}(2z^3-5z)S^2 $$We can modify the previous function by adding a "modified" parameter with a default value of True as follows. If True then the following piece of code is executed, which modifes z:
PortfolioRisk.var_gaussian(hfi, modified=True).sort_values()
var_table = [PortfolioRisk.var_historic(hfi),
PortfolioRisk.cvar_historic(hfi),
PortfolioRisk.var_gaussian(hfi, modified=False),
PortfolioRisk.var_gaussian(hfi, modified=True), ]
comparison = pd.concat(var_table, axis=1)
comparison.columns=['Historic VaR', 'cVaR', 'Gaussian', 'Cornish-Fisher']
comparison.plot.bar(title="Hedge Fund Indices: VaR at 5%",figsize=(12,6))