Learn R Programming

CLA (version 0.96-3)

CLA: 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)

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).

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.

Author

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

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.

References

Markowitz, H. (1952) Portfolio selection, The Journal of Finance 7, 77--91; tools:::Rd_expr_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; tools:::Rd_expr_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; tools:::Rd_expr_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

Run this code
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 ) $ 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))

Run the code above in your browser using DataLab