VaR Disaggregation in R

This article is a practical and real example of how value-at-risk, marginal VaR, betas, undiversified VaR and component VaRs are calculated.  Credit to Pawel Lachowicz for the idea for this article, he has done the same thing in Python here: http://www.quantatrisk.com/2015/01/18/applied-portfolio-value-at-risk-decomposition-1-marginal-and-component-var/

The level of detail here may not be required for the PRM exam, for that just the previous tutorial will do (the one with the formulae and explanations).  This article will be useful for practising risk analysts – we will extract real end-of-day prices, and perform our analysis on those in R.  To run the R code, you will need to install R on your machine.  The good thing with R is that it does not require administrative privileges, so if you can download it from Cran, you can run it.  If you are looking for an introduction to R, you can look at this 20 minute video I posted a few years ago: https://www.youtube.com/user/riskprep

This is how we will do our analysis:

  1. Download price data for all our securities from Quandl.com.  Quandl offers an R package allowing R to download data for a particular stock (or currency, or commodity).  
  2. The price data has a large number of columns.  We drop all the columns except the closing price.
  3. We do this one by one for each equity asset in our portfolio.  We then merge the time series.
  4. Then we calculate daily log returns.  R does that very elegantly – with just a one line command.
  5. Now that we have returns data for the period we are interested in, we can calculate the covariance and correlation matrices.
  6. We load up the dollar value for each equity in our portfolio in a column vector.
  7. Now we have everything we need, and we calculate:
  1. Portfolio weights (as a percentage)
  2. Porfolio returns
  3. Covariance matrix
  4. Each stock’s covariance to the portfolio
  5. Portfolio volatility, in percent and in dollars
  6. Portfolio VaR, in percent and dollars
  7. Volatility of each stock in the porfolio
  8. VaR for each stock
  9. The total undiversified VaR
  10. Beta for each stock
  11. Marginal VaR
  12. Component VaR

All using the same formulae that have been used in the previous tutorial.

Code:

# The first two lines instal xts and Quandl - you will need to run these only once.
install.packages("xts")
install.packages("Quandl")
library(xts)
library(Quandl)
# d1 to d7 are time series variables that store the data downloaded from Quandl.
# We drop all columns other than end of day closing price.
d1 = Quandl("WIKI/AAPL", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d1 = d1[,11]
colnames(d1)[1] = "AAPL"
d2 = Quandl("WIKI/DISCA", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d2 = d2[,11]
colnames(d2)[1] = "DISCA"
d3 = Quandl("WIKI/IBM", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d3 = d3[,11]
colnames(d3)[1] = "IBM"
d4 = Quandl("WIKI/JNJ", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d4 = d4[,11]
colnames(d4)[1] = "JNJ"
d5 = Quandl("WIKI/KO", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d5 = d5[,11]
colnames(d5)[1] = "KO"
d6 = Quandl("WIKI/NKE", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d6 = d6[,11]
colnames(d6)[1] = "NKE"
d7 = Quandl("WIKI/TXN", type="xts",start_date=as.Date("2012-01-01"),end_date=as.Date("2014-12-31"))
d7 = d7[,11]
colnames(d7)[1] = "TXN"
# We merge the 7 datasets 
d8 = merge(d1,d2,d3,d4,d5,d6,d7)
# We calculate daily log returns, and store it in a time series called returns.
returns = diff(log(d8))
# Now we enter our portfolio values. Assume that our portfolio has a total value of $1m. This 
# is divided between the seven stocks as 5%, 17%, 8%, 17%, 20%, 14%, 19% respectively.
# We store this in a matrix called w. Note that this holds the dollar value of the
# constituents of the portfolio.
w = matrix(data = c(50000, 170000, 80000, 170000, 200000, 140000, 190000), nrow = 7, ncol = 1, 
byrow = FALSE, dimnames =list(c("AAPL","DISCA","IBM","JNJ","KO","NKE","TXN"),c(NULL)))
# We put the percentage weights in a matrix called wts.
wts = w/sum(w)
# We calculate portfolio returns. Note that %*% is matrix multiplication in R.
pf_returns = returns %*% wts
# We calculate the covariance matrix. A one step process. Note that these are daily covariances.
# In order to get annual covariances, we will need to multiply by 250 (note that variances and covariances
# scale linearly with time, while standard deviation scales by the square root of time)
V = cov(na.omit(returns)) * 250
# We calculate the covariances of asset i to portfolio p.
cov_ip = V %*% wts
# Calculate the portfolio volatility, in percent, and in dollars. Note that we
# are multiplying by sqrt(250) to annualize the daily volatilities.
vol_p_pct = sqrt(t(wts) %*% V %*% wts) # in percent, annual Var
vol_p = sqrt(t(w) %*% V %*% w) #in dollars
# Calculate the VaR, in dollars and percent. Note that 'qnorm' is equivalent to Excel's NORMSINV.
# Note that we are calculating things here at the 95% confidence level.
var_p = qnorm(0.95) * vol_p #Portfolio VaR in dollars
var_p_pct = qnorm(0.95) * vol_p_pct #Portfolio VaR in percent
# Calculate the volatility of the i-th asset. We can then calculate the VaR of the i-th asset.
vol_i = sqrt(diag(V))
VaRi = qnorm(0.95) * vol_i * d
# We calculate the undiversified VaR as the sum of the VaRs of the individual assets.
uVar = sum(VaRi)
# We calculate the beta. Note that this is the same answer
# you would get if you did beta = sum(w) * (V %*% w)/as.numeric(vol_p^2)
beta = cov_ip/as.numeric(vol_p_pct)^2
# Calculate Marginal VaR
mvar = qnorm(0.95) * (V %*% w)/as.numeric(vol_p)
# Calculate Component VaR
cvar = mvar * w
# At this point you can print each of the variables by typing them on the R prompt.
print ("Portfolio Constituents in Dollars")
w
print ("Covariance matrix (annualized)")
V
print ("Annual portfolio volatility/standard deviation as a percent")
vol_p_pct
print ("Portfolio volatility/standard deviation in dollars")
vol_p
print ("Portfolio VaR, as a percent")
var_p_pct
print ("Portfolio VaR, in dollars")
var_p
print ("VaR of individual stocks in the portfolio (in dollars)")
VaRi
print ("Total undiversified VaR (sum of VaR of individual stocks")
uVar
print ("Beta of each stock")
beta
print ("Marginal VaR of each stock")
mvar
print ("Component VaR")
cvar
print ("Sum of component VaR - should be equal to portfolio VaR above")
sum(cvar)


So how does this code run in practice? Here is what the output looks like – pretty ugly but is much easier to read on the R console:

> print ("Portfolio Constituents in Dollars")
[1] "Portfolio Constituents in Dollars"
> w
[,1]
AAPL 50000
DISCA 170000
IBM 80000
JNJ 170000
KO 200000
NKE 140000
TXN 190000
> print ("Covariance matrix")
[1] "Covariance matrix"
> V
AAPL DISCA IBM JNJ KO NKE TXN
AAPL 0.071793333 0.01328617 0.009510680 0.004658095 0.006324530 0.009867259 0.017544753
DISCA 0.013286171 0.22312544 0.014487886 0.010578264 0.012427071 0.019696823 0.024372985
IBM 0.009510680 0.01448789 0.030129963 0.007129105 0.007669291 0.007695426 0.012682422
JNJ 0.004658095 0.01057826 0.007129105 0.015362860 0.007921800 0.007664518 0.010243517
KO 0.006324530 0.01242707 0.007669291 0.007921800 0.021141923 0.007522650 0.009041654
NKE 0.009867259 0.01969682 0.007695426 0.007664518 0.007522650 0.046169126 0.013834770
TXN 0.017544753 0.02437299 0.012682422 0.010243517 0.009041654 0.013834770 0.046970137
> print ("Portfolio volatility/standard deviation as a percent")
[1] "Portfolio volatility/standard deviation as a percent"
> vol_p_pct
[,1]
[1,] 0.1430367
> print ("Portfolio volatility/standard deviation in dollars")
[1] "Portfolio volatility/standard deviation in dollars"
> vol_p
[,1]
[1,] 143036.7
> print ("Portfolio VaR, as a percent")
[1] "Portfolio VaR, as a percent"
> var_p_pct
[,1]
[1,] 0.2352745
> print ("Portfolio VaR, in dollars")
[1] "Portfolio VaR, in dollars"
> var_p
[,1]
[1,] 235274.5
> print ("VaR of individual stocks in the portfolio (in dollars)")
[1] "VaR of individual stocks in the portfolio (in dollars)"
> VaRi
[,1]
[1,] 24513.657
[2,] 78486.737
[3,] 6683.584
[4,] 269280.534
[5,] 31365.429
[6,] 113494.770
[7,] 373189.729
> print ("Total undiversified VaR (sum of VaR of individual stocks")
[1] "Total undiversified VaR (sum of VaR of individual stocks"
> uVar
[1] 897014.4
> print ("Beta of each stock")
[1] "Beta of each stock"
> beta
[,1]
AAPL 0.6540175
DISCA 2.5135905
IBM 0.5660792
JNJ 0.4798204
KO 0.5566386
NKE 0.7994936
TXN 0.9993480
> print ("Marginal VaR of each stock")
[1] "Marginal VaR of each stock"
> mvar
[,1]
AAPL 0.1538736
DISCA 0.5913836
IBM 0.1331840
JNJ 0.1128895
KO 0.1309628
NKE 0.1881004
TXN 0.2351211
> print ("Component VaR")
[1] "Component VaR"
> cvar
[,1]
AAPL 7693.68
DISCA 100535.22
IBM 10654.72
JNJ 19191.21
KO 26192.57
NKE 26334.06
TXN 44673.00
> print ("Sum of component VaR - should be equal to portfolio VaR above")
[1] "Sum of component VaR - should be equal to portfolio VaR above"
> sum(cvar)
[1] 235274.5