投资组合回测的风险价值

Posted

技术标签:

【中文标题】投资组合回测的风险价值【英文标题】:Value at Risk for a Portfolio Backtest 【发布时间】:2019-08-28 16:39:51 【问题描述】:

我正在尝试为我的投资组合回测计算度量值。我正在使用 R 包PerformanceAnalytics,并且我想在我实际重新平衡我的投资组合的每一年应用/使用它的功能VaR。这似乎行不通,尽管我很确定必须有一个简单的解决方案,因为我有一个包含所有所需对数返回的表,以及一个包含所有投资组合权重/年的表。

我需要的是optimize.portfolio.rebalancing 步骤之后的 VaR/year。

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

当前的 VaR 计算给了我一个错误(R 是所用指数的每日回报,而 weights_rent 是重新平衡的权重,见下文)。需要补充的重要一点是 weights_rent 是每年的,而 R 是每日数据:

requires numeric/complex matrix/vector arguments

我认为这是因为 VaR 计算需要一个权重向量,而不是一个有 20 行提供不同权重的表,请参阅下面的权重表:

> 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

非常感谢您的帮助。提前致谢。

编辑测试数据:

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

我收到以下错误代码:

 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 

如果尝试创建函数:

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)

不幸的是没有按预期工作:

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

【问题讨论】:

欢迎来到 SO。尽管您的问题乍一看似乎有效,但它不符合 SO minimal site criteria。它将更适合姐妹站点。您可以从> here < 中选择一个或多个。提出了“交叉验证”的问题转移标志。尽情享受吧 ;-) 我已经编辑了问题,现在应该符合条件了。 如果您可以显示您提供给VaR 函数的对象/数据,它可能会有所帮助。目前还不是很清楚。 更新做得很好。要满足的导入标准是描述您的代码出了什么问题,也就是“错误”、“错误日志”、“回溯”等。因为情况并非如此,并且您的代码没有正确执行某个任务(显示一个论点)它成为不同类型的问题,属于姊妹网站。 @brko 您可以对 weights_rent 和 R 对象使用dputstructure 以可重现的方式显示其内容 【参考方案1】:

基于函数documentation,似乎错误的原因可能是您自己提到的:weights 参数需要vector 的权重 - 而不是zoo 对象或其他东西.您可以尝试为 VaR 函数提供它想要的东西 - 一个数值向量。

而且,如果你想获得 20 个 VaR 函数值(R 中每年一个),一次提供 VaR 一年的数据/R 似乎是合乎逻辑的,这最终会给你想要的20 个函数值。

如果您愿意,您可以自动化该过程,并在循环中按年份、一次 1 年对数据进行子集化,并将其提供给 VaR,然后打印结果或将结果存储在某个数据结构中。

编辑:使用您的假数据,您可以像这样分析它:

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)
      
  

【讨论】:

是的,它确实有效,但问题是它只为整个 R 数据集(20 年的每日指数数据)提供了一个 VaR 值,尽管我的努力是获得 20 个 VaR 值,而不是一个。我的目标是用 weights_rent 定义的权重在 R 中获得一个 VaR 值。 你可以一次喂它一年R,然后给你一个VaR函数值/年? 是的,这是可能的,不过我一直在寻找更自动化的流程 您可以自动化该过程(例如,一次设置 1 年的子集并将其提供给 VaR)。 我该怎么做,这意味着最快的方法是什么?

以上是关于投资组合回测的风险价值的主要内容,如果未能解决你的问题,请参考以下文章

用 pyfolio 进行量化交易回测

投资组合的方差公式推导

matlab使用Copula仿真优化市场风险

如何在投资组合分析中以 5% 和最大回报自定义 VaR

Python pandas,股票投资组合价值时间序列

python实现资产配置(1)----Markowitz 投资组合模型