1
$\begingroup$

I am currently trying to write a little script in R to determine the optimal weights given a fixed risk aversion parameter. The problem I have is that by increasing the risk aversion parameter I think that parabola should become wider. However, in my case it yields the same parabola with minor differences. The problem I am encountering is that I am not sure if the way I formulated the solve.qp is correct or not My idea was to minimize -w^tmu+aversion/2 w^tSigma*w; where w = weights, mu = mean of returns, Sigma= covariance of returns. I did try using portfolio.optim from the tseries package, but it does not allow me to fix the risk aversion parameter or does it ?

You may find my code below.

    efficientPortfolio <- function(er,cov.mat,aversion=3,target.return){

    Dmat<- cov.mat*aversion
    dvec<- as.vector(er)
    ones<- rep(1,length(er))
    zeros <-rep(0,length(er))
    Identity <- matrix(0,length(er),length(er))
    diag(Identity)<-1
    Amat<- (cbind((ones),colMeans(data),Identity)) #no short sell

    bvec<- c(1,target.return,zeros) #no short sell

    sol<-solve.QP(Dmat,dvec,Amat,bvec=bvec,meq=1)
    weights<-sol$solution


    exp.ret <- crossprod(dvec,weights)
    std.dev <- sqrt(weights %*% cov.mat %*% weights)

    ret <- list("call" = call,
                "er" = as.vector(exp.ret),
                "sd" = as.vector(std.dev),
                "weights" = weights) 
    ret
    }



    efficientFrontier <- function(er,cov.mat, nport = 20,aversion=3) {
    ef <- matrix(0, nport, 2 + length(er))

    pm <- seq((min(er)), (max(er)), 
              length.out = nport)

    for (i in 1:nport) {

            port <-         efficientPortfolio(er,cov.mat,aversion=aversion,target.ret=pm[i])

            ef[i, 1] <- port$sd
                ef[i, 2] <- port$er
            ef[i, 3:ncol(ef)] <- port$weights

     }
    list(ef = ef[, 1:2], weights = ef[, -1:-2])
     }

also
er and cov.mat in my case are :

   er<-c(2.626568e-05, 6.542483e-06, 2.169358e-05, 1.510713e-04 ,7.113906e-05 )
   cov.mat<-matrix(c(4.408143e-04 ,   1.487359e-05, 1.680034e-05,   3.066478e-04,   2.069675e-04,
1.487359e-05,   7.270984e-03,   9.134981e-06,   -1.699836e-05,  7.956140e-06,
1.680034e-05,   9.134981e-06,   6.528898e-04,   5.397248e-06,   9.887768e-06,
3.066478e-04,   -1.699836e-05,  5.397248e-06,   1.473456e-03,   6.657914e-04,
2.069675e-04,   7.956140e-06,   9.887768e-06,   6.657914e-04,   5.090455e-04),5,5)

and the package I am using is quadprog Thanks in advance. Jc

EDIT : During some tests I noticed that when I apply sove.qp for different Dmat=cov.mat*aversion, where aversion = 3 or 4, yields the same weights. How is this possible ?

$\endgroup$
2
$\begingroup$

Looking at your code, you seem to be mixing the risk minimization formulation of the mean-variance problem with the risk aversion formulation. Both formulations include the "budget" constraint, that the sum of the weights equal 1, and can require that each of the weights be greater than zero, the "long-only" inequality constraints. In the risk minimization problem, weights are found which minimize the portfolio variance subject to the constraint that the portfolio return equal a target return.

$$ \underset{w}{\arg \min} \quad w' Q w \quad \text{s.t} \quad rw = r_p,\quad \sum_i w_i=1, \quad w_i \geq 0\quad $$

where $Q$ is the covariance matrix and $r_p$ is the target portfolio return. In the risk aversion form, weights are found which maximize return less a risk aversion coefficient times the portfolio variance as you state in your post.

$$ \underset{w}{\arg \max} \quad w'r - \lambda w' Q w \quad \text{s.t} \sum_i w_i=1, \quad w_i \geq 0\quad $$

where $\lambda$ is the risk aversion coefficient. Notice that there is no constraint on portfolio return in the risk aversion formulation.

In your code, the second constraint is an inequality constraint on returns which requires the portfolio return be $\geq r_p$ . With this constraint, you solution switches from a risk aversion model to a risk minimization model when the return falls below the target return. This is a possible model but doesn't seem to be what you intended.

While there are many variations of portfolio optimization using different methods for calculating risk and return, once you've chosen a method, there is only one efficient frontier. The code below is a modification of your code which shows how risk and return vary for decreasing the value of $\lambda$ and that this is just an alternate way of mapping the efficient frontier given this set of risks and returns.

library(quadprog)
efficientPortfolio <- function(er,cov.mat,aversion=3, target_return=NULL, method= c("risk_min","risk_aver","mixed","min_var") ){
  n_asset <- length(er)
# quad problem
  if(method %in%  c("risk_min", "min_var")){
    aversion  = 1
    Dmat <- cov.mat
    dvec <- rep(0, n_asset)
    meq <- ifelse(method == "min_var", 1, 2)}  
  else {
    Dmat <- aversion*cov.mat
    dvec <- er
    meq <-  1}
# constraint eqns
  if(method %in% c("risk_aver","min_var")) {
    bvec <- c(1, rep(0,n_asset))
    Amat <- matrix( c(rep(1,n_asset), diag(nrow=n_asset)), nrow=n_asset)  }
  else {
    bvec <- c(1, target_return, rep(0,n_asset))
    Amat <- matrix( c(rep(1,n_asset), er, diag(nrow=n_asset)), nrow=n_asset)  }
  sol<-solve.QP(Dmat, dvec,Amat, bvec=bvec, meq=meq)
  weights<-sol$solution
      exp.ret <- t(er)%*%weights
      std.dev <- sqrt(weights %*% cov.mat %*% weights)
      ret <- list(er = as.vector(exp.ret),
                  sd = as.vector(std.dev),
                  weights = weights,
                  lagrange_mults=sol$Lagrangian )  
}

efficientFrontier <- function(er,cov.mat, nport=20, lambda_min = .1, lambda_max=2, lambda = 1,
                              target_return = NULL,  method = c("risk_min","risk_aver","mixed") ) {
 # if method = risk_min, input sequence of target_returns or use defaults; input target_returns < min_var return are not used
 #           = risk_aver, input upper and lower bounds of risk aversion coefficients lambda or use defaults
 #           = mixed, input single value of risk aversion coefficient lambda and seq of target_returns or use default
  n_asset <- length(er)
  method <- method[1]
  lambda <- if(method == "risk_min"){
                 nport <- ifelse(is.null(target_return), nport, length(target_return)) 
                 rep(NA_real_,nport) }
            else if(method == "mixed") rep(lambda, nport)
                  else seq(lambda_max, lambda_min, (lambda_min-lambda_max)/(nport-1)) 
  ef <- list(Efficient_Frontier_method = method, sol=matrix(0, nrow=nport, ncol=3, dimnames=list(NULL, c("lambda", "sd", "return")) ),
             weights= matrix(0, nrow=nport, ncol=n_asset),
             lagrange_mults=matrix(0, nrow=nport, ncol=ifelse(method=="risk_aver", 1, 2) +n_asset) )
  colnames(ef$lagrange_mults) <- if(method == "risk_aver") c("budget",rep("",n_asset)) else c("budget","target_return",rep("", n_asset))
    # calculate minimum variance portfolio
      port_min_var <- efficientPortfolio(er,cov.mat,target_return=NULL, aversion=NULL, method="min_var")
      cat("Mininum Variance Portfolio\n      sd          return\n")
      cat(sd=port_min_var$sd, return=port_min_var$er,"\n\n")
      target_return <- if(is.null(target_return)) seq(port_min_var$er, max(er), length.out=nport)
                   else {
                     target_return[target_return < port_min_var$er] <- port_min_var$er
                     target_return
                   }
  for (i in 1:nport) {
    port <- efficientPortfolio(er,cov.mat,aversion=lambda[i], target_return=target_return[i], method=method)
    ef$sol[i,"lambda"] <- lambda[i]
        ef$sol[i,"sd"] <- port$sd
        ef$sol[i,"return"] <- port$er
        ef$weights[i,] <- port$weights
        ef$lagrange_mults[i,] <- port$lagrange_mults
  }
  return(ef)
}

EDIT

The short answer to your question in the comment is yes. As the relation between the different risk formulations may be of interest, I've updated the code above to calculate efficient frontiers using both risk minimization (method = "risk_min") and risk aversion (method="risk_aver") methods. It will also treat your case where the two cases are mixed (method="mixed"). The code now also reports the lagrange multipliers for the points on the efficient frontier.

In particular, for your mixed case, which uses an inequality constraint on the portfolio return, you can see the switch from the risk adverse solution to the risk minimization solution. For smaller values of the target return where the return inequality constraint is not active, the portfolio solution is the same for different value of the target return since nothing has changed and the Lagrange multiplier for the return inequality is zero. As the target return increases, the portfolio return constraint becomes active and determines the solution, and the associated Lagrange multiplier takes on nonzero values. The solution has switched to the risk minimization case. It can be shown that the inverse of portfolio return Lagrange multiplier when it is nonzero is equal to the risk aversion coefficient. A thorough discussion of portfolio optimization using risk averse methods is given in an MSCI paper The Effects of Risk Aversion on Optimization especially in their Section B.6 where the relation between the Lagrange multipliers ( their dual variables $\pi_3$ and $\pi_4$ ) and the risk aversion coefficient is demonstrated.

$\endgroup$
  • $\begingroup$ Hi, thanks for you thorough answer, but just to be sure that I understood what you explained : it is not possible to set additional constaints in the risk aversion form e.g. minimum return in order to get the efficient frontier, because then I would fall into the risk minimization problem, which in return does not depend on the risk aversion parameter. Is that right ? Best regards, $\endgroup$ – Jonkie Mar 30 '15 at 21:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.