CLA {CLA}R Documentation

Critical Line Algorithm for mean-variance optimal portfolio

Description

The Critical Line Algorithm was first proposed by Markowitz(1987) to solve the mean-variance optimal portfolio problem.

We solve the problem with “box” constraints, i.e., allow to specify lower and upper bounds (via lB and uB) for each asset weight.

Here we provide a pure R implementation, quite fine tuned and debugged compared to earlier ones.

Usage

CLA(mu, covar, lB, uB,
    check.cov = TRUE, check.f = TRUE,
    tol.lambda = 1e-07,
    give.MS = TRUE, keep.names = TRUE, trace = 0)

Arguments

mu

numeric vector of length n containing the expected return E[R_i] for 1=1,2,\dots,n.

covar

the n \times n covariance matrix of the returns, must be positive definite.

lB, uB

vectors of length n with lower and upper bounds for the asset weights.

check.cov

logical indicating if the covar matrix should be checked to be positive definite.

check.f

logical indicating if a warning should be produced when the algorithm cannot produce a new (smaller) lambda even though there are still free weights to be chosen.

tol.lambda

the tolerance when checking for lambda changes or being zero.

give.MS

logical indicating if MS() should be computed (and returned) as well.

keep.names

logical indicating if the weights_set matrix should keep the (asset) names(mu).

trace

an integer (or logical) indicating if and how much diagnostic or progress output should be produced.

Details

The current implementation of the CLA is based (via Norring's) on Bailey et al.(2013). We have found buglets in that implementation which lead them to introduce their “purge” routines (purgeNumErr, purgeExcess), which are no longer necessary.

Even though this is a pure R implementation, the algorithm is quite fast also when the number of assets n is large (1000s), though that depends quite a bit on the exact problem.

Value

an object of class "CLA" which is a list with components

weights_set

a n \times m matrix of asset weights, corresponding to the m steps that the CLA has completed or the m “turning points” it has computed.

free_indices

a list of length m, the k-th component with the indices in {1,\dots,n} of those assets whose weights were not at the boundary after ...

gammas

numeric vector of length m of the values \gamma_k for CLA step k, k=1,\dots,n.

lambdas

numeric vector of length m of the Lagrange parameters \lambda_k for CLA step k, k=1,\dots,n.

MS_weights

the \mu(W) and \sigma(W) corresponding to the asset weights weights_set, i.e., simply the same as MS(weights_set = weights_set, mu = mu, covar = covar).

Note

The exact results of the algorithm, e.g., the assets with non-zero weights, may slightly depend on the (computer) platform, e.g., for the S&P 500 example, differences between 64-bit or 32-bit, version of BLAS or Lapack libraries etc, do have an influence, see the R script ‘tests/SP500-ex.R’ in the package sources.

Author(s)

Alexander Norring did the very first version (unpublished master thesis). Current implementation: Yanhao Shi and Martin Maechler

References

Markowitz, H. (1952) Portfolio selection, The Journal of Finance 7, 77–91; doi: 10.2307/2975974.

Markowitz, H. M. (1987, 1st ed.) and Markowitz, H. M. and Todd, P. G. (2000) Mean-Variance Analysis in Portfolio Choice and Capital Markets; chapters 7 and 13.

Niedermayer, A. and Niedermayer, D. (2010) Applying Markowitz’s Critical Line Algorithm, in J. B. Guerard (ed.), Handbook of Portfolio Construction, Springer; chapter 12, 383–400; doi: 10.1007/978-0-387-77439-8_12.

Bailey, D. H. and López de Prado, M. (2013) An open-source implementation of the critical-line algorithm for portfolio optimization, Algorithms 6(1), 169–196; doi: 10.3390/a6010169,

Yanhao Shi (2017) Implementation and applications of critical line algorithm for portfolio optimization; unpublished Master's thesis, ETH Zurich.

See Also

MS; for plotting CLA results: plot.CLA.

Examples

data(muS.sp500)
## Full data taking too much time for example
set.seed(47)
iS <- sample.int(length(muS.sp500$mu), 24)

CLsp.24 <- CLA(muS.sp500$mu[iS], muS.sp500$covar[iS, iS], lB=0, uB=1/10)
CLsp.24 # using the print() method for class "CLA"

plot(CLsp.24)

if(require(Matrix)) { ## visualize how weights change "along turning points"
  show(image(Matrix(CLsp.24$weights_set, sparse=TRUE),
             main = "CLA(muS.sp500 <random_sample(size=24)>) $ weights_set",
             xlab = "turning point", ylab = "asset number"))
}

## A 3x3 example (from real data) where CLA()'s original version failed
## and  'check.f = TRUE' produces a warning :
mc3 <- list(
    mu = c(0.0408, 0.102, -0.023),
    cv = matrix(c(0.00648, 0.00792, 0.00473,
                  0.00792, 0.0334,  0.0121,
                  0.00473, 0.0121, 0.0793), 3, 3,
           dimnames = list(NULL,
                           paste0(c("TLT", "VTI","GLD"), ".Adjusted"))))

rc3 <- with(mc3,  CLA(mu=mu, covar=cv, lB=0, uB=1, trace=TRUE))


[Package CLA version 0.96-2 Index]