5

I have code that successfully calculates VaR based on Extreme Value Theory using historical data. I'm trying to run this same code on multiple simulated price paths (i.e. calculating a VaR for each path) and then taking the median or average of those VaRs.

Every example I could find online had the simulation function return the price at the end of the period and then they replicated the function X many time. That makes sense to me, except that I essentially need to calculate value-at-risk for each simulated path. Below is the code I have so far. I can say that the code works when using historical data (i.e. the "evt" function works fine and the datatable is populated correctly when the lossOnly, u, and evtVar lines aren't in a function). However, I've been trying to implement simulation in the second function and trying various combinations, which have all failed.

library('RODBC')
library('nor1mix')
library('fExtremes')
library('QRM')
library('fGarch')

#function for computing the EVT VaR
evt <- function(data,u){
  #fit excess returns to gpd to get estimates

  gpdfit = tryCatch({
    gpdfit <- gpdFit(data,u,type="mle")
  }, warning = function(w) {
    gpdfit <- gpdFit(data,u,type="mle",optfunc="nlminb")
    return(gpdfit)
  }, error = function(e) {
    gpdfit <- gpdFit(data,u,type="pwm",optfunc="nlminb")
    return(gpdfit)
  }, finally = {})

  #now calculate VaRs
  xi <- gpdfit@fit$par.ests["xi"]
  beta <- gpdfit@fit$par.ests["beta"]
  Nu <- length(gpdfit@data$exceedances)
  n <- length(data)

  evtVar95 <- (u+((beta/xi)*(((n/Nu)*.05)^(-xi) - 1.)))*100
  evtVar99 <- (u+((beta/xi)*(((n/Nu)*.01)^(-xi) - 1.)))*100
  evtVar997 <- (u+((beta/xi)*(((n/Nu)*.003)^(-xi) - 1.)))*100
  evtVar999 <- (u+((beta/xi)*(((n/Nu)*.001)^(-xi) - 1.)))*100

  #return calculations
  return(cbind(evtVar95,evtVar99,evtVar997,evtVar999,u,xi,beta,Nu,n))
}

#data <- read.table("pricedata.txt")
prices <- data$V1
returns <- diff(log(prices)) #or returns <- log(prices[-1]/prices[-n])
xi <- mean(returns)
std <- sd(returns)
N <- length(prices)
lstval <- prices[N]
options(scipen = 999)
p <- c(lstval, rep(NA, N-1))

gen.path <- function(){
  N <- length(prices)
  for(i in 2:N)
    p[i] <- p[i-1] * exp(rnorm(1, xi, std))
  # plot(p, type = "l", col = "brown", main = "Simulated Price")

  #evt calculation
  #first get only the losses and then make them absolute
  lossOnly <- abs(p[p<0])
  #get threshold
  u <- quantile(lossOnly, probs = 0.9, names=FALSE)
  evtVar <- evt(lossOnly,u)

  return(evtVar)
}

runs <- 10
sim.evtVar <- replicate(runs, gen.path())
evtVar <- mean(sim.evtVar)

#add data to total table
VaR <- c(evtVar[1],evtVar[2],evtVar[3],evtVar[4],evtVar[5],evtVar[6],evtVar[7],evtVar[8],evtVar[9])  
DF <- data.frame(VaR, row.names=c("evtVar95","evtVaR_99","evtVaR_997","evtVaR_999","u","xi","beta","Nu","n"))

In short, I'm trying to run the value-at-risk function (first function) within the monte carlo function (second function) and trying to put the average simulated values into a data tables. I know the first function works, but it's the second function that's driving me crazy. There are the errors I'm getting:

> sim.evtVar <- replicate(runs, gen.path())
Error in if (xi > 0.5) { : missing value where TRUE/FALSE needed
Called from: .gpdpwmFit(x, u)
Browse[1]> evtVar <- mean(sim.evtVar)
Error during wrapup: object 'sim.evtVar' not found
Browse[1]> 
> #add data to total table
> VaR <- c(evtVar[1],evtVar[2],evtVar[3],evtVar[4],evtVar[5],evtVar[6],evtVar[7],evtVar[8],evtVar[9])  
Error: object 'evtVar' not found
> DF <- data.frame(VaR, row.names=c("evtVar95","evtVaR_99","evtVaR_997","evtVaR_999","u","xi","beta","Nu","n"))
Error in as.data.frame.default(x[[i]], optional = TRUE) : 
  cannot coerce class ""function"" to a data.frame

Any help you can provide is greatly appreciated! Thank you in advance!

1 Answers1

0

I think the Problem is this row:

lstval <- prices[N]  

because if you take a stock price, that can't ever be negative, you produce an empty vector at this row in your function:

lossOnly <- abs(p[p<0])

you should try instead:

lstval <- min(returns)

if you want the highest negative return of your dataset

user3666197
  • 1
  • 6
  • 50
  • 92
Macjackson
  • 21
  • 2