Introduction to Risk Management
Introduction to Risk Management
“Only those who risk going too far can possibly find out how far they can go.” - T.S. Eliot
The entirety of risk analysis is a very extensive space. This introduction to risk management is going to focus solely on applied business risk modeling and analysis. Some examples of this would include market risk (the risk of having unknown future prices in a market), operational risk (the risk of having unknown effects impact a company’s operation like employee turnover), credit risk (the risk of having people default on loans - for more information on modeling credit risk directly check out the code notes: Credit Modeling), and liquidity risk (the risk of not being able to liquefy assets when capital is needed).
Risk is typically tied with uncertainty. Risk and uncertainty are related, however, they are different than each other. Risk is something that someone bears. Risk is a possible outcome of uncertainty. Once you have an uncertain event and you can put some distribution to it, you can measure possible risks associated with that event. Just because there is uncertainty doesn’t mean there is risk. Take the flip of a coin. The outcome of this flip of a coin is uncertain. It could be heads or tails. However, there is no risk involved in this uncertainty. Now imagine that the outcome of the flip of that coin is you getting $5 for heads and losing $5 for tails. Now there is risk to the uncertainty of the coin flip because you stand to lose something based on one of the possible outcomes.
There are three levels of uncertainty that we typically think of:
Known - a guaranteed event or no uncertainty. For example, I enter in a contract where I will buy 10 bushels of corn 1 year from now.
Unknown - events that carry risk that will be reduced / eliminated over time as the event gets closer. For example, I do not know the price of corn 1 year from now so our contract could be bad for me in terms of price, but as I get closer to 1 year from now I know more about my risk.
Unknowable - events that carry risk that may not change over time as the event gets closer. For example, a natural disaster could prevent us from exercising the contract. The risk didn’t change up to the event because the disaster might not have been known to happen. Insurance can protect us against this kind of risk!
Let’s load up all of the needed libraries in R that we will be using in these course notes. This isn’t needed for the SAS sections of the code.
install.packages("quantmod")
install.packages("ks")
install.packages("TTR")
install.packages("scales")
install.packages("fExtremes")
install.packages("triangle")
library(graphics)
library(quantmod)
library(TTR)
library(ks)
library(scales)
library(fExtremes)
library(triangle)
Primer on Risk
Let’s go through a basic example of evaluating risk. Here we have three potential projects to invest in - A, B, or C. The cost of these projects, the expected net return of these projects (profit after subtracting initial costs), and the risk of these projects is defined in the table below:
If we evaluate the project based solely on the expected net return we might choose project B. However, project B carries more risk. To combine the information on return and risk we have the Risk Adjusted Return on Capital (RAROC) calculation which is simply the ratio of return to risk. Here we can see that project C is the most return for the risk that we are taking. In fact, investors are not getting paid based on RAROC instead of just return in the investment world. This is because of the incentive problem. Investors were willing to take high risks with other people’s money to make high incomes. They were relying on the government to bail them out if they made a mistake. Now, they are getting paid based on smart investments in terms of both return as well as risk.
However, when evaluating possible scenarios of outcomes, this method of RAROC still falls short. It helps make sound decisions when only considering point estimates of return and risk, but what if that expected return is variable? For example, I want to get in the market of selling widgets. I think I can sell 1500 widgets (quantity, Q) at $10.00 per widget (price, P). It will cost me $7.00 to make each widget (variable cost, VC) and $2,500 to buy the widget making machine (initial / fixed costs, FC). From a basic revenue calculation we can see the net revenue (NR) this enterprise has:
\[ NR = Q \times (P - VC) - FC \]
\[ NR = 1500 \times (10-7) - 2500 \]
\[ NR = \$2,000 \] Again, this assumes that these inputs are all fixed and known ahead of time. Let’s see what happens when they vary.
Scenario Analysis
In the previous example, we looked at our widget making business and calculated an expected net return of $2,000. If all of the inputs are guaranteed, then we should always invest in this opportunity as it guarantees us a net return that is positive.
Scenario analysis introduces the idea of risk into these calculations. People started accounting for possible extreme values in their estimation of some inputs into calculations. Let’s change the above example slightly. Instead of 1500 widgets being guaranteed to be sold, we have three possibilities. I am most likely to sell 1500 widgets. The best case scenario though is that I can sell 2000 widgets. However, the worst case scenario is that I can only sell 500 widgets. Going through the same net revenue calculation for all three of these possibilities shows some variability to our final result. Now we have an expected net revenue still of $2,000, but with the possibility of making as much as $3,500 and losing as much as $1,000. With those possibilities, the investment is no longer a guarantee. This process can be repeated across all of the variables to see which one has the most impact on the net revenue.
This basic scenario analysis is OK, but still has highly variable outcomes. Is losing money rare or is it more likely that I make some money with a small chance of losing money? We don’t know as only three possibilities are shown. What about interdependence between variables? I imagine that the quantity I sell is highly related to the price that I charge.
Simulation
Simulation analysis allows us to account for all of the possible changes in all these variables and the possible correlation between them. The final output from a simulation analysis is the probability distribution of all possible outcomes. Let’s imagine triangle distributions for the inputs to the above example with the following bounds:
Variable | Worst Case | Expected | Best Case |
---|---|---|---|
Quantity | 500 | 1,500 | 2,000 |
Price | $9.00 | $10.00 | $11.00 |
Variable Cost | $8.00 | $7.00 | $6.50 |
Fixed Cost | $3,000 | $2,500 | $1,500 |
By randomly drawing possible values from the respective triangle distributions 10,000 times and plotting the possible net revenues from each of these simulations we can get a fuller view of the possible outcomes from our widget investment. To do this we use the rtriangle
function to draw values for each input to our equation. From there we just calculate the net revenue for each row in our input vectors to get 10,000 different possible net revenues. From there we just plot the corresponding distribution.
<- 10000
simulation.size
<- rtriangle(simulation.size, a=500, b=2000, c=1500)
Units <- rtriangle(simulation.size, a=6.5, b=8, c=7)
Var.Cost <- rtriangle(simulation.size, a=1500, b=3000, c=2500)
Fixed.Cost <- rtriangle(simulation.size, a=8, b=11, c=10)
Price
<- (Price - Var.Cost)*Units - Fixed.Cost
Net.Revenue
hist(Net.Revenue, breaks=50, main='Sampling Distribution of Net Revenue', xlab='Net Revenue')
From this we see a much fuller picture of the possible outcomes from our investment. Although the average net revenue is a little over $1,000, in 23.34% of outcomes we lose money. This helps us better evaluate risk. For more information on how to develop simulations like this one, please see the code notes: Introduction to Simulation.
Key Risk Measures
Risk is an uncertainty that affects a system in an unknown fashion and brings great fluctuation in values and outcomes. Remember, that risk is a possible outcome of uncertainty. These outcomes can be measured in a probabilistic sense. Risk has a time horizon and has to be set against a benchmark. Risk analysis uses some of the “typical” statistical measures of spread.
There are some common measures that are used in risk analysis:
- Probability of occurrence - measures the probability of risky outcomes like a project losing money, defaulting on a loan, downgrading of a company, etc.
- Standard deviation / variance - measures spread in a two-sided manner that works best in normality or symmetric distributions.
- Semi-standard deviation - measures of dispersion for the values falling on the risk side of a distribution. For example, if you were measuring risk for profit the semi-standard deviation is calculated as:
\[ \sigma_{semi} = \sqrt{\frac{1}{T} \sum_{t=1}^T \min(X_t - \bar{X}, 0)^2} \]
- Volatility - measures the standard deviation of an asset’s logarithmic returns as follows:
\[ \sigma_{volatility} = \sqrt{\frac{1}{T} \sum_{t=1}^T \log(\frac{X_t}{X_{t-1}})^2} \]
- Value at Risk (VaR) - measures the amount of money at risk given a particular time period at a particular probability of loss. For example, a 1 year 1% VaR being $10,000 means there is a 1% chance you will lose more than $10,000 in 1 year.
- Expected Shortfall (ES) - measures the average money in the worst % of cases given a particular period of time. For example, in the worst 1% of scenarios, the average amount of money you will lose in one year is $15,000.
Value at risk and expected shortfall are some of the most popular measures of risk so we will discuss them in much further detail throughout these notes.
Value at Risk
Value at risk (VaR) was developed in the early 1990’s by JP Morgan. They were made famous in JP Morgan’s “4:15pm” report which was a daily report given to the Chief Risk Officer at JP Morgan detailing the risk of all current investments / portfolios. In 1994, JP Morgan launched RiskMetrics®. VaR has been widely used since that time and people are researching other similar measures.
The VaR calculation is aimed at making a statement of the following form: We are 1% certain that we will lose more than $10,000 in the next 3 days. VaR is the maximum amount at risk to be lost over a period of time and at a particular level of confidence. Essentially, VaR is associated with a percentile (quantile) of a distribution as shown in the chart below:
For the plot above, the one year 1% VaR is $500,000. In other words, there is a 1% chance you will lose at least $500,000 by holding that portfolio for a year. Although most of the portfolio value over the next year is positive with the average being one million in value, there is some risk. VaR calculates the value that is most at risk in terms of a quantile. For costs, the VaR would be on the high end since risk is high cost, not low cost.
The main steps to estimating VaR are the following:
- Identify the variable of interest (asset value, portfolio value, credit losses, insurance claims, etc.)
- Identify the key risk factors that impact the variable of interest (asset prices, interest rates, duration, volatility, default probabilities, etc.)
- Perform deviations in the risk factors to calculate the impact in the variable of interest
The main question is how to estimate the distribution that we will calculate the quantile of. There are three main approaches to estimating the distribution in VaR:
- Delta-Normal (Variance-Covariance) Approach
- Historical Simulation Approach(s)
- Simulation Approach
These will be discussed in later sections of these notes.
Expected Shortfall
There are some downsides to value at risk as a calculation. One of them is that VaR ignores the distribution of a portfolio’s return beyond its VaR value. For example, if two portfolios each have a one year 1% VaR of $100,000, does that mean you are indifferent between the two? What if you then knew the maximum loss for one of the portfolios is $250,000, while the other has a maximum loss of $950,000. VaR ignores the magnitude of the worst outcomes. Another downside of VaR is that under non-normality, VaR may not capture diversification. Mathematically, it fails to satisfy the subadditivity property:
\[ Risk(A + B) \le Risk(A) + Risk(B) \]
The VaR of a portfolio with two securities may be larger than the sum of the VaR’s of the securities in the portfolio.
The expected shortfall (ES) (also called the conditional value at risk (CVaR)) is a measure that doesn’t have the two drawbacks described above. Given a confidence level and a time horizon, a portfolio’s ES is the expected loss one suffers given that a “bad” event occurs. The ES is a conditional expectation that tries to answer what you should expect to lose if your loss exceeds the VaR. It is the expected (average) value of the portfolio in the circled region below:
The main question is how to estimate the distribution that we will calculate the average of the worst case outcomes. There are three main approaches to estimating the distribution in ES and they are the same as VaR:
- Delta-Normal (Variance-Covariance) Approach
- Historical Simulation Approach(s)
- Simulation Approach
These will be discussed in later sections of these notes.
Returns
Before getting into detail on calculating the distributions behind VaR and ES, let’s briefly talk about returns. A lot of the calculations in the remaining pieces of this document will revolve around calculating returns on assets. There are two main methods for calculating returns:
- Arithmetic returns
- Geometric returns
As we detail the differences between these approaches, here is the notation we will use:
- Arithmetic Returns (\(r_t\)) - return at a period \(t\) (value of holding an asset from period \(t-1\) to period \(t\))
- Price (\(P_t\)) - price at a given time period \(t\)
- Lag Price (\(P_{t-1}\)) - price at a given time period \(t-1\)
- Dividend (\(D_t\)) = sum of money regularly paid from company to shareholders at time period \(t\). For small time periods we typically ignore dividends (set them equal to 0). Equivalently, we can think about the price of an asset where dividends are fully reinvested and reflected in the price itself.
Arithmetic returns are calculated as follows:
\[ r_t = \frac{P_t + D_t - P_{t-1}}{P_{t-1}} = \frac{P_t - P_{t-1}}{P_{t-1}} \; when \; D_t = 0 \]
If \(r_1 = 5\%\) and \(r_2 = -5\%\), what is the total return of the two days? It is not 0%! This is how we would get the return, \(r_{0,2}\), over the two days:
\[ r_{0,2} = \frac{P_2 - P_0}{P_0} = \cdots = \frac{P_1}{P_0}r_2 + r_1 \ne r_2 + r_1 \]
For example, if we had $100 that we got 5% return on after 1 year, but lost 5% in year two with arithmetic returns we would have:
\[ P_0 = 100, \; P_1 = 100 \times (1 + 0.05) = 105, \; P_2 = 105 \times (1 - 0.05) = 99.75 \]
\[ r_{0,2} = \frac{99.75 - 100}{100} = -0.25\% \]
Geometric returns (denoted \(R_t\) instead) on the other hand are calculated as follows:
\[ R_t = \log(\frac{P_t + D_t}{P_{t-1}}) = \log(\frac{P_t}{P_{t-1}}) = \log(P_t) - \log(P_{t-1}) \; when \; D_t = 0 \]
If \(R_1 = 5\%\) and \(R_2 = -5\%\), what is the total return of the two days? It is 0%! This is how we would get the return, \(R_{0,2}\), over the two days:
\[ R_{0,2} = \log(\frac{P_2}{P_0}) = \log(\frac{P_2}{P_1} \times \frac{P_1}{P_0}) = \log(\frac{P_2}{P_1}) + \log(\frac{P_1}{P_0}) = R_1 + R_2 \]
Let’s use the previous example’s prices to see what the geometric returns would be:
\[ P_0 = 100, \; P_1 = 105, \; P_2 = 99.75 \]
\[ R_1 = 4.88%, \; R_2 = -5.13% \]
\[ R_{0,2} = \frac{99.75}{100} = 4.88% - 5.13% = -0.25\% \]
The difference between arithmetic and geometric means is very small when returns are close to zero. We can see this by expanding the natural log:
\[ R_t = \log(\frac{P_t}{P_{t-1}}) = \log(\frac{P_t - P_{t-1}}{P_{t-1}} + 1) = \log(1 + r_t) = r_t - \frac{r_t^2}{2} + \frac{r_t^3}{3} - \cdots \]
This is approximately \(r_t\) when \(r_t\) is small. The following are the arithmetic returns and geometric returns for Google.
As you can see above, the two different types of returns are approximately equal.
Estimation of VaR and ES
The main steps to estimating VaR and ES are the following:
- Identify the variable of interest (asset value, portfolio value, credit losses, insurance claims, etc.)
- Identify the key risk factors that impact the variable of interest (asset prices, interest rates, duration, volatility, default probabilities, etc.)
- Perform deviations in the risk factors to calculate the impact in the variable of interest
The main question is how to estimate the distribution that we will calculate the quantile of. There are three main approaches to estimating the distribution in VaR:
- Delta-Normal (Variance-Covariance) Approach
- Historical Simulation Approach(s)
- Simulation Approach
First we will discuss how to do this for value at risk followed by expected shortfall.
Delta Normal
The Delta Normal approach has two key characteristics that define it. First, we will discuss the Normal part of the name. Suppose that the value, \(V\), of an asset is a function of a normally distributed risk factor, \(RF\). Assume that the relationship between this risk factor and the value of the asset is linear:
\[ V = \beta_0 + \beta_1 RF \]
In this situation it is easy to calculate the VaR. If \(RF\) is normally distributed in the baove equation, then \(V\) would also be normally distributed as well. The 2.5% VaR on any normal distribution is the quantile shown below:
The VaR at 2.5% is just \(\mu - 1.96\sigma\). With an estimate of \(\mu\) and \(\sigma\) we can estimate this number easily. In fact, any VaR for a normal distribution can be calculated by adjusting the \(1.96\) to match the quantile of interest. For example, the 1% VaR is \(\mu - 2.33\sigma\).
The above approach works great if the relationship is linear between \(RF\) and \(V\). What if the relationship between the two is nonlinear:
\[ V = \beta_0 + \beta_1 RF^2 \]
Finding the extreme of a normally distributed value and squaring that value does not equal the extreme value for a squared risk factor. However, we can still use the normality assumption to help calculate the VaR.
This is where the delta piece of the name comes into play. The derivative of the relationship will help us approximate what we need. Remember, the derivative at a specific point (say \(RF_0\)) is the tangent line at that point. If we zoom in closer to the area around \(RF_0\) the relationship is approximately linear as seen below:
Small changes of the risk factor result in small changes of the value of the asset. We can approximate these small changes with the slope. We can see this more mathematically by looking at the Taylor-series expansion of a function’s derivatives:
\[ dV = \frac{\partial V}{\partial RF}\cdot dRF + \frac{1}{2}\cdot \frac{\partial^2 V}{\partial RF^2}\cdot dRF^2 + \cdots \]
The Delta-Normal approach assumes that only the first derivative is actually important. We can evaluate this first derivative at a specific point \(RF_0\) which is typically some initial value:
\[ dV = \frac{\partial V}{\partial RF} \Biggr \vert_{RF_0} \cdot dRF \; \rightarrow \; \Delta V = \delta_0 \cdot \Delta RF \]
The change in the value of the asset / portfolio is a constant (\(\delta_0\)) multiplied by the change in the risk factor. This is a linear relationship between the changes. All we need to know is the distribution of \(\Delta RF\). Luckily, we already assumed normality for \(RF\). Since \(\Delta RF = RF_t - RF_{t-1}\) and each of \(RF_t\) and \(RF_{t-1}\) are normal, then \(\Delta RF\) is normally distributed since the difference in normal distributions is still normal. Therefore, the change in the value of the asset / portfolio, \(\Delta V\) is also normally distributed by the same logic. Since \(\Delta V\) is normally distributed we can easily calculate any VaR values for the change in the portfolio as we did above.
Let’s work through an example! Suppose that the variable of interest is a portfolio consisting of \(N\) units in a certain stock, \(S\). The price of the stock at time \(t\) is denoted as \(P_t\). Therefore, the value of the portfolio is \(N \times P_t\). Let’s assume that the price of the stock follows a random walk:
\[ P_t = P_{t-1} + \varepsilon_t \] with \(\varepsilon_t\) following a normal distribution with mean 0 and standard deviation \(\sigma\). Therefore, the change in the value of the portfolio is \(N \times \Delta P_t\) with \(\Delta P_t = P_t - P_{t-1} = \varepsilon_t\) which is a normal distribution. We can then look up the VaR for a portfolio under this structure by just looking up the corresponding point on the normal distribution. If we wanted the 1% VaR for the change in the value of the portfolio, it would just be \(0 - 2.33 \sigma\). This is why the Delta-Normal approach is sometimes referred to as the variance-covariance approach. If you know the variances of your data and are willing to assume normality, then the calculation of the VaR is rather straight forward.
Let’s put some numbers to the previous example. Suppose you invested $100,000 in Apple today (bought Apply stock). Historically, the daily standard deviation of Apple returns are 2.36%. Let’s also assume daily returns for Apple have a mean return of 0%. Let’s assume that the returns for Apple follow a normal distribution. Then the 1 day, 1% VaR is calculated as \(\$100,000 \times (-2.33) \times 0.0236 = -\$5,498.80\). In other words, you think there is a 1% chance of losing more than $4,075.50 by holding that portfolio of Apple stock for a single day.
What if we had two assets in our portfolio? Luckily, these calculations are still easily worked out under the assumption of normality. If we had two random variables X and Y that were both normally distributed, then the variance of a linear combination of X and Y, \(aX + bY\) would be the following:
\[ \sigma^2 = a^2 \sigma_X^2 + b^2 \sigma_Y^2 + 2ab \times Cov(X,Y) \]
Suppose you invested $200,000 in Microsoft and $100,000 in Apple. Assume the historical daily average return is 0% for both. Also assume that the historical standard deviation of daily returns for Microsoft and Apple are 2.15% and 2.36% respectively. Lastly, assume that the historical correlation between the two returns is 0.791. Under the assumption that both returns follow normal distributions then the variance of that portfolio is the following:
\[ \sigma^2_P = (\frac{2}{3})^2 \sigma_M^2 + (\frac{1}{3})^2 \sigma_A^2 + 2(\frac{2}{3})(\frac{1}{3}) \times Cov(M,A) \]
\[ \sigma^2_P = (\frac{2}{3})^2 0.0215^2 + (\frac{1}{3})^2 0.0236^2 + 2(\frac{2}{3})(\frac{1}{3}) \times (0.791 * 0.0215 * 0.0236) = 0.00045 \]
Then the one day, 1% VaR for this portfolio is \(\$300,000 \times (-2.32635) \times \sqrt(0.00045) = -\$14,728.28\).
Let’s see how we can do this in each of our softwares!
R
It is easy to replicate the calculations we did above by hand using R. First, we need to collect our stock data. We can do this using the getSymbols
function. The input to the getSymbols
function is the stock tickers from the New York Stock Exchange accessed through Yahoo Finance ®. It will pull all daily opening, closing, high, and low prices for the given stock tickers and save them in dataframes under the same names. The last
function will extract only the last number of observations from the data sets. Here we are looking at the last 500 days. Every day you run this code, the last 500 days will change so the calculations could be different. Specifically we are looking only at the closing prices for each stock. The ROC
function will give us the daily returns for each of these stocks now saved as the variables msft_r and appl_r.
= c("AAPL", "MSFT")
tickers
getSymbols(tickers)
[1] "AAPL" "MSFT"
<- cbind(last(AAPL[,4], '500 days'), last(MSFT[,4], '500 days'))
stocks
$msft_r <- ROC(stocks$MSFT.Close)
stocks$aapl_r <- ROC(stocks$AAPL.Close)
stocks
head(stocks)
AAPL.Close MSFT.Close msft_r aapl_r
2019-02-26 43.5825 112.36 NA NA
2019-02-27 43.7175 112.17 -0.001692451 0.003092763
2019-02-28 43.2875 112.03 -0.001248876 -0.009884593
2019-03-01 43.7425 112.53 0.004453160 0.010456306
2019-03-04 43.9625 112.26 -0.002402217 0.005016874
2019-03-05 43.8825 111.70 -0.005000948 -0.001821436
Next, we just calculate the historical numbers we need for our calculations, namely the correlation between and the variance of the stocks. Instead of the correlation, we could also use the covariance directly. The cov
, var
, and cor
functions give us the covariance, variances, and correlations respectively. From there we just recreate the equation written above in code. Lastly, we use the qnorm
function to get the quantile from the normal distribution for our VaR calculation.
<- var(stocks$msft_r, na.rm=TRUE)
var.msft <- var(stocks$aapl_r, na.rm=TRUE)
var.aapl <- cov(stocks$msft_r, stocks$aapl_r, use="pairwise.complete.obs")
cov.m.a <- cor(stocks$msft_r, stocks$aapl_r, use="pairwise.complete.obs")
cor.m.a
= 0.01
VaR.percentile <- 100000
AAPL.inv <- 200000
MSFT.inv
<- (MSFT.inv/(MSFT.inv+AAPL.inv))^2*var.msft + (AAPL.inv/(MSFT.inv+AAPL.inv))^2*var.aapl + 2*(AAPL.inv/(MSFT.inv+AAPL.inv))*(MSFT.inv/(MSFT.inv+AAPL.inv))*cov.m.a
var.port
<- (AAPL.inv+MSFT.inv)*qnorm(VaR.percentile)*sqrt(var.port)
VaR.DN.port dollar(VaR.DN.port)
[1] "-$14,729.81"
If the number above is different than the number we calculated by hand, then it is simply a result of a different time period and different data underlying it. The code is written to always use the most up to date data for each stock.
Another great aspect of the VaR under the normality assumption is the ease of calculating any \(n\)-day VaR from the 1-day VaR. This is defined simply as \(VaR_n = \sqrt(n) \times VaR_1\). Another great reason why the normality assumption in the Delta-Normal approach makes the calculation of VaR numbers rather easy.
SAS
We will use the functions in the R section of the code to get the necessary data in a dataset called stocks. First, we will use PROC CORR
to get us the necessary information on the variances, covariances, and correlations. You could easily just write these numbers down, but we are going to use the out =
option to store the needed information into a dataset called covar_results. We then use the DATA
step to create MACRO variables that store the values of the covariance between and variances of the stocks.
proc corr data=SimRisk.stocks cov out=covar_results plots;
var msft_r aapl_r;
run;
data _null_;
set covar_results(where = (_type_ eq 'COV'));
if upcase(_name_) eq 'MSFT_R' then do;
call symput("var_msft",msft_r);
call symput("covar",aapl_r);
end;
if upcase(_name_) eq 'AAPL_R' then do;
call symput("var_aapl",aapl_r);
end;
run;
data _null_;
set covar_results(where = (_type_ eq 'CORR'));
if upcase(_name_) eq 'MSFT_R' then do;
call symput("corr",aapl_r);
end;
run;
2 Variables: | msft_r aapl_r |
---|
Covariance Matrix, DF = 498 | ||
---|---|---|
msft_r | aapl_r | |
msft_r | 0.0004619768 | 0.0004010742 |
aapl_r | 0.0004010742 | 0.0005560452 |
Simple Statistics | ||||||
---|---|---|---|---|---|---|
Variable | N | Mean | Std Dev | Sum | Minimum | Maximum |
msft_r | 499 | 0.00158 | 0.02149 | 0.78668 | -0.15945 | 0.13293 |
aapl_r | 499 | 0.00225 | 0.02358 | 1.12495 | -0.13771 | 0.11316 |
Pearson Correlation Coefficients, N = 499 Prob > |r| under H0: Rho=0 |
||||||
---|---|---|---|---|---|---|
msft_r | aapl_r | |||||
msft_r |
|
|
||||
aapl_r |
|
|
Next, we need to use PROC IML
to do the calculations by hand. PROC IML
is the interactive matrix language of SAS. It is similar in design to R. We start by defining some MACRO variables for the amount we invested in each stock as well as the desired VaR percentile. From there we invoke PROC IML
and put in calculations as we would in R. We print out the results of these equations that we defined above.
%let msft_position = 200000;
%let aapl_position = 100000;
%let var_percentile = 0.01;
proc iml;
title 'VaR Results';
msft_p_weight = &msft_position/(&msft_position + &aapl_position);
aapl_p_weight = &aapl_position/(&msft_position + &aapl_position);
P_variance = &var_msft*(msft_p_weight)**2 + &var_aapl*(aapl_p_weight)**2
+ 2*aapl_p_weight*msft_p_weight*&covar;
P_StdDev=sqrt(P_variance);
VaR_normal = (&msft_position + &aapl_position)*PROBIT(&var_percentile)*SQRT(P_variance);
print "Daily VaR (Percentile level: &var_percentile); Delta-Normal" VaR_normal[format=dollar15.2];
quit;
If the number above is different than the number we calculated by hand, then it is simply a result of a different time period and different data underlying it. The code is written to always use the most up to date data for each stock.
Another great aspect of the VaR under the normality assumption is the ease of calculating any \(n\)-day VaR from the 1-day VaR. This is defined simply as \(VaR_n = \sqrt(n) \times VaR_1\). Another great reason why the normality assumption in the Delta-Normal approach makes the calculation of VaR numbers rather easy.
Historical Simulation Approach
The historical simulation approach is a non-parametric (distribution free) approach to estimating the VaR and ES values. This approach, as the name states, depends solely on historical data. For example, if history suggests that only 1% of the time Apple’s daily returns were below -4%, then the 1% VaR for daily returns is just -4%. Essentially, we just find the quantiles of our historical data! Let’s work through some examples.
Single Position Example
Suppose you invested $100,000 in Apple today. You have 500 historical observations on Apple’s daily returns. You want to compute the daily, 1% VaR of your portfolio. All we have to do is find the 1% quantile of our 500 observations. To do this we simply calculate the portfolio’s value as if the 500 historical observations we had were possible future values of the Apple’s daily returns. We sort these 500 portfolio values from worst to best. The 1% of 500 days is 5 days, so we need to find a loss that is only exceeded 5 times. In other words, the 1% VaR would be the 6th observation in our sorted possible portfolio values as shown below:
Here we can see that our portfolio dropping 6.76% in value is the 6th worst occurrence.
Let’s see how to do this in each of our softwares!
R
It is rather easy to sort data in R. We simply use the order
function inside of the []
to resort the rows of the variable of interest. We then just use the head
function to define which elements we want to look at. Here we want the 6th element.
<- AAPL.inv*stocks$aapl_r[head(order(stocks$aapl_r), 6)[6]]
VaR.H.AAPL print(VaR.H.AAPL)
aapl_r
2020-02-27 -6760.263
SAS
We will use PROC IML
again to easily calculate this quantile in SAS. Again, we will read in our data that we obtained from R. We then calculate the portfolio values as we did before. Lastly, we just use the SORT
function from the CALL
statement to sort these returns. From there we just use the 6th observation.
proc iml;
use SimRisk.stocks var {aapl_r};
read all var _all_ into returns;
portfolio_return = &aapl_position*returns[,1];
call sort(portfolio_return,{1});
number_of_observations = nrow(portfolio_return);
VaR_historical = portfolio_return[6,1];
print "Daily VaR (Percentile level: &var_percentile); Historical" VaR_historical[format=dollar15.2];
title;
quit;
Two Position Example
We can easily extend this to a two position portfolio example by taking the same approaches. Suppose you invested $200,000 in Microsoft and $100,000 in Apple today. You have 500 historical observations on both returns. Simply calculate the portfolio’s value as if each of the previous 500 days is a possible scenario for your one day return on this portfolio. We then sort these 500 possible scenarios and the 1% VaR will be the 6th observation as shown below:
Let’s see how to do this in each of our softwares!
R
Just like with the one position portoflio, it is rather easy to sort data in R. We simply use the order
function inside of the []
to resort the rows of the variable of interest. We then just use the head
function to define which elements we want to look at. Here we want the 6th element.
$port_v <- MSFT.inv*stocks$msft_r + AAPL.inv*stocks$aapl_r
stocks
<- stocks$port_v[order(stocks$port_v)[6]]
VaR.H.port dollar(as.numeric(VaR.H.port))
[1] "-$18,089.40"
SAS
Just like with the one position portfolio, we will use PROC IML
again to easily calculate this quantile in SAS. Again, we will read in our data that we obtained from R. We then calculate the portfolio values as we did before. Lastly, we just use the SORT
function from the CALL
statement to sort these returns. From there we just use the 6th observation.
proc iml;
use SimRisk.stocks var {msft_r aapl_r};
read all var _all_ into returns;
portfolio_return = &msft_position*returns[,1] + &aapl_position*returns[,2];
call sort(portfolio_return,{1});
number_of_observations = nrow(portfolio_return);
VaR_historical = portfolio_return[6,1];
print "Daily VaR (Percentile level: &var_percentile); Historical" VaR_historical[format=dollar15.2];
title;
quit;
Stressed VaR and ES
There are some key assumptions we are making with the historical simulation approach:
- The past will repeat itself.
- The historical period covered is long enough to get a good representation of “tail” events.
These have lead to alternative version of the historical simulation approach.
One of these approaches is the stressed VaR (and ES) approach. Instead of basing the calculations on the movements in market variables over the last \(n\) days, we can base calculations on movements during a period in the past that would have been particularly bad for the current portfolio. Essentially, we look for the worst collection of \(n\) days in a row in our data. That is where we will get our stressed VaR instead of the last \(n\) days.
Let’s see how to do this in each of our softwares!
R
The only difference between the stressed approach and the historical simulation approach is the data that we use. In the code below we will get a different collection of data then just the previous 500 days. First, we aggregate all of our data back to 2007 in a new dataframe called stocks_stressed. Again, we calculate the daily returns and daily portfolio values of holding $200,000 in Microsoft and $100,000 in Apple. We then use the SMA
function to calculate the moving average of the portfolio value across 500 days for every observation in the data. Essentially, we are trying the “worst” 500 days in terms of our portfolio values. These will be what we build the VaR calculation off of.
<- cbind(AAPL[, 4], MSFT[, 4])
stocks_stressed $msft_r <- ROC(stocks_stressed$MSFT.Close)
stocks_stressed$aapl_r <- ROC(stocks_stressed$AAPL.Close)
stocks_stressed$port_v <- MSFT.inv*stocks_stressed$msft_r + AAPL.inv*stocks_stressed$aapl_r
stocks_stressed
$ma <- SMA(stocks_stressed$port_v, 500)
stocks_stressed<- stocks_stressed[seq(order(stocks_stressed$ma)[1]-499,order(stocks_stressed$ma)[1],1)] stocks_stressed
From there we use the same approach to calculating the VaR.
<- stocks_stressed$port_v[order(stocks_stressed$port_v)[6]]
stressed.VaR.H.port dollar(as.numeric(stressed.VaR.H.port))
[1] "-$18,639.23"
We can see that this number is slightly larger than the traditional historical simulation approach.
SAS
The only difference between the stressed approach and the historical simulation approach is the data that we use. As with the previous example we will use R to get the data and then analyze it in SAS. From there we use the same approach to calculating the VaR.
proc iml;
use SimRisk.stocks_s var {msft_r aapl_r};
read all var _all_ into returns;
portfolio_return = &msft_position*returns[,1] + &aapl_position*returns[,2];
call sort(portfolio_return,{1});
number_of_observations = nrow(portfolio_return);
VaR_historical = portfolio_return[6,1];
print "Daily VaR (Percentile level: &var_percentile); Historical" VaR_historical[format=dollar15.2];
title;
quit;
We can see that this number is slightly larger than the traditional historical simulation approach.
Multiple Day VaR
With the Delta-Normal approach is was easily mathematically to extend the 1 day VaR calculations to the \(n\)-day VaR. When extending to multiple days using the historical simulation approach you could do one of the following approaches:
- Calculate \(n\) day returns first, then run the historical simulation approach(es) as desired.
- Use any of the historical simulation approaches, but consider the daily returns as starting points. Record the return of the next consecutive \(n\) days to get a real example of \(n\) day returns for simulation.
Simulation
The last approach to estimating the VaR and ES would be through simulation. We simulate the value of the portfolio using some statistical / financial model that explains the behavior of the random variables of interest. If we have “enough” simulations then we have simulated the distribution of the portfolio’s value. From there we can find the VaR or ES at any point we desire. Simulation approaches allow us to control for non-normal distributions, non-linear relationships, multidimensional problems, and history changing.
Using simulation assumes a couple of key aspects:
- The choice of distribution is an accurate representation of the reality.
- The number of draws is enough to capture the tail behavior.
Let’s walk through the approach for our two position portfolio. If we have $200,000 invested in Microsoft and $100,000 invested in Apple, we just need to pick a distribution for their returns to simulate. Assume a normal distribution for each of these stocks returns with their historical mean and standard deviation. We can draw 10,000 observations from each of these distributions.
We can add in the correlation structure to these returns through Cholesky decomposition. For more details on Cholesky decomposition and adding correlation to simulations, please see the code notes for Introducion to Simulation.
From there, we just need to calculate the quantile for this distribution. With 10,000 simulations, the 1% VaR would be the \(101^{st}\) observation.
Due to the normality assumption in this example we could have easily used the Delta-Normal approach instead, but it would at least illustrates the simulation approach.
Let’s see how to do this in each of our softwares!
R
Running this simulation is rather easy to do in R. First, we define our correlation structure (here R) and calculate the Cholesky decomposition of this matrix to multiply into our data. Next, we simulate 10,000 draws from the respective normal distributions for our Microsoft and Apple returns using the rnorm
function. We multiply in the correlation structure and then simply calculate the return on the portfolio of these two sets of returns. From there it is a simple call of the quantile
function to find the quantile of the distribution to get the VaR. A histogram of the distribution of changes in the portfolio is also provided.
<- 10000
n.simulations <- matrix(data=cbind(1,cor.m.a, cor.m.a, 1), nrow=2)
R <- t(chol(R))
U
<- rnorm(n=n.simulations, mean=0, sd=sqrt(var.msft))
msft.r <- rnorm(n=n.simulations, mean=0, sd=sqrt(var.aapl))
aapl.r <- cbind(msft.r, aapl.r)
Both.r <- U %*% t(Both.r)
port.r <- t(port.r)
port.r
<- MSFT.inv*port.r[,1] + AAPL.inv*port.r[,2]
value.change <- (MSFT.inv + AAPL.inv) + value.change
value
<- quantile(value.change, VaR.percentile, na.rm=TRUE)
VaR <- dollar(VaR)
VaR.label
hist(value.change/1000, breaks=50, main='1 Day Value Change Distribution', xlab='Value Change', col="lightblue")
= c(-40, -30, -20, -10, 0, 10, 20, 30, 40, 50, 60)
breaks axis(1, at = breaks, labels = paste("$", breaks, "K", sep = ""))
abline(v = VaR/1000, col="red", lwd=2)
mtext(paste("Value at Risk",VaR.label, sep=" = "), at=VaR/1000, col="red")
As you can see from above, the one day, 1% VaR for this portfolio (assuming normality of returns for each asset) is $14,476.19.
SAS
Running this simulation is a little complicated in SAS due to correlation structure we are imposing on the returns. For more detail on the code below and the approach to adding in correlation structures in simulations in SAS please see the code notes for Introducion to Simulation. First, we define our correlation structure using the DATA
step. This will repeat the desired correlation matrix the number of times we are simulating. Next, we again use the DATA
step to define starting points for each of the variables in the simulation - namely the returns for Microsoft and Apple. From there PROC MODEL
simulates and correlates the necessary returns.
data Corr_Matrix;
do i=1 to 10000;
_type_ = "corr";
_name_ = "msft_r";
msft_r = 1.0;
aapl_r = &corr;
output;
_name_ = "aapl_r";
msft_r = &corr;
aapl_r = 1.0;
output;
end;
run;
data Naive;
do i=1 to 10000;
msft_r=0;
aapl_r=0;
output;
end;
run;
proc model noprint;
msft_r = 0;
errormodel msft_r ~Normal(&var_msft);
aapl_r = 0;
errormodel aapl_r ~Normal(&var_aapl);
solve msft_r aapl_r/ random=1 sdata=Corr_Matrix
data=Naive out=mc_stocks(keep=msft_r aapl_r i);
by i;
run;
quit;
data mc_stocks;
set mc_stocks;
by i;
if first.i then delete;
rename i=simulation;
value_change = &msft_position*msft_r + &aapl_position*aapl_r;
value = &msft_position + &aapl_position + value_change;
format value_change dollar15.2;
run;
%let var_clevel=%sysevalf(100*&var_percentile);
proc univariate data=mc_stocks;
var value_change;
format value_change dollar15.2;
output out=percentiles pctlpts = &var_clevel pctlpre=P;
histogram value_change / kernel normal;
ods select Quantiles;
run;
Quantiles (Definition 5) | |
---|---|
Level | Quantile |
100% Max | 26189.6834 |
99% | 14542.6342 |
95% | 10210.8088 |
90% | 8113.6385 |
75% Q3 | 4169.7244 |
50% Median | -53.3739 |
25% Q1 | -4251.9856 |
10% | -8178.0204 |
5% | -10484.2905 |
1% | -14628.3288 |
0% Min | -25310.7449 |
As you can see from above, the one day, 1% VaR for this portfolio (assuming normality of returns for each asset) is $14,615.71.
Comparison of Three Approaches
The following is a summary comparison for the three approaches - Delta-Normal, historical simulation, and simulation.
Confidence Intervals for VaR
Value at risk calculations in any of the above approaches are just estimates. All estimates have a notion of variability. Therefore, we can calculate confidence intervals for each of the above approaches.
When you have a normal distribution (the Delta-Normal approach) there is a known mathematical equation for the confidence interval around a quantile. It is derived as a confidence interval around the standard deviation \(\sigma\) followed by multiplying this \(\sigma\) by the corresponding quantiles of interest on the normal distribution. The confidence interval for \(\sigma\) is as follows:
\[ CI(\hat{\sigma}) = (\sqrt{\frac{(n-1)\hat{\sigma}^2}{\chi^2_{\alpha / 2, n-1}}}, \; \sqrt{\frac{(n-1)\hat{\sigma}^2}{\chi^2_{1 - \alpha / 2, n-1}}}) \]
For non-normal distributions or historical / simulation approaches, the bootstrap method of confidence intervals is probably best. The bootstrap approach to confidence intervals is as follows:
- Resample from the simulated data using their empirical distribtion; or rerun the simulation severeal times.
- In each new sample (from step 1) calculate the VaR.
- Repeat steps 1 and 2 many times to get several VaR estimates. Use these estimates to get the expected VaR and its confidence interval.
Let’s see both of these approaches in our softwares!
R
Let’s first start with the direct normal distribution calculation approach. Under the Delta-Normal approach you can easily calculate the confidence interval for the value at risk based on the equation defined above. The code below just recreates that function using the qchisq
and qnorm
functions were necessary to get values from the \(\chi^2\) and normal distributions.
<- sqrt(var.port*(length(stocks$AAPL.Close)-1)/qchisq((1-(VaR.percentile/2)),length(stocks$AAPL.Close)-1) )
sigma.low <- sqrt(var.port*(length(stocks$AAPL.Close)-1)/qchisq((VaR.percentile/2),length(stocks$AAPL.Close)-1) )
sigma.up
<- (AAPL.inv+MSFT.inv)*qnorm(VaR.percentile)*sqrt(var.port)
VaR.DN.port <- (AAPL.inv+MSFT.inv)*qnorm(VaR.percentile)*(sigma.low)
VaR.L <- (AAPL.inv+MSFT.inv)*qnorm(VaR.percentile)*(sigma.up)
VaR.U
print(paste("The VaR is ", dollar(VaR.DN.port), " with confidence interval (", dollar(VaR.L), " , ", dollar(VaR.U), ")", sep = "" ))
[1] "The VaR is -$14,729.81 with confidence interval (-$13,614.27 , -$16,029.05)"
To perform the bootstrap approach in R, we first need to define the number of bootstrap samples as well as the size of each of these samples. From there we loop through the simulation values we already obtained earlier called value.change using a for
loop. Using the sample
function we can sample values from our original simulation and calculate the VaR of this new sub-sample using the quantile
function at our percentile. We repeat this process over and over until we form many different values for our VaR from which to build our confidence interval. From there we simply look at the values that define the middle 95% of all of our VaR values, again using the quantile
function to define the upper and lower bounds of our confidence interval. Lastly, we plot the VaR as well as its confidence interval bounds on a histogram of the value.change distribution.
<- 1000
n.bootstraps <- 1000
sample.size
<- rep(0,n.bootstraps)
VaR.boot for(i in 1:n.bootstraps){
<- sample(value.change, size=sample.size)
bootstrap.sample <- quantile(bootstrap.sample, VaR.percentile, na.rm=TRUE)
VaR.boot[i]
}
<- quantile(VaR.boot, 0.975, na.rm=TRUE)
VaR.boot.U <- quantile(VaR.boot, 0.025, na.rm=TRUE)
VaR.boot.L
print(paste("The VaR is ", dollar(mean(VaR.boot)), " with confidence interval (", dollar(VaR.boot.L), " , ", dollar(VaR.boot.U), ")", sep = "" ))
[1] "The VaR is -$14,033.25 with confidence interval (-$15,606.72 , -$12,821.69)"
hist(value.change/1000, breaks=50, main='1 Day Value Change Distribution', xlab='Value Change', col="lightblue")
= c(-20, -10, 0, 10, 20)
breaks axis(1, at = breaks, labels = paste("$", breaks, "K", sep = ""))
abline(v = VaR/1000, col="red", lwd=2)
mtext(paste("Value at Risk",VaR.label, sep=" = "), at = VaR/1000, col="red")
abline(v = VaR.boot.L/1000, col="blue", lwd=2, lty="dashed")
abline(v = VaR.boot.U/1000, col="blue", lwd=2, lty="dashed")
SAS
It is actually rather easy to calculate the confidence intervals for a percentile in SAS under the normality assumption. PROC UNIVARIATE
and the cipctlnormal
option calculates confidence intervals for percentiles of any variable. Here we define the value_change variable from our dataset to make this calculation.
proc univariate data=mc_stocks cipctlnormal;
var value_change;
ods select Quantiles;
run;
Quantiles (Definition 5) | |||
---|---|---|---|
Level | Quantile |
95% Confidence Limits Assuming Normality |
|
100% Max | 22706.234 | ||
99% | 15013.916 | 14641.3 | 15121.9 |
95% | 10615.659 | 10349.6 | 10732.6 |
90% | 8153.985 | 8058.8 | 8395.7 |
75% Q3 | 4252.741 | 4222.5 | 4499.1 |
50% Median | 82.039 | -60.0 | 189.6 |
25% Q1 | -4188.497 | -4369.5 | -4092.9 |
10% | -8041.911 | -8266.1 | -7929.2 |
5% | -10312.626 | -10603.0 | -10220.0 |
1% | -15076.400 | -14992.3 | -14511.7 |
0% Min | -23546.838 |
To perform the bootstrap approach in SAS, we first need to define the number of bootstrap samples as well as the size of each of these samples. From there we use PROC SURVEYSELECT
to sample from our dataset many times. The method = srs
option specifies that we want to use simple random sampling. We want sample sizes that are 10% of the size of the simulation which is defined in the samprate =
option. Lastly, we repeat this sampling over and over again using the rep =
option. Make sure to put noprint
so you don’t see results from each of these 1000 samples!
Next, we just calculate percentiles using PROC UNIVARIATE
for each of the samples (called replicates) using the by
statement. We will output the percentiles from each of these calculations using the output
statement with the out =
option. Specifically, we want the 1% quantile (our VaR values) which we can define using the pctlpts
option. We will label this quantile as P1. We define this name using the pctlpre
option to define the prefix on the number of the quantile (here 1). Another PROC UNIVARIATE
call will give us the percentiles of all of these VaR calculations from the previous PROC UNIVARIATE
. Lastly, we print these results.
%let n_bootstraps=1000;
%let bootstrap_prop=0.1;
%let var_percentile = 0.01;
%let var_clevel=%sysevalf(100*&var_percentile);
proc surveyselect data=mc_stocks out=outboot seed=12345 method=srs
samprate=&bootstrap_prop rep=&n_bootstraps noprint;
run;
proc univariate data=outboot noprint;
var value_change;
output out=boot_var pctlpts = &var_clevel pctlpre=P;
by replicate;
run;
proc univariate data=boot_var;
var P1;
output out=var_ci pctlpts = 2.5 97.5 pctlpre=P;
ods select Quantiles;
run;
proc print data=var_ci;
run;
Expected Shortfall
The ES is a conditional expectation that tries to answer what you should expect to lose if your loss exceeds the VaR. It is the expected (average) value of the portfolio in the circled region below:
The main question is how to estimate the distribution that we will calculate the average of the worst case outcomes. There are three main approaches to estimating the distribution in ES and they are the same as VaR:
- Delta-Normal (Variance-Covariance) Approach
- Historical Simulation Approach(s)
- Simulation Approach
The best part is that extending these approaches to include expected shortfall from what we already covered for value at risk is rather straight forward. Let’s take a look at each of these.
Delta-Normal
Just like the VaR calculation for the Delta-Normal approach, the ES has a known equation. For a normal distribution, the average (or expected value) in a tail of the distribution is defined as follows:
\[ ES = CVaR = \mu - \sigma \times \frac{e^{\frac{-q^2_\alpha}{2}}}{\alpha \sqrt(2\pi)} \] with \(\sigma\) being the standard deviation of the data, \(\alpha\) being the percentile of interest (1% for example), and \(q_\alpha\) as the tail percentile from the standard normal distribution (-2.33 for example).
Let’s see how to code this into our softwares!
R
Just as with the VaR, the ES is easy to hard code into R directly. The function below repeats the same function as defined above.
<- (0 - sqrt(var.port)*exp(-(qnorm(VaR.percentile)^2)/2)/(VaR.percentile*sqrt(2*pi)))*(AAPL.inv+MSFT.inv)
ES.DN.port dollar(ES.DN.port)
[1] "-$16,875.42"
Again, this value is saying that if the worst 1% of cases happens, we expect to lose $16,874.49 on average.
SAS
Just as with the VaR, the ES can be coded into SAS directly using PROC IML
. The function below repeats the same function as defined above.
%let msft_position = 200000;
%let aapl_position = 100000;
%let var_percentile = 0.01;
proc iml;
title 'VaR Results';
msft_p_weight = &msft_position/(&msft_position + &aapl_position);
aapl_p_weight = &aapl_position/(&msft_position + &aapl_position);
P_variance = &var_msft*(msft_p_weight)**2 + &var_aapl*(aapl_p_weight)**2
+ 2*aapl_p_weight*msft_p_weight*&covar;
P_StdDev=sqrt(P_variance);
VaR_normal = (&msft_position + &aapl_position)*PROBIT(&var_percentile)*SQRT(P_variance);
pi=3.14159265;
ES_normal = -(&msft_position + &aapl_position)*SQRT(P_variance)*exp(-0.5*(PROBIT(&var_percentile))**2)/(&var_percentile.*sqrt(2*pi));
print "Daily CVaR/ES (Percentile level: &var_percentile); Delta-Normal" ES_normal[format=dollar15.2];
quit;
Again, this value is saying that if the worst 1% of cases happens, we expect to lose $16,873.67 on average.
Historical
We can easily extend the historical simulation approach for VaR to ES. Let’s look at our two position portfolio example. Suppose you invested $200,000 in Microsoft and $100,000 in Apple today. You have 500 historical observations on both returns. Simply calculate the portfolio’s value as if each of the previous 500 days is a possible scenario for your one day return on this portfolio. We then sort these 500 possible scenarios and the 1% ES will be the average of these 5 observations that make up the 1%:
The average of these 5 observations is -$28,154.09. Again, this value is saying that if the worst 1% of cases happens, we expect to lose $28,154.09 on average. Let’s see how to do this in each of our softwares!
R
Just as with the historical simulation approach before for VaR, we can easily isolate the worst five observations using the head
and order
functions followed by using the mean
to take the average.
<- mean(stocks$port_v[head(order(stocks$port_v), 5)])
ES.H.port dollar(as.numeric(ES.H.port))
[1] "-$28,154.09"
Again, this value is saying that if the worst 1% of cases happens, we expect to lose $28,154.09 on average.
SAS
Just as with the historical simulation approach before for VaR, we can easily isolate the worst five observations using PROC IML
. Inside of this PROC we can calculate the mean of the worst five observations.
proc iml;
use SimRisk.stocks_s var {msft_r aapl_r};
read all var _all_ into returns;
portfolio_return = &msft_position*returns[,1] + &aapl_position*returns[,2];
call sort(portfolio_return,{1});
number_of_observations = nrow(portfolio_return);
VaR_historical = portfolio_return[6,1];
ES = sum(portfolio_return[1:6,1])/(6-1);
print "Daily CVaR/ES (Percentile level: &var_percentile level); Historical" ES[format=dollar15.2];
title;
quit;
Again, this value is saying that if the worst 1% of cases happens, we expect to lose $28,212.32 on average.
Simulation
Simulation is just an extension of what we did earlier to calculate the VaR. First, follow the steps described earlier to create the 10,000 simulated, sorted, portfolio values for the VaR calculation. Then simply just take the average of all the values that are worst than the VaR. For 10,000 simulations, the ES would be the average of the worst 100 observations.
Let’s see how to do this in each of our softwares!
R
Just as with simulation in R, we can easily get the final distribution for our portfolio changes, called value.change, and just isolate the worst observations through boolean logic. We just take the mean
function of all the observations for value.change that are lower than the VaR value.
<- mean(value.change[value.change < VaR], na.rm=TRUE)
ES dollar(ES)
[1] "-$16,320.06"
<- hist(value.change/1000, breaks=50, plot=FALSE)
h <- cut(h$breaks, c(-Inf, VaR/1000, Inf))
cuts plot(h, col = cuts, main='1 Day Value Change Distribution', xlab='Value Change')
= c(-20, -10, 0, 10, 20, 30)
breaks axis(1, at = breaks, labels = paste("$", breaks, "K", sep = ""))
abline(v = VaR/1000, col="red", lwd=2)
mtext(paste("Value at Risk",VaR.label, sep=" = "), at=VaR/1000, col="red")
Again, this value is saying that if the worst 1% of cases happens, we expect to lose $16,041.57 on average. This would be the average in the dark shaded tail region in the histogram above.
SAS
Just as with simulation in SAS, we can easily get the final distribution for our portfolio changes, called value_change in our mc_stocks dataset, and just isolate the worst observations through the WHERE
statement in PROC MEANS
. This will apply the mean of all the observations for value_change that are lower than the VaR value.
proc print data=percentiles;
run;
data _null_;
set percentiles;
call symput("var_p",P1);
run;
proc means data=mc_stocks mean;
var value_change;
where value_change < &var_p;
run;
Again, this value is saying that if the worst 1% of cases happens, we expect to lose $16,921.19 on average.
Recent Developments
The field of risk management is ever changing and growing quickly. The following couple of sections outline some of the latest additions to the field of risk management - extreme value theory (EVT) and newer VaR calculations.
Extreme Value Theory
There are some complications to the expected shortfall calculation. First, ES estimates tend to be less stable than the VaR for the same confidence level due to sample size limitations. ES requires a large number of observations to generate a reliable estimate. Due to this, ES is also more sensitive to estimation errors than VaR because is substantially depends on the accuracy of the tail model used in the distribution.
We try so hard to estimate the full distribution. However, our only care is the tail of the distribution so we will turn our attention on just estimating the tail. This is the value of extreme value theory (EVT). EVT provides the theoretical foundation for building statistical models describing extreme events. This is used in many fields such as finance, structual engineering, traffic prediction, weather prediction, and geological prediction.
EVT provides the distribution for the following two things:
Block Maxima (Minima) - the maximum (or minimum) the variable takes in successive periods.
Exceedances - the values that exceed a certain threshold.
For VaR and ES calculations we will focus on the exceedances piece of EVT. The approach of exceedances tries to understand the distribution of values that exceed a certain threshold. Instead of isolating the tail of an overall distribution (limiting the values) we are trying to build a distribution for the tail events themselves.
One of the popular distributions for this is the generalized Pareto. This distribution is named after Italian engineer and economist Vilfredo Pareto. It came into popularity with the “Pareto Principle” which is more commonly known as the “80-20” Rule. Pareto noted in 1896 that 80% of the land of Italy was owned by 20% of the population. Richard Koch authored the book The 80/20 Principle to illustrate some common applications. The plot below shows some example Pareto distributions:
This can be applied to value at risk and expected shortfall to provide more accurate estimates of VaR and ES, but the math is very complicated. We need to use maximum likelihood estimation to find which generalized Pareto distribution fits our data the best - which parameters \(\xi\) and \(\beta\) are optimal to maximize:
\[ f(v) = \sum_{i=1}^{n_u} \log(\frac{1}{\beta} (1 + \frac{\xi(v_i - u)}{\beta})^{\frac{-1}{\xi-1}} ) \]
The calculation for VaR from the Pareto distribution is:
\[ VaR = u + \frac{\beta}{\xi}([\frac{n}{n_u} (1-q)]^{-\xi}) \]
The calculation of ES from the Pareto distribution is:
\[ ES = \frac{VaR + \beta - \xi u}{1-\xi} \]
Let’s walk through the approach for our two position portfolio. If we have $200,000 invested in Microsoft and $100,000 invested in Apple, we can use the 500 observations for each stocks’ returns to estimate the generalized Pareto distribution parameters. Assume a normal distribution for each of these stocks returns with their historical mean and standard deviation. From there we can just estimate the VaR and ES from the above equations.
Let’s see how to this in each of our softwares!
R
To get the estimated parameters from the Pareto distribution we can use the gpdFit
function. The first input is the data itself (careful, the function requires positive values) and the second input input is the type = c("mle")
option to specify using maximum likelihood estimation to estimate the parameters. From there we use the tailRisk
function to estimate the VaR and ES from the output of the gpdFit
function.
<-gpdFit(as.numeric(stocks$port_v[-1])*-1, type = c("mle"))
pareto.fit tailRisk(pareto.fit, prob = 0.99)
Prob VaR ES
95% 0.99 19419.31 27720.33
dollar(tailRisk(pareto.fit, prob = 0.99)[,2]*-1)
[1] "-$19,419.31"
dollar(tailRisk(pareto.fit, prob = 0.99)[,3]*-1)
[1] "-$27,720.33"
We can see the values from the Pareto estimation above. To compare this to the normal distribution, the following plot shows the estimated distribution (in the histogram) of the Pareto distribution compared to the theoretical normal distribution (the density line) for the same data.
hist(-1*rgpd(n = 10000, mu = pareto.fit@parameter$u, beta = pareto.fit@fit$par.ests[2], xi = pareto.fit@fit$par.ests[1]), breaks = 50, main = "Comparison of Simulated tail to Normal", xlab = "Portfolio Value", freq = FALSE, yaxt = "n", ylab = "", col = "lightblue")
curve(dnorm(x, mean(stocks$port_v, na.rm = TRUE), sd(stocks$port_v, na.rm = TRUE)), add = TRUE, col = 'red', lwd = 2)
As we can see above, the data estimates a distribution with a much thicker tail than the normal distribution would otherwise account for. This aligns with the historical simulation approach that had a much riskier value for VaR and ES compared to the Delta-Normal approach. All of the approaches are compared in the table below:
SAS
In SAS, we first need to isolate the tail fo the data to fit the Pareto distribution with. SAS requires that the data values are all positive so we convert our negative values to positive using the DATA
step and multiplying our values by -1. Next, we use PROC UNIVARIATE
to calculate the percentiles of our data. We want to isolate the 5% tail to build our Pareto distribution off of. We specify the variable of interest, neg_port_v, in our VAR
statement. We then use the OUTPUT
statement to save the percentiles into a new dataset called percentiles by using the pctlpts = 95
and pctlpre = P
options we have defined before. Next, we use another DATA
step to create a MACRO variable for the value of the 5% quantile of interest (remember we are working with the 95% instead of 5% because we flipped all of our values when taking the negative). We then use a last DATA
step to delete all the data values not in the tail of interest.
%let var_percentile=0.01;
data neg_stocks;
set SimRisk.stocks;
neg_port_v = -1*port_v;
run;
proc univariate data=neg_stocks;
var neg_port_v;
output out=percentiles pctlpts = 95 pctlpre=P;
ods select Quantiles;
run;
proc print data=percentiles;
run;
data _null_;
set percentiles;
call symput("tail",P95);
run;
data stocks_tail;
set neg_stocks;
if neg_port_v <= &tail then delete;
run;
Quantiles (Definition 5) | |
---|---|
Level | Quantile |
100% Max | 45661.487 |
99% | 21134.514 |
95% | 9002.725 |
90% | 6101.344 |
75% Q3 | 1908.307 |
50% Median | -821.581 |
25% Q1 | -3565.546 |
10% | -5890.933 |
5% | -8902.751 |
1% | -20184.071 |
0% Min | -37901.543 |
Now we can use PROC UNIVARIATE
to fit our data to the Pareto distribution. To do this we use the HISTOGRAM
statement on our variable neg_port_v with the pareto(theta=&tail percent=80)
option. This will fit the parameters of the Pareto distribution to our dataset. We can output these parameters using the ODS OUTPUT
statements. The output from PROC UNIVARIATE
provides the parameter estimates for the Pareto distribution as well as the estimate of our quantile of interest, the VaR. We save this VaR as a MACRO variable and print it out using PROC IML
.
proc univariate data=stocks_tail;
histogram neg_port_v / pareto(theta=&tail percent=80);
ods output ParameterEstimates=PE FitQuantiles=FQ;
ods select histogram ParameterEstimates FitQuantiles;
run;
data _null_;
set PE;
if upcase(Symbol) eq 'THETA' then do;
call symput("threshold",Estimate);
end;
if upcase(Symbol) eq 'SIGMA' then do;
call symput("beta",Estimate);
end;
if upcase(Symbol) eq 'ALPHA' then do;
call symput("xi",Estimate);
end;
run;
data _null_;
set FQ;
call symput("VaR",EstQuantile);
run;
proc iml;
title 'EVT Results';
VaR_EVT = &VaR*-1;
print "Daily VaR (Percentile level: &var_percentile); EVT" VaR_EVT[format=dollar15.2];
quit;
Parameters for Pareto Distribution | ||
---|---|---|
Parameter | Symbol | Estimate |
Threshold | Theta | 9002.725 |
Scale | Sigma | 5984.027 |
Shape | Alpha | -0.12531 |
Mean | 15844.01 | |
Std Dev | 7902.856 |
Quantiles for Pareto Distribution | ||
---|---|---|
Percent | Quantile | |
Observed | Estimated | |
80.0 | 21134.5 | 19673.5 |
Lastly, we use one final PROC IML
call to calculate the ES using the equation defined above.
proc iml;
title 'EVT Results';
VaR_EVT = &VaR*-1;
ES_EVT = ((&VaR + &beta - &xi*&threshold)/(1-&xi))*-1;
print "Daily CVaR/ES (Percentile level: &var_percentile); EVT" ES_EVT[format=dollar15.2];
quit;
These values align with the historical simulation approach that had a much riskier value for VaR and ES compared to the Delta-Normal approach. All of the approaches are compared in the table below:
VaR Extensions
The last section just briefly touches on some of the latest variations and adaptions of the value at risk metric. There are many additions to VaR calculations:
- Delta-Gamma VaR
- Delta-Gamma Monte Carlo Simulation
- Marginal VaR
- Incremental VaR
- Component VaR
Let’s discuss each briefly in concept.
Delta-Gamma VaR
The Delta-Gamma approximation approach tries to improve on the Delta-Normal approach by taking into account higher derivatives than the first derivative only. In the expansion of the derivatives we can look at the first two:
\[ dV = \frac{\partial V}{\partial RF}\cdot dRF + \frac{1}{2}\cdot \frac{\partial^2 V}{\partial RF^2}\cdot dRF^2 + \cdots \]
\[ dV = \Delta \cdot dRF + \frac{1}{2} \cdot \Gamma \cdot dRF^2 \]
Essentially, this approach takes the variance component into account in building the Gamma portion of the equation. Delta-Normal typically underestimates VaR when assumptions do not hold. The Delta-Gamma approach tries to correct for this, but it is computationally more intensive.
Delta-Gamma Monte Carlo
The assumption of normality still might not be reliable even with the Delta-Gamma adjustment to Delta-Normal. The Delta-Gamma MC simulation approach simulates the risk factor before using Taylor-series expansion to create simulated movements in the portfolio’s value. Just like with regular simulation, the VaR is calculated using the simulated distribution of the portfolio.
For a comparison, if you have a large number of things to evaluate in a portfolio with few options, the Delta-Normal approach is fast and efficient enough. However, if you have only a few sources of risk and substantial complexity, the Delta-Gamma approach is better. If you have both a large number of risk factors and substantial complexity, simulation is probably the best approach.
Marginal VaR
The marginal VaR tries to answer the question of how much the VaR will change if we invest one more dollar in a position of the portfolio. In other words, the first derivative of VaR with respect to the weight of a certain position in the portfolio. Assuming normality, this calculation is quite easy:
\[ \Delta VaR = \alpha \times \frac{Cov(R_i, R_p)}{\sigma_p} \]
Incremental VaR
The incremental VaR tries to measure the change in VaR due to the addition of a new position in the portfolio. This is used whenever an institution wants to evaluate the effect of a proposed trade or change in the portfolio of interest. This is slightly different from the marginal VaR that only takes into account an additional dollar of one position instead of adding or subtracting an entire (or multiple) positions.
This is trickier to calculate as you now need to calculate the VaR under both portfolios and take their difference. There are Taylor series approximations to his, but they are not as accurate as calculating the full VaR for both portfolios and looking at the difference.
Component VaR
The component VaR decomposes the VaR into its basic components ina way that takes into account the diversification of the portfolio. It is a “partition” of the portfolio VaR that indicates the change of VaR if a given component was deleted. The component VaR is defined in terms of the marginal VaR:
\[ VaR_{Comp} = \Delta VaR \times (\$ \; value \; of \; component) \]
The sum of all component VaR’s is the total portfolio VaR.