rperformanceanalytics

Value at Risk for a Portfolio Backtest


I am trying to calculate measures for my portfolio backtest. I am using R package PerformanceAnalytics, and I want to apply/use its function VaR for every year where I've actually rebalanced my portfolio. This seems not to work, though I am pretty sure there must be a simple solution for it, as I have my table with all the logreturns needed, and a table with all the portfolio weights/year.

What I need is the VaR/year after the optimize.portfolio.rebalancing step.

port_ret <- portfolio.spec(assets=funds)
port_ret <- add.constraint(portfolio=port_ret, type="full_investment")
port_ret <- add.constraint(portfolio=port_ret, type="long_only")
port_ret <- add.constraint(portfolio=port_ret, type="box", min=0.0, max=0.2)
port_ret <- add.objective(portfolio=port_ret, type="quadratic_utility", risk_aversion=(4.044918))
port_ret <- add.objective(portfolio=port_ret, type="risk", name="StdDev")
port_ret <- add.objective(portfolio=port_ret, type="return", name="mean")

opt_rent<- optimize.portfolio(R=R, portfolio=port_ret, optimize_method="ROI", trace=TRUE)

plot(opt_rent, risk.col="StdDev", return.col="mean", main="Quadratic Utility Optimization", chart.assets=TRUE, xlim=c(0, 0.03), ylim=c(0, 0.002085))

extractStats(opt_rent) 
bt_port_rent <- optimize.portfolio.rebalancing(R=R, portfolio= port_ret, optimize_method="ROI", rebalance_on="years", trace=TRUE, training_period= NULL)
chart.Weights(bt_port_rent,  ylim=c(0, 1))
extractStats(bt_port_rent)
weights_rent <- round(extractWeights(bt_port_rent),3)
VaR(R, weights= weights_rent, portfolio_method="component",method="historical")

The current VaR calculaction gives me an error (R are the daily returns of the indices used, and weights_rent are the weights for the rebalancing, see below). Important to add is that the weights_rent are yearly, wheareas R is a daily data:

requires numeric/complex matrix/vector arguments

I assume this is because the VaR calculation requires a vector of weights and not a table with 20 rows providing different weights, see the weights table below:

> weights_rent
             SPX   RUA  FTSE   DAX NKY MSCI EM  GOLD ASIA50   SSE  BBAG   REX  GSCI
1998-12-31 0.200 0.200 0.198 0.002   0   0.000 0.000  0.000 0.000 0.200 0.200 0.000
1999-12-31 0.200 0.159 0.000 0.188   0   0.000 0.000  0.200 0.076 0.177 0.000 0.000
2000-12-29 0.179 0.000 0.000 0.150   0   0.000 0.000  0.071 0.200 0.200 0.000 0.200
2001-12-31 0.147 0.000 0.000 0.045   0   0.000 0.077  0.122 0.200 0.200 0.200 0.010
2002-12-31 0.013 0.000 0.000 0.000   0   0.000 0.200  0.106 0.109 0.200 0.200 0.172
2003-12-31 0.000 0.053 0.000 0.000   0   0.000 0.200  0.137 0.071 0.200 0.200 0.140
2004-12-31 0.000 0.080 0.000 0.000   0   0.000 0.200  0.161 0.000 0.200 0.200 0.160
2005-12-30 0.000 0.070 0.000 0.000   0   0.000 0.200  0.193 0.000 0.200 0.145 0.191
2006-12-29 0.000 0.097 0.000 0.000   0   0.015 0.200  0.196 0.193 0.200 0.000 0.098
2007-12-31 0.000 0.008 0.000 0.017   0   0.130 0.200  0.125 0.200 0.200 0.000 0.120
2008-12-31 0.000 0.055 0.000 0.025   0   0.000 0.200  0.129 0.130 0.200 0.200 0.061
2009-12-31 0.000 0.051 0.000 0.010   0   0.007 0.200  0.145 0.162 0.200 0.200 0.024
2010-12-31 0.000 0.064 0.000 0.015   0   0.012 0.200  0.158 0.129 0.200 0.200 0.023
2011-12-30 0.000 0.098 0.000 0.000   0   0.000 0.200  0.149 0.119 0.200 0.200 0.035
2012-12-31 0.000 0.099 0.000 0.014   0   0.000 0.200  0.161 0.109 0.200 0.200 0.018
2013-12-31 0.000 0.134 0.000 0.025   0   0.000 0.200  0.146 0.095 0.200 0.200 0.000
2014-12-31 0.000 0.138 0.000 0.016   0   0.000 0.200  0.117 0.130 0.200 0.200 0.000
2015-12-31 0.000 0.129 0.000 0.041   0   0.000 0.200  0.102 0.127 0.200 0.200 0.000
2016-12-30 0.000 0.148 0.000 0.036   0   0.000 0.200  0.119 0.098 0.200 0.200 0.000
2017-12-29 0.000 0.151 0.000 0.018   0   0.000 0.200  0.146 0.085 0.200 0.200 0.000
2018-12-31 0.000 0.179 0.000 0.004   0   0.000 0.200  0.150 0.066 0.200 0.200 0.000

I would really appreciate some help. Thanks in advance.

Edit Test Data:

#fake data
data(edhec)
ticker1 <- c("ConA","CTA","DisE","EM","EQN","EvD", "FIA", "GM", "LSE","MA", "RV", "SS","FF")
colnames(edhec) <- ticker1 
fund.names <- colnames(edhec)      
port_test <- portfolio.spec(assets=fund.names)
port_test <- add.constraint(portfolio=port_test, type="full_investment")
port_test <- add.constraint(portfolio=port_test, type="long_only")
port_test <- add.constraint(portfolio=port_test, type="box", min=0.0, max=0.2)      
port_test <- add.objective(portfolio=port_test, type="quadratic_utility", risk_aversion=(4.044918))
port_test <- add.objective(portfolio=port_test, type="risk", name="StdDev")
port_test <- add.objective(portfolio=port_test, type="return", name="mean")

bt_port_test <- optimize.portfolio.rebalancing(R=edhec, portfolio= port_test,                                                        optimize_method="ROI", rebalance_on="years", trace=TRUE, training_period= NULL)

chart.Weights(bt_port_test,  ylim=c(0, 1))
extractStats(bt_port_test)
weights_test <- round(extractWeights(bt_port_test),3)
weights_test
head(edhec)

#split data per year (result in list)
ret.year <- split(edhec, f="years")

#calculating yearly VaR
VaRs = rollapply(data = edhec, width = 20, FUN = function(x) VaR(x, p = 0.95, weights= weights_test, portfolio_method="component",method = "historical", by.column = TRUE))

I am getting the following error code:

 Error in VaR(x, p = 0.95, weights = weights_test, portfolio_method = "component",  : 
  number of items in weights not equal to number of columns in R 

If tried to create a function:

ret.year2 <- ret.year[-c(1,2)]
VAR <- function(p, ret.year2, weights.year){
  a <- for(i in 1:ret.year2)
  b <- for(j in 1:weights.year)
  VaR(a,p=0.95,weights= b, portfolio_method="component",method = "historical")
}
resultat <- VAR(p=0.95,ret.year2=ret.year2, weights.year= weights.year)

which unfortunately didn't work out as expected:

Error in 1:ret.year2 : NA/NaN argument
In addition: Warning message:
In 1:ret.year2 : numerical expression has 11 elements: only the first used

Solution

  • Based on the function documentation, it seems like the reason for the error could be the one you´ve mentioned yourself: weights argument requires a vector of weights - not a zoo object or something else. You could try to give VaR function what it wants - a vector of numeric values.

    And, if you want to get 20 VaR function values (one for each year in R) it would seem logical to feed VaR one year of data/R at a time, which ultimately would give you the wanted 20 function values.

    If you want, you can automate the process and in a loop subset the data by year, 1 year at a time, and feed it to the VaR, then either print the results or store the in some data structure.

    EDIT: With your fake data you can analyse it like this:

    library(ROI) 
    library(ROI.plugin.quadprog) 
    library(ROI.plugin.glpk) 
    library(PerformanceAnalytics)
    library(PortfolioAnalytics)
    
    # your code here
    #split data per year (result in list)
    ret.year <- split(edhec, f="years")
    
    # split weights per year
    weights.year <- split(weights_test, f="years")
    
    # loop over the list of weights, find corresponding data from edhec and run the analysis
    for (i in 1:length(weights.year)){
      weight <- weights.year[[i]]
      year_weight <- as.numeric(format(start(weight), "%Y"))
      weight <- as.vector(weight)
    
      for (j in 1:length(ret.year)){
        YearlyR <- ret.year[[j]]
        year_R <- as.numeric(format(start(YearlyR), "%Y"))
    
        if (year_R==year_weight){
          print(paste("BINGO - years match: ", year_R, year_weight, sep=" "))
          result <- VaR(YearlyR, weights= weight, portfolio_method="component",method="historical")
          print(result)
          }
      }
    }