Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

I am trying to use the chart.EfficientFrontier function in the portfolioanalytics package in R to chart an efficient frontier object that I have created but it keeps failing. Basically I am trying to find a frontier that will minimize annaulized standard deviation. Eventually once I get this working I would also like to maximize annualized return.

Firstly I created an annualized standard deviation function using this code

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
}

I imported a csv file with monthly returns and my portfolio object looks like this:

> 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 

Now I successfully create an efficient frontier object using this line:

prt.ef <- create.EfficientFrontier(R = returns, portfolio = prt, type = "DEoptim", match.col = "pasd")

But when I try to plot it I am getting the following error messages.

> 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

Anyone know why this is the case? When I use summary(prt.ef) I can see the weights, but why is the chart.EfficientFrontier function failing?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
202 views
Welcome To Ask or Share your Answers For Others

1 Answer

As @WaltS suggested, you need to be consistent in implementing functions to annualize mean and risk returns.

But actually to get annualized statistics you have two options, you are not using any:

1) Make the optimization with monthly data, with the original risk return functions in the specification. For plotting you can anualize making

Port.Anua.Returns=prt.ef$frontier[,1]*12 
Port.Anua.StDev=prt.ef$frontier[,2]*12^.5

The weights will be the same for monthly or annualized portfolios.

prt.ef$frontier[,-(1:3)]

2) Transform your monthly returns in annualized returns multiplying by 12. Then do the optimization with the usual procedure, all risk and return will be already annualized in prt.ef$frontier.

Related to the jagged line in EF. Using your portfolio specification I was also able to recreate the same behavior. For the following plot I used edhec data, your specification with original mean and StdDev in the objectives:

data(edhec)
returns <- edhec[,1:3]

enter image description here

That behavior must be influenced by the specification or the optimization algorithm you are using. I did the same optimization with solve.QP from package quadprog. This is the result. enter image description here

Update

The code is here:

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...