首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >投资组合分析chart.EfficientFrontier函数

投资组合分析chart.EfficientFrontier函数
EN

Stack Overflow用户
提问于 2015-06-03 08:15:31
回答 4查看 3.4K关注 0票数 0

我试图在R中的投资组合分析包中使用chart.EfficientFrontier函数来绘制一个有效的前沿对象,我已经创建了这个对象,但是它一直在失败。基本上,我试图找到一个将年化的标准差最小化的前沿。最终,一旦我完成了这项工作,我也希望最大限度地提高年化的回报。

首先,我使用以下代码创建了一个年化标准差函数。

代码语言:javascript
复制
pasd <- function(R, weights){
  as.numeric(StdDev(R=R, weights=weights)*sqrt(12)) # hardcoded for monthly data
  # as.numeric(StdDev(R=R, weights=weights)*sqrt(4)) # hardcoded for quarterly data
}

我导入了一个包含月回报的csv文件,我的portfolio对象如下所示:

代码语言:javascript
复制
> prt
**************************************************
PortfolioAnalytics Portfolio Specification 
**************************************************

Call:
portfolio.spec(assets = colnames(returns))

Number of assets: 3 
Asset Names
[1] "Global REITs"      "Au REITs"          "Au Util and Infra"

Constraints
Enabled constraint types
        - leverage 
        - long_only 

Objectives:
Enabled objective names
        - mean 
        - pasd 

现在,我成功地使用以下行创建了一个有效的前沿对象:

代码语言:javascript
复制
prt.ef <- create.EfficientFrontier(R = returns, portfolio = prt, type = "DEoptim", match.col = "pasd")

但是,当我试图绘制它时,我会得到以下错误消息。

代码语言:javascript
复制
> chart.EfficientFrontier(prt.ef, match.col="pasd")
Error in StdDev(R = R, weights = weights) : 
  argument "weights" is missing, with no default
In addition: There were 26 warnings (use warnings() to see them)
Error in StdDev(R = R, weights = weights) : 
  argument "weights" is missing, with no default
Error in StdDev(R = R, weights = weights) : 
  argument "weights" is missing, with no default
Error in xlim[2] * 1.15 : non-numeric argument to binary operator

有人知道为什么会这样吗?当我使用汇总(prt.ef)时,我可以看到权重,但是为什么chart.EfficientFrontier函数会失败呢?

EN

回答 4

Stack Overflow用户

发布于 2015-06-04 18:01:34

正如@WaltS所建议的那样,您需要在实现函数时保持一致,以实现平均回报和风险回报的年度化。

但实际上,要获得年度统计数据,您有两个选项,您没有使用任何:

( 1)利用规范中原有的风险回报函数,利用月度数据进行优化。为了谋划,你可以把制造

代码语言:javascript
复制
Port.Anua.Returns=prt.ef$frontier[,1]*12 
Port.Anua.StDev=prt.ef$frontier[,2]*12^.5

月投资组合或年化投资组合的权重将相同。

代码语言:javascript
复制
prt.ef$frontier[,-(1:3)]

2)将你的月收益按年率乘以12,然后按照通常的程序进行优化,所有的风险和回报都将在prt.ef$frontier中实现。

与EF中的锯齿线有关。使用您的投资组合规范,我还能够重新创建相同的行为。对于下面的图,我使用了edhec数据,您的规范在目标中使用了原始的meanStdDev

代码语言:javascript
复制
data(edhec)
returns <- edhec[,1:3]

这种行为必须受您正在使用的规范或优化算法的影响。我对来自包solve.QPquadprog做了同样的优化。这就是结果。

更新

守则如下:

代码语言:javascript
复制
require(quadprog) 
#min_x(-d^T x + 1/2 b^T D x) r.t A.x>=b
MV_QP<-function(nx, tarRet, Sig=NULL,long_only=FALSE){
  if (is.null(Sig)) Sig=cov(nx)
  dvec=rep(0,ncol(Sig))
  meq=2
  Amat=rbind(rep(1,ncol(Sig)),
             apply(nx,2,mean) )
  bvec=c(1,tarRet )
  if (long_only) {
    meq=1
    Amat=Amat[-1,]
    Amat=rbind(Amat,
               diag(1,ncol(Sig)),
               rep(1,ncol(Sig)),
               rep(-1,ncol(Sig)))
    bvec=bvec[-1]
    bvec=c(bvec,
               rep(0,ncol(Sig)),.98,-1.02)
  }
  sol  <- solve.QP(Dmat=Sig, dvec, t(Amat), bvec, meq=meq)$solution 
}

steps=50
x=returns
 µ.b <- apply(X = x, 2, FUN = mean) 
long_only=TRUE
range.bl <- seq(from = min(µ.b), to = max(µ.b)*ifelse(long_only,1,1.6), length.out = steps) 
risk.bl <- t(sapply(range.bl, function(targetReturn) { 
  w <- MV_QP(x, targetReturn,long_only=long_only) 
  c(sd(x %*% w),w)  }))

weigthsl=round(risk.bl[,-1],4)
colnames(weigthsl)=colnames(x)
weigthsl
risk.bl=risk.bl[,1]
rets.bl= weigthsl%*%µ.b
fan=12
plot(x = risk.bl*fan^.5, y = rets.bl*fan,col=2,pch=21,
     xlab = "Annualized Risk ", 
     ylab = "Annualized Return", main = "long only EF with solve.QP")
票数 2
EN

Stack Overflow用户

发布于 2015-06-05 22:10:12

除了Robert的评论外,带月收益的优化计算是一个具有线性约束的二次规划问题。当meanreturn目标,StdDevvarrisk目标时,optimize.portfoliocreate.EfficientFrontier选择ROI方法作为解决这类问题的有效方法solve.QP。当risk目标被转换为pasd时,这些函数并不认为这是一个QP问题,所以使用DEoptim --一种一般的非线性问题求解器--也许更适合于解决非凸问题,而不是凸QP问题。见基于DEoptim的差分进化。这似乎是造成锯齿状的有效边界的原因。

为了让create.EfficientFrontier使用solve.QP,这对于这类问题来说更加有效和准确,您可以使用自定义矩函数来计算平均值和方差,然后用参数momentFUN指定它。然而,create.EfficientFrontier至少部分地使用直接从返回计算的方法,而不是使用来自momentFUNmu。为了处理这一点,将返回乘以12,如下面的示例所示。

代码语言:javascript
复制
library(PortfolioAnalytics)
  data(edhec)
  returns <- edhec[,1:3]
#  define moment function
  annualized.moments <- function(R, scale=12, portfolio=NULL){
    out <- list()
    out$mu <-    matrix(colMeans(R), ncol=1)
    out$sigma <- cov(R)/scale
    return(out)
  }
# define portfolio
  prt <- portfolio.spec(assets=colnames(returns))
  prt <- add.constraint(portfolio=prt, type="long_only")
  #  leverage defaults to weight_sum = 1 so is equivalent to full_investment constraint
  prt <- add.constraint(portfolio=prt, type="leverage")
  prt <- add.objective(portfolio=prt, type="risk", name="StdDev")
# calculate and plot efficient frontier
  prt_ef <- create.EfficientFrontier(R=12*returns, portfolio=prt, type="mean-StdDev", 
                                      match.col = "StdDev", momentFUN="annualized.moments", scale=12)
  xlim <- range(prt_ef$frontier[,2])*c(1, 1.5)
  ylim <- range(prt_ef$frontier[,1])*c(.80, 1.05)
  chart.EfficientFrontier(prt_ef, match.col="StdDev", chart.assets = FALSE, 
                          labels.assets = FALSE, xlim=xlim, ylim=ylim )
  points(with(annualized.moments(12*returns, scale=12), cbind(sqrt(diag(sigma)), mu)), pch=19 ) 
  text(with(annualized.moments(12*returns, scale=12), cbind(sqrt(diag(sigma)), mu)), 
       labels=colnames(returns), cex=.8, pos=4) 
  chart.EF.Weights(prt_ef, match.col="StdDev")

资产的均值和标准差也需要调整,因此在chart.EfficientFrontier之外绘制并显示在下面的图表上。

最后,正如Robert建议的那样,用月收益计算有效前沿的权重会更简单,然后使用年度化资产均值和标准差计算投资组合收益和标准差,以及在这两种情况下每月的权重是相同的。然而,也许这个示例对于显示自定义矩和目标函数的使用是有用的。

票数 1
EN

Stack Overflow用户

发布于 2015-06-03 10:19:11

没有找到错误的原因,但设置限制它的部分工作!

代码语言:javascript
复制
prt.ef$frontier  #see the EF
xylims=apply(prt.ef$frontier[,c(2,1)],2,range)*c(.98,1.01)
chart.EfficientFrontier(prt.ef, match.col="pasd", 
      main="Portfolio Optimization", 
      xlim=xylims[,1], ylim=xylims[,2])
#or
plot(prt.ef$frontier[,c(2,1)],col=2)
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30614457

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档