使用 R 计算风险价值和条件风险价值(预期短缺)

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

我是 R 的新手,对使用投资组合分析包计算 VaR 和 CVaR 有一些疑问。

我在 csv 文件中有历史 return 数据。例如如下:

    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) 我想计算这个投资组合的风险价值和条件风险价值,权重相等(后来权重不同)。我想使用历史数据。 (我 不想 想对概率分布做出假设——尤其是不假设高斯分布。)所以,例如对于 VaR,我基本上想找到百分位数。

(II) 我想通过 CVaR 优化权重。 (再次通过历史方法)。

我有以下问题:

  1. 如果我使用 VaR 函数并选择 method = c("historical"),它会计算我的历史数据的相应百分位数吗?

  2. 在一些在线教程的帮助下,到目前为止,我尝试了(但还没有完全理解)以下内容:

     *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)
    

    给我 "VaR 0.5707718".

为了测试这个结果,我选择了 VaR 函数

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

这个 return 结果是我:

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

因此,我不明白为什么我得到不同的结果,我不明白为什么我在最后一行得到三个结果。

为了进一步测试,我使用了python如下:

我通过将每天的 return 相加并除以 3 来合并 return,得到一个包含一列的 csv 文件。

    -0.1636948075
    -0.433413786
    -0.7346513217
    ...

然后我计算了这些 return 的第 95 个百分位数(同上)。

    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))

结果是 -0.74321324。

所以,我不明白为什么这个结果与我的第一个结果有很大不同 (-0.74 != 0.57)。

此外,我不明白为什么我的第二种方法会为我提供每只股票的 VaR。

下面的示例代码尝试通过使用三个资产的 VaR 计算的简单示例来回答您的问题。由于您的 post 没有提供 returns 的完整时间历史记录,该示例首先使用 quantmod 包从 Yahoo finance 获取三个股票代码的价格数据,然后计算 returns .

代码比较 VaRVaR 函数使用 portfolio_method="single"quantile 函数计算的每只股票。由于存在三只股票,每种方法都给出了 VaR 的三个值,并且每只股票的结果应该一致。

投资组合计算的约束和 objective 与您指定的非常相似。参数列表已扩展为包括 method ="historical" 以指示 VaR 应直接从累积分布函数而不是从模型计算,以及 portfolio_method="component" 以指示 VaR 函数应使用输入权重来计算投资组合 VaRoptimize.portfolio 具有给定的约束,objective 用于查找最佳投资组合。结果包含在 opt.

最后,VaR 的投资组合是使用 constrained_objective 计算的,对于指定 VaR 的投资组合 ObjSpec_hist,并与使用 VaR 计算的投资组合进行比较quantile 对于使用优化权重形成的投资组合。这些结果应该一致。

代码如下:

  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 计算

要使用 CVaR 而不是 VaR 作为 objective,optimization_method 应更改为 "ROI",因为 CVaR 优化可以表述为二次规划问题。与此同时,weight_sum 约束可以替换为设置 weight_sum = 1full_investment 约束。代码现在看起来像:

#
# 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)