PortfolioAnalytics不同资产收益矩下返回相同投资组合及boudt矩功能失效问题咨询
PortfolioAnalytics回测问题:三种优化结果一致+Boudt矩估计报错
问题描述
我正在使用R语言的PortfolioAnalytics包回测不同投资组合优化方法,流程如下:
- 运行标准均值-方差优化
- 用
MASS包的MCD、MVE两种稳健估计优化资产收益的方差-协方差矩阵 - 尝试结合Boudt收益矩估计,用
optimize.portfolio.rebalancing进行滚动再平衡优化
但遇到两个问题:
- 前三次优化(标准方法、MCD、MVE)的回测结果完全一致(绩效图对比可看出)
- 使用Boudt矩估计时出现两条警告,且投资组合输出有缺陷:
1: In Return.portfolio(ret, weights = extractWeights(opt_Boudt)) : number of assets in beginning_weights is less than number of columns in returns, so subsetting returns. 2: In Return.portfolio.geometric(R = R, weights = weights, wealth.index = wealth.index,: The weights for one or more periods do not sum up to 1: assuming a return of 0 for the residual weights
可复现代码
library(xts) library(PortfolioAnalytics) library(ROI) library(MASS) data("edhec") ret = edhec[,1:6] port <- portfolio.spec(assets = colnames(ret)) port <- add.constraint(port, "long_only") port <- add.constraint(port, "full_investment") port <- add.objective(port, type = "Risk", name = "StdDev") port <- add.objective(port, type = "return", name = "mean") # Standard Optimization opt_norm <- optimize.portfolio.rebalancing(R = ret, portfolio = port, optimize_method = "ROI", rebalance_on = "months", training_period = 60, rolling_window = NULL) summary(opt_norm) rr_norm <- Return.portfolio(ret, weights = extractWeights(opt_norm)) charts.PerformanceSummary(rr_norm) # Robust MCD-VarCov Optimization custom_fun <- function(R, portfolio, rob_method = "mcd"){ out <- list() out$sigma <- cov.rob(R, method = rob_method) return(out) } opt_MCD <- optimize.portfolio.rebalancing(R = ret, portfolio = port, optimize_method = "ROI", momentFUN = custom_fun, rob_method = "mcd", rebalance_on = "months", training_period = 60, rolling_window = NULL) summary(opt_MCD) rr_MCD <- Return.portfolio(ret, weights = extractWeights(opt_MCD)) charts.PerformanceSummary(rr_MCD) # Robust MVE-VarCov Optimization opt_MVE <- optimize.portfolio.rebalancing(R = ret, portfolio = port, optimize_method = "ROI", momentFUN = custom_fun, rob_method = "mve", rebalance_on = "months", training_period = 60, rolling_window = NULL) summary(opt_MVE) rr_MVE <- Return.portfolio(ret, weights = extractWeights(opt_MVE)) charts.PerformanceSummary(rr_MVE) # Boudt Optimization boudt_moments <- set.portfolio.moments(R = ret, portfolio = port, method = "boudt", k = 1) opt_Boudt <- optimize.portfolio.rebalancing(R = ret, portfolio = port, optimize_method = "ROI", momentFUN = boudt_moments, rebalance_on = "months", training_period = 60, rolling_window = NULL) rr_Boudt <- Return.portfolio(ret, weights = extractWeights(opt_Boudt)) charts.PerformanceSummary(rr_Boudt)
具体问题
- 为何前三次优化回测(标准方法、MCD方差-协方差法、MVE方差-协方差法)返回完全相同的结果?
- 在尝试使用“boudt”资产收益矩估计时,我操作上存在哪些错误?
另外这是我第一次在Stack Overflow提问,希望能得到关于如何提升提问质量的建议。感谢各位的帮助!
解答
问题1:三种优化结果一致的原因
你的自定义矩函数custom_fun存在两个关键问题,导致它没有真正替换默认的矩估计逻辑:
- 协方差矩阵提取错误:
cov.rob()返回的是一个包含协方差矩阵、均值等元素的列表,你直接把整个列表赋值给out$sigma,但PortfolioAnalytics期望sigma是纯协方差矩阵,所以实际优化时还是用了默认的协方差估计。 - 缺少均值估计返回:你只返回了协方差相关内容,没有返回均值
mu,优化过程会自动使用默认的均值估计,进一步导致和标准优化的矩输入完全一致。
修改后的custom_fun应该是:
custom_fun <- function(R, portfolio, rob_method = "mcd"){ out <- list() # 提取协方差矩阵本身,而非完整的cov.rob结果 out$sigma <- cov.rob(R, method = rob_method)$cov # 返回自定义均值(这里用稳健估计的均值,也可以用colMeans) out$mu <- cov.rob(R, method = rob_method)$center return(out) }
问题2:Boudt矩估计的操作错误
你错误地将set.portfolio.moments()的运行结果传给了momentFUN参数,但momentFUN需要的是一个可在每个滚动窗口中重新计算矩的函数,而不是一次性生成的矩对象。
正确的做法是直接传递set.portfolio.moments函数本身,并附带所需参数,这样每个滚动期都会重新计算Boudt矩:
opt_Boudt <- optimize.portfolio.rebalancing( R = ret, portfolio = port, optimize_method = "ROI", # 传递函数本身,而非函数运行结果 momentFUN = set.portfolio.moments, # 传递set.portfolio.moments需要的参数 method = "boudt", k = 1, rebalance_on = "months", training_period = 60, rolling_window = NULL )
提升提问质量的建议
你已经做得非常好了(提供可复现代码、明确错误信息、清晰问题),可以再优化几点:
- 标题更精准:比如改成“PortfolioAnalytics: 3 optimization methods return identical results + Boudt moment estimation warnings”,让其他开发者一眼抓住核心问题
- 格式化错误信息:把警告信息用代码块包裹,提升可读性
- 补充环境信息:加上
sessionInfo()的输出(R版本、各包版本),不同版本可能存在兼容性差异 - 补充结果细节:比如前三种优化的权重片段、绩效指标(年化收益、波动率),帮助更快定位问题
- 拆分独立问题:如果两个问题关联性不强,可以拆成两个提问,但这次两个问题都围绕矩估计,放在一起没问题
内容的提问来源于stack exchange,提问作者JB97
相关产品推荐
相关产品推荐

