Search code examples
roptimizationvar

Computing Value at Risk and Conditional Value at Risk (Expected Shortfall) with R


I am new to R and have some questions with regard to computing VaR and CVaR with the Portfolio Analytics package.

I have historical return data in a csv file. For example as follows:

    time         return of stock1    return of stock2   return of stock3
    2016-01-01  -0.6184181087       -0.126394629        0.2537283152
    2016-01-02  -0.1738764113       -0.8100882955       -0.3162766513
    2016-01-03  -0.8229430174       -0.5007778048       -0.880233143
    ...         ...                 ...                 ...

(I) I want to compute the value at risk and conditional value at risk of this portfolio with equal weights (and later with different weights). I want to use the historical data. (I do not want to make an assumption about the probability distribution-especially not asssume a Gaussian distribution.) So e.g. for the VaR I basically want to find the percentile.

(II) I want to optimize the weights by optimizing with the CVaR. ( again by the historical method).

I have following questions:

  1. If I use the VaR function and choose method = c("historical"), does it compute the respective percentile of my historical data?

  2. With the help of some online tutorials, I have tried (but not completely understood) the following so far:

     *Loading data into file*
     testData_return <- Return.read(filename = "myTest.csv", frequency = "d",format = "%Y-%m-%d", header = TRUE)
    
     *Create the portfolio specification object*
      Wcons <- portfolio.spec(assets = colnames(testData_return))
    
     * Add box constraints *
      Wcons <- add.constraint(portfolio = Wcons, type='box', min=0, max=1)  
      Wcons <- add.constraint( portfolio=Wcons, type = "weight_sum", min_sum=0.99, max_sum=1.01)         * why can't I put min_sum=1, max_sum=1 ? *
    
      * Add an objective * 
      ObjSpec = add.objective(portfolio = Wcons, type = "risk", name = "VaR", arguments=list(p=0.95), enabled=TRUE)
    
    
    * value of the objective function * 
    constrained_objective(w=rep(1/3,3), R=testData_return,portfolio = ObjSpec)
    

    gives me "VaR 0.5707718".

To test this result I chose the VaR function

    VaR(testData_return, p = 0.95, method = c("historical"), clean = c("none"), portfolio_method = c("single")) 

this returns me as a results:

      "stock1     stock2     stock3
      VaR -0.8836453 -0.9002575 -0.9151286"

Hence, I do not understand why I get different results and I cannot understand why I get three results for the last line.

In order to test further, I used python as follows:

I merged the returns by adding up the returns for each day and dividing by 3, yielding a csvfile with one column.

    -0.1636948075
    -0.433413786
    -0.7346513217
    ...

Then I have computed the 95th percentile (same as above) of these returns.

    percentile = 0.95

    * fname is the name of my file with the one column of data *
    returns_values = np.loadtxt(fname, skiprows=0, usecols=[0], unpack=True)

     print(np.percentile(returns_values, percentile))

This gives me -0.74321324 as a result.

So, I do not understand why this result is substantially different to my first results (-0.74 != 0.57 ).

Also, I do not understand why my second approach gives me a VaR for each individual stock.


Solution

  • The example code below tries to answer your questions by working through a simple example of VaR calculations using three assets. Since your post didn't supply a complete time history of returns, the example first gets price data for three stock tickers from Yahoo finance using the quantmod package then computes returns.

    The code compares VaR for each stock calculated by the VaR function using portfolio_method="single" and by the quantile function. Since there are three stocks, each method gives three values for VaR and the results should agree for each stock.

    The constraints and objective for the portfolio calculation are specified very much as you had them. The arguments list has been expanded to include method ="historical" to indicate that VaR should be calculated from a cumulative distribution function directly rather than from a model and portfolio_method="component" to indicate that the VaR function should use input weights to calculate a portfolio VaR. optimize.portfolio with the given constraints and objective is used to find the optimum portfolio. The results are contained in opt.

    Finally, VaR for the portfolio is calculated using constrained_objective for the portfolio ObjSpec_hist which specifies VaR and compared with the portfolio VaR calculated using quantile for the portfolio formed with the optimized weights. These results should agree.

    Code follows:

      library(xts)
      library(quantmod)
      library(PerformanceAnalytics)
      library(PortfolioAnalytics)
    
      tickers <- c("AAPL", "MSFT", "AMZN")
      start_date <- "2016-01-01"
      percentile <- .95            # confidence level used in VaR calculations
     #
     # get Adjusted Close prices from Yahoo Finance
     # 
      prices <- xts()
      for( tick in tickers) {
        prices <- merge(prices, getSymbols(Symbols=tick, from=start_date, 
                                           auto.assign=FALSE)[,paste(tick,"Adjusted",sep=".")])
      }
      colnames(prices) <- tickers
    #
    # transform index from POSIXct to Date class
    #
      index(prices) <- as.Date(index(prices))
    #
    # compute returns
    #  
      testData_return <- diff(prices, arithmetic=FALSE, na.pad=FALSE) - 1
    #
    #  Compare VaR with quantile calculations for assets
    #  when portfolio_method = "single" in VaR, the VaR for each column in R is calculated 
    #
      VaR_asset_hist <- VaR(R = testData_return, p=percentile, method="historical",
                            portfolio_method = "single")
      print(VaR_asset_hist)
      quant_asset_hist <- sapply(testData_return, quantile, probs=1-percentile, type=7)
      print(quant_asset_hist)  
    #
    # Create the portfolio specification object 
    #
      Wcons <- portfolio.spec(assets = colnames(testData_return))
    # 
    # Add long_only and weight_sum = 1 constraints
    #
      Wcons <- add.constraint(portfolio = Wcons, type='box', min=0, max=1)  
      Wcons <- add.constraint( portfolio=Wcons, type = "weight_sum",
                               min_sum=0.99, max_sum=1.01)          
    #
    # Set the objective to minimize VaR using historical returns
    # portfolio_method ="component" tells VaR to use values of weights argument and calculate VaR for the portfolio
    #
      ObjSpec_hist = add.objective(portfolio = Wcons, type = "risk", 
                                   name = "VaR", 
                                   arguments=list(p=percentile, method="historical",
                                                                portfolio_method="component"),
                                   enabled=TRUE)
      opt <-  optimize.portfolio(R =testData_return, portfolio=ObjSpec_hist, 
                         search_size = 2000, trace = TRUE)
      print(opt)
    #
    # compare VaR calculated using the optimization results with the quantile case.
    # the VaR function calculates VaR slightly differently for historical data depending upon whether the 
    # portfolio_method = "single" or "component".  The values for the quantile arguments probs and type used below should 
    # give the same results for both the constrained_objective and quantile functions
    #
      VaR_port_opt <-constrained_objective(w=weights(opt),
                                           R=testData_return,portfolio = ObjSpec_hist)
      quant_probs <- floor((1-percentile)*nrow(testData_return))/nrow(testData_return)
      quant_port_opt <- quantile( testData_return%*%weights(opt), 
                                  probs = quant_probs, type=1)
      cat(paste("VaR using opt weights =", VaR_port_opt,
                "\nquantile calculation using opt weights =", quant_port_opt))
    

    CVaR calculation

    To use to CVaR rather than VaR as the objective, the optimization_method should be changed to "ROI" since CVaR optimization can be formulated as a quadratic programming problem. Along with this, the weight_sum constraint can be replaced with a full_investment constraint which set weight_sum = 1. The code now looks like:

    #
    # Create the portfolio specification object 
    #
      Wcons <- portfolio.spec(assets = colnames(testData_return))
    # 
    # Add long_only and full investment (weight_sum = 1) constraints
    #
      Wcons <- add.constraint(portfolio = Wcons, type='box', min=0, max=1)  
      Wcons <- add.constraint(portfolio=Wcons, type = "full_investment")
    #
    # Set the objective to minimize CVaR using historical returns
    # portfolio_method ="component" tells VaR to use values of weights argument and calculate CVaR for the portfolio
    #
      ObjSpec_hist = add.objective(portfolio = Wcons, type = "risk", 
                                   name = "CVaR", 
                                   arguments=list(p=percentile, method="historical", 
                                    portfolio_method="component"),
                                   enabled=TRUE)
      opt <- optimize.portfolio(R = testData_return, portfolio = ObjSpec_hist,
                                 optimize_method="ROI")
      print(opt)