Skip to content

Instantly share code, notes, and snippets.

@jpicerno1
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpicerno1/c3af6285713c76a5d124 to your computer and use it in GitHub Desktop.
Save jpicerno1/c3af6285713c76a5d124 to your computer and use it in GitHub Desktop.
# tail.risk.1.13jul2015.R
# R code re: CapitalSpecator.com post on tail risk, part I:
# "Tail Risk Analysis In R: Part I"
# 13 July 2015
# By James Picerno
# http://www.capitalspectator.com/tail-risk-analysis-in-r-part-i/#more-5707
# load packages
library(xts)
library(timeSeries)
library(tseries)
library(TTR)
library(quantmod)
library(PerformanceAnalytics)
# Theoretical VaR and ES estimates
p <-c(0.05,0.01)
VaR <-qnorm(p)
ES <-dnorm(qnorm(p))/p
# simulated VaR and ES for portfolio with expected mean of 7% and 15% volatility for $100 portfolio
alpha <- c(0.95, 0.99)
VaR.sim.1 <-qnorm(alpha,mean=-0.07,sd=0.15)*100
ES.sim.1 <-(-0.07 + 0.15 * dnorm(qnorm(alpha))/(1 - alpha))*100
# graph VaR and ES for $100 portfolio with expected 7% mean and 15% volatility
# at range of confidence levels: 90% to 99.9%
x <- seq(0.9,0.999,length=1000)
VaR <- (-0.07 + 0.15 * qnorm(x))*-1
ES <- (-0.07 + 0.15 * dnorm(qnorm(x))/(1 - x))*-1
VaR.a <-VaR*100
ES.a <-ES*100
plot(x, VaR.a, type="l", main="Value at Risk & Expected Shortfall\nrandomly distributed return for $100 portfolio: 7% mean, 15% volatility",
cex.main=0.9,
ylim=range(VaR.a, ES.a),
xlab=expression(alpha), ylab="")
grid()
lines(x, ES.a, lty=2, col=2)
legend("bottomleft", legend=c("VaR","ES"),col=1:2, lty=1:2)
# simulated ES with Student's t distribution
# with expected mean of 7% and 15% volatility for $100 portfolio
alpha <- c(0.95, 0.99)
mu=0.07
nu=5 # degrees of freedom
lambda <- 0.116 # scaling parameter which approximates 0.15 volatility
nu=5 # degrees of freedom
ES.sim.students.1 <-(-mu+lambda*dt(qt(alpha, df=nu),df=nu)/
(1-alpha)*(nu + qt(alpha,df=nu)^2)/(5-1) )*100
###################################################
# Run tail risk analytics on Global ETF portfolio #
###################################################
# download data, generate monthly returns
symbols <-c("SPY","IJS","EFA","EEM","IEF","LQD","VWEHX","RPIBX","PREMX","QRACX","VGSIX")
getSymbols(symbols, src='yahoo', from='2000-12-31')
for(symbol in symbols) {
x <- get(symbol)
indexFormat(x) <- '%Y-%m-%d'
colnames(x) <- gsub("x",symbol,colnames(x))
x <- x[,6]
assign(symbol,x)
}
prices <- do.call(merge, lapply(symbols, get))
colnames(prices) <-c(symbols)
colnames(prices) <-c(symbols)
prices.daily <-na.locf(prices) # copies previous price forward 1 day if no data available
prices.monthly <-to.period(prices.daily,period="months",k=1,indexAt="endof",OHLC=FALSE)
returns.daily <-na.omit(ROC(prices.daily,1,"discrete"))
returns.monthly <-na.omit(ROC(prices.monthly,1,"discrete"))
# initial weights
w.global = c(0.25,0.05,0.20,0.05,0.10,0.10,0.05,0.05,0.05,0.05,0.05) # global aa
# calculate weighted total returns for portfolios
# buy and hold no rebalancing
port.bh <-Return.portfolio(returns.daily,weights=w.global,wealth.index=TRUE,verbose=TRUE)
# year-end rebalanced portfolios
port.rebal <-Return.portfolio(returns.daily,
rebalance_on="years",
weights=w.global,wealth.index=TRUE,verbose=TRUE)
# extract returns for buy & hold and rebal strategies and merge data sets
port.returns <-merge(port.bh$returns,port.rebal$returns)
colnames(port.returns) <-c("","")
chart.VaRSensitivity(port.returns[,1],
methods = c("HistoricalVaR",
"ModifiedVaR",
"HistoricalES"),
xlab="confidence level",
ylab="",
lwd=2,
cex.legend=0.65,
main="Risk Sensitivity")
chart.BarVaR(returns.monthly[,1], legend.loc="topleft",
methods = c("ModifiedES"),
show.greenredbars = TRUE,
colorset = 4,
lty = 2,
legend.cex = 0.8,width=12)
### END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment