【问题标题】:Computing Value at Risk and Conditional Value at Risk (Expected Shortfall) with R使用 R 计算风险价值和条件风险价值(预期短缺)
【发布时间】:2016-10-03 14:00:44
【问题描述】:

我是 R 新手,对使用 Portfolio Analytics 软件包计算 VaR 和 CVaR 有一些疑问。

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

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

这会将我作为结果返回:

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

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

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

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

    -0.1636948075
    -0.433413786
    -0.7346513217
    ...

然后我计算了这些回报的第 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。

【问题讨论】:

  • 抱歉,我是一个学究,但要指出的是,您仍在对概率分布做出假设——特别是未来的价格分布将与您选择的历史窗口和权重中的数据一致.这与使用高斯函数一样大。并不是说这是一个糟糕的假设,但重要的是要注意它。
  • 嗨,是的,确实如此!感谢您的评论。下次我会注意用更好的方式表达它。 ;)

标签: r optimization var


【解决方案1】:

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

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

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

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

代码如下:

  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 作为目标,应将 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)

【讨论】:

  • 您好,感谢您的回复。我正在逐步浏览您的代码,并遇到了有关此行VaR_asset_hist &lt;- VaR(R = testData_return, p=percentile, method="historical", portfolio_method = "single") 的问题。我已经通过portfolio_method = component 交换了portfolio_method = single。如果我选择 p = 0.95,我会得到与 p = 0.05 相同的结果,即VaR= 0.03413823。如果我选择p=0.5,我会得到VaR= -0.001176201。对于 p=0.95p=0.05 我怎么会得到相同的结果?另外,为什么 p=0.5 的 VaR 比 p = 0.95 更差?
  • 对于Performance Analytics VaR函数,首先,至于为什么p = .95和p=.05得到相同的结果,如果参数p > .51,VaR设置p = 1 - p;否则 p 不变。 VaR 函数帮助页面中给出的第四个示例建议了此行为。接下来,VaR 报告的值是损失,因此 VaR = 0.03413823 实际上意味着值 -0.03413823。同样,VaR= -0.001176201 的 p=.5 的值意味着 0.001176201 的值。这在 VaR 函数帮助页面上的注释段落中有详细记录
  • 谢谢!如果我现在想针对 CVaR 而不是 VaR 优化我的投资组合,我在目标 ObjSpec_hist = add.objective(portfolio = Wcons, type = "risk", name = "VaR", arguments=list(p=percentile, method="historical", portfolio_method="component"), enabled=TRUE) 中将 name = "VaR" 交换为 name = "CVaR",不是吗?
  • 参见上面的 CVaR 部分。
  • 谢谢!很有帮助!
猜你喜欢
  • 1970-01-01
  • 2014-10-22
  • 2020-11-28
  • 2013-11-09
  • 2017-11-13
  • 2019-08-28
  • 2016-09-04
  • 2015-09-01
  • 2020-02-24
相关资源
最近更新 更多