Skip to content
All library documents

Formulating CVaR Portfolio Optimization with a Risk Aversion Penalty

Article Quant Q&A · Author: Malva

Summary

The document presents an attempt to maximize expected portfolio return minus a risk-aversion-weighted conditional value at risk (CVaR) penalty. It uses the Rockafellar-style scenario formulation, with a threshold variable for VaR and auxiliary variables representing losses beyond that threshold, then encodes the problem as a linear program in R using Rglpk.

The author reports that a two-asset test returns the same corner allocation across risk-aversion settings, unlike results from a standard CVaR formulation, and asks what is wrong. No answer or diagnosis is included, so the code should be treated as an unverified implementation rather than a validated optimization method. The post is useful for identifying the modeling ingredients and the symptom, but readers must check the objective signs, scenario constraints, variable layout, and solver conventions before relying on its outputs.

Key ideas

  • CVaR portfolio selection can be expressed with a VaR threshold and scenario-specific excess-loss variables.
  • The proposed objective balances expected return against a risk-aversion-weighted risk measure.
  • The example encodes the optimization as a linear program with scenario constraints.
  • The reported allocation does not vary with risk aversion, and the document gives no resolution.

Tags

Full text
# CVaR portfolio optimization with risk aversion parameter


# CVaR portfolio optimization with risk aversion parameter












I'm trying to implement the Rockafellar's function described in this paper http://past.rinfinance.com/agenda/2009/yollin_slides.pdf with a risk aversion parameter for my thesis. The function to maximize should be: $$ \max (w):\, w'\mu - \lambda\Big(R_\text{VAR}+\frac{\sum ds}{(1-\beta)s}\Big) $$

The code I have implemented is:

```
cvarOpt= function(rmat, alpha=0.05, lambda = 10000, rmin=0, wmin=0, wmax=1, weight.sum=1) { 

require(Rglpk) 

n = ncol(rmat) 

# number of assets 
s = nrow(rmat) 

# number of scenarios i.e. periods 
averet = colMeans(rmat)

# creatobjective vector, constraint matrix, constraint rhs 
#Amat = rbind(cbind(rbind(1, averet), matrix(data = 0, nrow = 2, ncol = s+1)), cbind(rmat, diag(s), 1)) 

first <- cbind(matrix(1, nrow = 2, ncol = n), rbind(1, averet), matrix(data = 0, nrow = 2, ncol = s+1))
second <- cbind(matrix(1, nrow = s, ncol = n), rmat, diag(s), 1)

colnames(first) <- 1:(1+2*n+s)
colnames(second) <- 1:(1+2*n+s)

Amat <- rbind(first, second)

objL = c(averet, rep(0, n), rep(lambda/(alpha*s), s), lambda) 

bvec= c(weight.sum, rmin, rep(0, s))

# direction vector 
dir.vec= c("==", ">=", rep(">=", s))

# bounds on weights 
bounds = list(lower = list(ind= 1:n, val= rep(wmin, n)), upper = list(ind = 1:n, val = rep(wmax, n)))

res= Rglpk_solve_LP(obj = objL, mat = Amat, dir = dir.vec, rhs = bvec, types = rep("C", length(objL)), max = TRUE, bounds = bounds)

w = as.numeric(res$solution[1:n]) 

return(list(w = w, status = res$status))
}
```

I guess it doesn't work because with a portfolio of only two assets I get always (1, 0) as weights whatever the lambda is while with the standard CVaR formulation I get (0.96, 0.4)...

Thank you in advance.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.