# Jointly estimates a portfolio with risk-parity strategy and asset selection
#
# @param mu mean vector of the random returns of n assets
# @param Sigma positive definite covariance matrix of the random returns
# of n assets
# @param w0 initial estimate of the portfolio weights
# @param risk_contrib function that takes the portfolio weights and the
# covariance matrix of the returns as inputs and outputs the risk
# contribution of each asset
# @param gamma learning rate for the optimization
# @param zeta how much to decrease the learning rate per iteration such that
# gamma <- gamma * (1 - zeta * gamma)
# @param nu regularization parameter
# @param l1 regularization parameter
# @param l2 regularization parameter
# @param tau regularization parameter
# @param type approximation type
# @param maxiter maximum number of iterations
# @param w_tol convergence tolerance on the portfolio weights
# @param theta_tol convergence tolerance on the average of the RCs for the
# selected assets
# @param ftol convergence tolerance on the objective function
# @export
sparseRiskParityPortfolio <- function(mu, Sigma, w0 = NA, risk_contrib = NA,
gamma = 1e-1, zeta = 1e-2, nu = 5e-1,
l1 = 1e-1, l2 = 4, tau = 1e-3, type = "1",
p = 2e-3, e = 1e-8, maxiter = 5000,
w_tol = 1e-4, theta_tol = 1e-4, ftol = 1e-4) {
if (is.na(risk_contrib)) {
# g is defined in successiveConvexApprox.R
risk_contrib = g
}
if (any(is.na(w0))) {
w0 <- 1 / diag(Sigma)
w0 <- w0 / sum(w0)
}
# initialization
rho_sq <- rho(w0, p, e) ^ 2
x <- rho_sq / sum(rho_sq ^ 2)
theta0 <- sum(x * risk_contrib(w0, Sigma))
# save likelihood and objective at the initial point
nll0 <- negLogLikelihood(w0, nu, mu, Sigma)
nll_seq <- c(nll0)
fun0 <- nll0 + negLogPrior(w0, w0, theta0, Sigma, l1, l2, p, e, tau, type)
fun_seq <- c(fun0)
for (k in 1:maxiter) {
# update theta
theta <- theta_update(theta0, w0, Sigma, risk_contrib, p, e, gamma)
# update w
w <- w_update(w0, theta, nu, gamma, l1, l2, mu, Sigma, tau, p, e, type)
# check tolerance on parameters
w_err <- norm(w - w0, "2") / max(1., norm(w, "2"))
theta_err <- abs(theta - theta0) / max(1., theta)
if ((w_err < w_tol) & (theta_err < theta_tol))
break
# check tolerance on objective function
nll <- negLogLikelihood(w, nu, mu, Sigma)
nll_seq <- c(nll_seq, nll)
fun <- nll + negLogPrior(w, w0, theta, Sigma, l1, l2, p, e, tau, type)
fun_seq <- c(fun_seq, fun)
ferr <- abs(fun - fun0) / max(1., abs(fun))
if (ferr < ftol)
break
# update gamma
gamma <- gamma * (1 - zeta * gamma)
w0 <- w
theta0 <- theta
fun0 <- fun
}
return(list(portfolio_weights = w, negloglike = nll_seq, obj_fun = fun_seq))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.