# How to set a fixed return for mean-CVaR portfolio optimization?

I'm using the timeSeries and fportfolio package in R to minimize the CVaR with different constraints for a given portfolio. Everything is working out so far. However, I can't manage to set a fixed mean return. When I use setTargetReturn(cvar_spec) <- 0.04 , as in the code below, the further code ignores it and calculates the CVAR for a smaller mean return. The last function, portfolioFrontier() does not return the desired value pair as well. Does anyone know a way how to fix this?

library(timeSeries)
library(timeDate)
library(fPortfolio)

lppAssets3 <- 100 * LPP2005.RET[, 1:6]
colMeans(lppAssets3)

cvar_spec <- portfolioSpec()
setTargetReturn(cvar_spec) <- 0.04
setType(cvar_spec) <- "CVaR"
setSolver(cvar_spec) <- "solveRglpk.CVAR"
getOptimize(cvar_spec)
getSolver(cvar_spec)

box.1 <- "minW[1:6] = 0.0"
box.2 <- "maxW[1:6] = 0.5"

group.1 <- "minsumW[1:6] = 1.0"
group.2 <- "maxsumW[1:6] = 1.0"

constraints_cvar1 <- c(box.1, box.2, group.1, group.2)

minCVAR_Portfolio2 <- minriskPortfolio(lppAssets3,
cvar_spec,
constraints = constraints_cvar1
)
getWeights(minCVAR_Portfolio2)

CVAR_Portfolio2_frontier <- portfolioFrontier(lppAssets3,
cvar_spec,
constraints = constraints_cvar1
)


I don't use fPortfolio but when I run your code example, I first get an error:

## Error in add.constraint() : could not find function "add.constraint"


Nevertheless, after that, I can extract a solution:

getWeights(minCVAR_Portfolio2)
##      SBI      SPI      SII      LMI      MPI      ALT
## 0.240491 0.000172 0.169241 0.500000 0.000000 0.090096


Cross-checking with minCVaR in package ǸMOF (which I maintain):

library("NMOF")
R <- as.matrix(lppAssets3)
c(minCVaR(R, q = 0.05, wmax = 0.5))
## [1] 0.240491 0.000172 0.169241 0.500000 0.000000 0.090096


So, the computation so far seems reasonable. But your problem probably is the much-too-high required return of 0.04: Inspecting lppAssets3 suggests that these are daily data. And then 4% is way too high: apply(lppAssets3, 2, max) shows you that no asset ever had a single daily return of 4% in your sample:

##     SBI     SPI     SII     LMI     MPI     ALT
## 0.00364 0.02584 0.01201 0.00368 0.02408 0.01679


And the column means are much closer to zero. So there simply is no feasible solution. A check:

minCVaR(R, q = 0.05, wmax = 0.5, min.return = 0.04,
Rglpk.control = list(verbose = TRUE))
## GLPK Simplex Optimizer 5.0
## 379 rows, 384 columns, 2975 non-zeros
##       0: obj =   0.000000000e+00 inf =   1.040e+00 (2)
##     220: obj =   3.241764706e-02 inf =   3.915e-02 (1) 2
## LP HAS NO PRIMAL FEASIBLE SOLUTION
## ....


I guess here that you might mean an annual return of 4%, but then you'd have to scale it so that it is aligned with the return scenarios (e.g. 0.04/250 = 0.00016).

Update following the comment:

You can compute portfolio returns under the scenario set, and then it becomes straightforward to compute quantities of interest.

R <- as.matrix(lppAssets3)
sol <- minCVaR(R, q = 0.05, wmax = 0.5)
p.rt <- c(R %*% sol)


I use c() to drop (unnecessary) attributes. You now have a univariate return series p.rt:

vol <- sd(p.rt)
## [1] 0.00103604
VaR <- quantile(p.rt, probs = 0.05)
## -0.001551667
CVaR <- mean(p.rt[p.rt <= VaR])
## [1] -0.001952581


The covariance matrix is not (explicitly) used in the computation, but cov(R) is the standard estimator.

Note that if you compute CVar-optimal portfolios with the LP-formulation of Rockafellar/Uryasev, as minCVaR does per default, you could also directly reuse some results of the LP, for instance the VaR:

-attr(sol, "LP")\$solution[1]
## [1] -0.001551667


Perhaps this note on the implementation of minCVaR` also helps.

• First of all, I must say that I actually used lppAssets3 <- 100 * LPP2005.RET[, 1:6], but forgot to paste the updated code (that is why there is also this add.constraint() - but I edited the code now). So the returns are given in %, and I'm aware that the target return is 0.04% daily. Anyway, this doesn't change the outcome. However your hint to the NMOF package is great (thank you very much!) as it does consider the min return. But how can I return the same results summary as with minriskPortfolio() (the optimal CVaR itself, the VaR, the cov matrix,...)? Aug 15 '21 at 11:00
• You can compute portfolio returns under the scenario set, and then it becomes straightforward to compute quantities of interest. I have update the answer. Aug 16 '21 at 8:17