Constraining Portfolio Leverage in Mean-Variance Optimization
Summary
The document discusses mean-variance portfolio optimization with a target return, a fully invested constraint, and a limit on the sum of absolute portfolio weights. That absolute-weight constraint limits gross leverage while allowing short positions. It notes that a standard quadratic programming setup handles linear constraints but not the absolute-value constraint directly, and points to nonlinear optimization as an alternative.
A second approach reformulates the absolute values with auxiliary nonnegative variables. Constraints make each auxiliary variable at least as large as the magnitude of its corresponding weight, so their sum can enforce the leverage cap within a quadratic program. An example reports weights that meet a target return and leverage limit.
The discussion flags solver and formulation caveats: replacing the L1 constraint with a squared-weight constraint changes the meaning, while per-asset bounds are distinct from a portfolio-wide leverage cap. The included example is illustrative and does not establish out-of-sample performance or robustness.
Key ideas
- A cap on the sum of absolute weights limits gross leverage while permitting short sales.
- The L1 constraint can be represented with auxiliary nonnegative variables that bound each weight’s absolute value.
- Quadratic programming can then impose the leverage cap through linear constraints alongside target-return and budget constraints.
- A squared-weight constraint and individual position bounds represent different restrictions from an L1 leverage cap.
- The example demonstrates feasibility but provides no evidence of investment performance.
Tags
Full text
# R package for portfolio
# R package for portfolio
In the context of modern portfolio theory, one often wishes to minimise $\mathbf{w}^{\mathrm{{\scriptstyle T}}}\boldsymbol{\Sigma}\mathbf{w}$ subject to $\mathbf{w}^{T}\boldsymbol{\mu}=c_{1}$, $\left\Vert \mathbf{w}\right\Vert _{1}<c_{2}$ and $\mathbf{w}^{T}\mathbf{1}=1$. Is there an R function or package to do this?
## Answer by Richi Wa (score 4, accepted)
https://quant.stackexchange.com/a/17904
If you can add linear constriants (as you can do in quadprog) then you can formulate $w \mu = c_1$ as linear constraint, no matter what $\mu$ is (and first delete it from the objective by setting the parameter to zero. The only problem is the one norm. Let my clarify, this is: $$ \sum_{i=1}^n |w_i| < c_2 $$ Thus you allow for short sales but you want to limit leverage -> right? I am afraid that quadprog can not handle such constraints.
Some solvers can handle quadratic constraints then $$ \sum_{i=1}^n |w_i|^2 = w^T w< c_2^* $$ would limit leverage. The first equation above describes a constraint for the $L_1$-norm. If you mean that $|w_i|$ should be bounded for each $i$ then of course you get this by the two inequalities: $$ w \le c_2 \quad \text{and} \quad w \ge -c_2. $$
EDIT after the comment of John: THe package nloptr can handle non-linear constraints. Follow the examples in the link to define the objective function and the constraint. Note that the gradient of $$ f(w) = w^T \Sigma w $$ is given by $$ 2 \Sigma w.$$ Providing the gradient will improve the result of this non-linear optimizer.
EDIT: If you want something built for portfolio optimization directly then you could look at fPorfolio and e.g. this presentaton. I find that the documentation lacks details and I wonder whether all features "promised" in the presentation work properly. On page 13 they say that the package can handle non-linear constraints. If you try it then please tell us whether this works.
## Answer by WaltS (score 2)
https://quant.stackexchange.com/a/17901
I wonder if it's possible to use `solve.QP` from `quadprog` by using dummy variables. One dummy variable $y_i$ would be used for each $w_i$, each $y_i$ would be constrained to be greater than zero, and the leverage constraint would be applied to the sum of the $y_i$. Problem formulation would look like $$ \text{min } w^tΣw $$ subject to the constraints $$ w^t\mu= c_1 $$ $$ w^t 1 = 1 $$
$$ y_i \geq 0 $$ $$ w_i + y_i \geq 0 $$ $$ -w_i + y_i \geq 0 $$
$$ -\sum y_i \geq -c_2 $$
Code could look like
```
leveraged_port <- function( er,cov.mat, target_return=NULL, leverage=1., tickers=NULL ){
library(quadprog)
# leverage checks and adjustments
if(leverage < 1.) stop( "leverage must be >= 1.")
if( target_return > (leverage+1)/2*max(er)) stop("target_return not achievable; increase leverage or decrease target_return")
lev_adj <- 1.E-06
if(leverage < 1 + lev_adj) leverage <- 1 + lev_adj
n_asset <- length(er)
zeros <- integer(n_asset)
# quad problem
# calculate small diag value for dummy variables so Dmat is positive def.
diag_dum <- 1.e-05*min(diag(cov.mat))
Dmat <- diag(diag_dum, nrow=2*n_asset, ncol=2*n_asset)
Dmat[1:n_asset, 1:n_asset] <- 2*cov.mat
dvec <- numeric(2*n_asset)
meq <- 2
# constraints on weights
bvec <- c(1, target_return)
Amat <- matrix( c(rep(1,n_asset), er, diag(n_asset), -diag(n_asset), diag(0, nrow=n_asset),
zeros), nrow=n_asset)
# constraints on dummy variables
bvec <- c(bvec, zeros, zeros, zeros, -leverage)
Amat <- rbind( Amat, matrix(c(zeros, zeros, diag(n_asset), diag(n_asset), diag(n_asset),
-rep(1,n_asset)), nrow=n_asset))
sol<-solve.QP(Dmat, dvec, Amat, bvec, meq=meq)
weights<-sol$solution[1:n_asset]
names(weights) <- tickers
exp.ret <- t(er)%*%weights
std.dev <- sqrt(weights %*% cov.mat %*% weights)
ret <- list(er = as.vector(exp.ret),
StdDev = as.vector(std.dev),
weights = weights,
sum_weights = sum(weights),
leverage = sum(abs(weights)),
lagrange_mults=sol$Lagrangian )
}
```
Results on the following example problem seem feasible
```
library(quantmod)
tickers <- c("MSFT","AAPL", "AMZN", "YHOO", "XOM", "CVX", "UNH", "NKE")
prices <- do.call(cbind,
lapply(tickers, function(x) getSymbols(x, from="2010-01-01", auto.assign=FALSE, warnings=FALSE)[,6]))
colnames(prices) <- tickers
returns <- diff(prices, arithmetic=FALSE, na.pad=FALSE) - 1
means <- sapply(returns, mean)
QPsol <- leveraged_port(er=means, cov.mat=cov(coredata(returns)), target_return=.0016, leverage=1.8, tickers)
```
with the results
```
QPsol
$er
[1] 0.0016
$StdDev
[1] 0.01830004
$weights
MSFT AAPL AMZN YHOO XOM CVX UNH NKE
-9.809695e-14 1.044254e+00 -5.297152e-14 -1.780017e-17 -4.000000e-01 -1.556950e-13 3.557464e-01 4.224909e-14
$sum_weights
[1] 1
$leverage
[1] 1.8
```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.