calc_weights: Calculate the optimal portfolio weights using a variety of...

View source: R/RcppExports.R

calc_weightsR Documentation

Calculate the optimal portfolio weights using a variety of different objective functions.

Description

Calculate the optimal portfolio weights using a variety of different objective functions.

Usage

calc_weights(returns, controlv)

Arguments

returns

A time series or a matrix of returns data (the returns in excess of the risk-free rate).

controlv

A list of portfolio optimization model parameters (see Details).

Details

The function calc_weights() calculates the optimal portfolio weights using a variety of different objective functions.

The function calc_weights() accepts a list of portfolio optimization parameters through the argument controlv. The list of portfolio optimization parameters can be created using the function param_portf(). Below is a description of the parameters.

If method = "maxsharpe" (the default) then calc_weights() calculates the weights of the maximum Sharpe portfolio, by multiplying the reduced inverse of the covariance matrix \strong{C}^{-1} times the mean column returns \bar{r}:

\strong{w} = \strong{C}^{-1} \bar{r}

If method = "maxsharpemed" then calc_weights() uses the medians instead of the means.

If method = "minvarlin" then it calculates the weights of the minimum variance portfolio under linear constraint, by multiplying the reduced inverse of the covariance matrix times the unit vector:

\strong{w} = \strong{C}^{-1} \strong{1}

If method = "minvarquad" then it calculates the weights of the minimum variance portfolio under quadratic constraint (which is the highest order principal component).

If method = "sharpem" then it calculates the momentum weights equal to the Sharpe ratios (the returns divided by their standard deviations):

\strong{w} = \frac{\bar{r}}{\sigma}

If method = "kellym" then it calculates the momentum weights equal to the Kelly ratios (the returns divided by their variance):

\strong{w} = \frac{\bar{r}}{\sigma^2}

calc_weights() calls the function calc_inv() to calculate the reduced inverse of the covariance matrix of returns. It performs regularization by selecting only the largest eigenvalues equal in number to dimax.

In addition, calc_weights() applies shrinkage to the columns of returns, by shrinking their means to their common mean value:

r^{\prime}_i = (1 - \alpha) \, \bar{r}_i + \alpha \, \mu

Where \bar{r}_i is the mean of column i and \mu is the average of all the column means. The shrinkage intensity alpha determines the amount of shrinkage that is applied, with alpha = 0 representing no shrinkage (with the column means \bar{r}_i unchanged), and alpha = 1 representing complete shrinkage (with the column means all equal to the single mean of all the columns: \bar{r}_i = \mu).

After the weights are calculated, they are scaled, depending on several arguments.

If rankw = TRUE then the weights are converted into their ranks. The default is rankw = FALSE.

If centerw = TRUE then the weights are centered so that their sum is equal to 0. The default is centerw = FALSE.

If scalew = "voltarget" (the default) then the weights are scaled (multiplied by a factor) so that the weighted portfolio has an in-sample volatility equal to voltarget.

If scalew = "voleqw" then the weights are scaled so that the weighted portfolio has the same volatility as the equal weight portfolio.

If scalew = "sumone" then the weights are scaled so that their sum is equal to 1. If scalew = "sumsq" then the weights are scaled so that their sum of squares is equal to 1. If scalew = "none" then the weights are not scaled.

The function calc_weights() is written in C++ RcppArmadillo code.

Value

A column vector of the same length as the number of columns of returns.

Examples

## Not run: 
# Calculate covariance matrix and eigen decomposition of ETF returns
retp <- na.omit(rutils::etfenv$returns[, 1:16])
ncols <- NCOL(retp)
eigend <- eigen(cov(retp))
# Calculate reduced inverse of covariance matrix
dimax <- 3
eigenvec <- eigend$vectors[, 1:dimax]
eigenval <- eigend$values[1:dimax]
invmat <- eigenvec %*% (t(eigenvec) / eigenval)
# Define shrinkage intensity and apply shrinkage to the mean returns
alpha <- 0.5
colmeans <- colMeans(retp)
colmeans <- ((1-alpha)*colmeans + alpha*mean(colmeans))
# Calculate weights using R
weightr <- drop(invmat %*% colmeans)
# Apply weights scaling
weightr <- weightr*sd(rowMeans(retp))/sd(retp %*% weightr)
weightr <- 0.01*weightr/sd(retp %*% weightr)
weightr <- weightr/sqrt(sum(weightr^2))
# Create a list of portfolio optimization parameters
controlv <- HighFreq::param_portf(method="maxsharpe", dimax=dimax, alpha=alpha, scalew="sumsq")
# Calculate weights using RcppArmadillo
weightcpp <- drop(HighFreq::calc_weights(retp, controlv=controlv))
all.equal(weightcpp, weightr)

## End(Not run)


algoquant/HighFreq documentation built on Feb. 9, 2024, 8:15 p.m.