我刚开始学习 R 语言的投资组合分析,我偶然发现了一篇通过示例解释基本原理的文章。但是这段代码有问题。该代码包含以下错误: 1) 由于约束 full_investment 无法优化 Portfolio;2)写向量有问题;3) 未计算夏普比率;4) 绘图问题。那么谁对此感兴趣,我们开始解析代码
library(PortfolioAnalytics)
library(quantmod)
library(PerformanceAnalytics)
library(zoo)
library(plotly)
library(foreach)
library(DEoptim)
library(iterators)
library(fGarch)
library(Rglpk)
library(quadprog)
library(ROI)
library(ROI.plugin.glpk)
library(ROI.plugin.quadprog)
library(ROI.plugin.symphony)
library(pso)
library(GenSA)
library(corpcor)
library(testthat)
library(nloptr)
library(MASS)
library(robustbase)
# Get data
getSymbols(c("MSFT", "SBUX", "IBM", "AAPL", "^GSPC", "AMZN"))
# Assign to dataframe
# Get adjusted prices
prices.data <- merge.zoo(MSFT[,6], SBUX[,6], IBM[,6], AAPL[,6], GSPC[,6], AMZN[,6])
# Calculate returns
returns.data <- CalculateReturns(prices.data)
returns.data <- na.omit(returns.data)
# Set names
colnames(returns.data) <- c("MSFT", "SBUX", "IBM", "AAPL", "^GSPC", "AMZN")
# Save mean return vector and sample covariance matrix
meanReturns <- colMeans(returns.data)
covMat <- cov(returns.data)
# Start with the names of the assets
port <- portfolio.spec(assets = c("MSFT", "SBUX", "IBM", "AAPL", "^GSPC", "AMZN"))
# Box
port <- add.constraint(port, type = "box", min = 0.05, max = 0.8)
# Leverage
port <- add.constraint(portfolio = port, type = "full_investment")
# Generate random portfolios
rportfolios <- random_portfolios(port, permutations = 500000, rp_method = "sample")
这部分代码通过没有错误,但随后......
# Get minimum variance portfolio
minvar.port <- add.objective(port, type = "risk", name = "var")
# Optimize
minvar.opt <- optimize.portfolio(returns.data, minvar.port, optimize_method = "random", rp = rportfolios)
# Generate maximum return portfolio
maxret.port <- add.objective(port, type = "return", name = "mean")
# Optimize
maxret.opt <- optimize.portfolio(returns.data, maxret.port, optimize_method = "random", rp = rportfolios)
针对目标进行优化时,每个点都会显示以下错误:
Leverage constraint min_sum and max_sum are restrictive, consider relaxing. e.g. 'full_investment' constraint should be min_sum=0.99 and max_sum=1.01
我不知道为什么会发生这个错误,但由于某种原因,用 Leverage 或其他替换 full_investment 方面,错误消失了。然后是第二个错误:
# Generate vector of returns
minret <- 0.06/100
maxret <- maxret.opt$weights %*% meanReturns
vec <- seq(minret, maxret, length.out = 100)
接收 vec 元素时抛出错误:
Warning message:
In seq_len(length.out - 2L) * by :
Recycling array of length 1 in vector-array arithmetic is deprecated.
Use c() or as.vector() instead.
也许这个错误可以忽略,因为数据仍然被写入
eff.frontier <- data.frame(Risk = rep(NA, length(vec)),
Return = rep(NA, length(vec)),
SharpeRatio = rep(NA, length(vec)))
frontier.weights <- mat.or.vec(nr = length(vec), nc = ncol(returns.data))
colnames(frontier.weights) <- colnames(returns.data)
for(i in 1:length(vec)){
eff.port <- add.constraint(port, type = "return", name = "mean", return_target = vec[i])
eff.port <- add.objective(eff.port, type = "risk", name = "var")
eff.port <- add.objective(eff.port, type = "weight_concentration", name = "HHI",conc_aversion = 0.001)
eff.port <- optimize.portfolio(returns.data, eff.port, optimize_method = "ROI")
eff.frontier$Risk[i] <- sqrt(t(eff.port$weights) %*% covMat %*% eff.port$weights)
eff.frontier$Return[i] <- eff.port$weights %*% meanReturns
eff.frontier$Sharperatio[i] <- eff.port$Return[i] / eff.port$Risk[i]
frontier.weights[i,] = eff.port$weights
print(paste(round(i/length(vec) * 100, 0), "% done..."))
}
经过这些操作,创建了满足条件的有效投资组合,但无法建立有效边界(在名为 eff.frontier 的表中没有填写 Sharp ratio 列)
接下来,我还想根据可用数据构建绘图,但又出现错误:
feasible.sd <- apply(rportfolios, 1, function(x){
return(sqrt(matrix(x, nrow = 1) %*% covMat %*% matrix(x, ncol = 1)))
})
feasible.means <- apply(rportfolios, 1, function(x){
return(x %*% meanReturns)
})
feasible.sr <- feasible.means / feasible.sd
p <- plot_ly(x = feasible.sd, y = feasible.means, color = feasible.sr,
mode = "markers", type = "scattergl", showlegend = F,
marker = list(size = 3, opacity = 0.5,
colorbar = list(title = "Sharpe Ratio"))) %>%
add_trace(data = eff.frontier, x = Risk, y = Return, mode = "markers",
type = "scattergl", showlegend = F,
marker = list(color = "#F7C873", size = 5)) %>%
layout(title = "Random Portfolios with Plotly",
yaxis = list(title = "Mean Returns", tickformat = ".2%"),
xaxis = list(title = "Standard Deviation", tickformat = ".2%"),
plot_bgcolor = "#434343",
paper_bgcolor = "#F8F8F8",
annotations = list(
list(x = 0.4, y = 0.75,
ax = -30, ay = -30,
text = "Efficient frontier",
font = list(color = "#F6E7C1", size = 15),
arrowcolor = "white")
))
虽然 eff.frontier 表中有一个 Risk 列,但函数仍然没有找到它:
Error in add_trace(., data = eff.frontier, x = Risk, y = Return, mode = "markers", :
object 'Risk' not found
我只是想解释一下这些问题,因为我的编程能力还不足以理解这些问题的本质。
原始代码:https ://www.r-bloggers.com/portfolio-optimization-using-r-and-plotly/