# Weight optimization in order to maximize correlation [R]

I'm researching a way to speed up a problem I already have in Excel's Solver.

I wanna know if my approach is correct (I doubt it tbh) and if there're better alternatives.

I have a matrix of scores I have already calculated through means non relevant to this topic and I want to maximize the lagged correlation of the weighted sum of these scores with the return of a certain asset.

The restrictions are simple:

• Weights have to be greater than 0
• Weights have to be smaller than 1
• Weights have to sum 1

I'm having issues with the last one and have read other posts regarding the issue. However their preferred solution seems to be to rebalance the optim output such that the weights sum 1. I do not believe that would work in my case (I could be wrong).

Reproducible example:

library(tidyr)
library(dplyr)
set.seed(42)
days <- 500
cols <- 5
lag_score <- 30*3
corr_window <- 30*6

scores <- matrix(runif(days*cols), nrow = days, ncol = cols)
colnames(scores) <- c("Momentum","Growth","Quality","Value","Volatility")
returns <- rnorm(days,mean = 0,sd = 0.05)

#General procedure

weights <- rep(0.2,cols)
f_score <- scores %*% weights
x <- f_score[lag_score:(lag_score+corr_window-1)]
y <- returns[1:corr_window]
#What I want to maximize
correl <- cor(x,y)


My attempt so far is the following:

#Function to maximize
cor.model <- function(w=rep(0.2,5),
sc=scores,
ret=returns,
lag_sc=lag_score,
corr_w=corr_window){
f_score <- sc %*% (w/sum(w))
x <- f_score[lag_sc:(lag_sc+corr_w-1)]
y <- ret[1:corr_w]
correl <- cor(x,y)
return(correl)
}

#Output
out <- optim(par = rep(1/cols,cols),
fn = cor.model,
method = "L-BFGS-B",
lower = rep(0,cols), # W_i >= 0 for all i
upper = rep(1,cols), # W_i <= 1 for all i)
control = list(fnscale = -1),
sc=scores,
ret=returns,
lag_sc=lag_score,
corr_w=corr_window)


Alternative with nloptr:

library(nloptr)
optres <- nloptr(x0 = rep(1/cols,cols),
eval_f = cor.model.min,
lb = rep(0,cols),
ub = rep(1,cols),
opts = list('algorithm' = "NLOPT_LN_BOBYQA",
'print_level' = 2,
'maxeval' = 10000,
'xtol_rel' = 0),
sc=scores,
ret=returns,
lag_sc=lag_score,
corr_w=corr_window)


cor.model.min is cor.model with a negative result. (-correl)

According to other posts my answer should be out$$par/sum(out$$par) or optres$$solution/sum(optres$$solution) depending on the approach. Is this correct?

The problem in my head is the following:

(C being correlation and not complex) s.t. The restrictions stated above.

Where Score is the matrix multiplication of the scores matrix and the weights vector and Ret is the returns vector.

Yes. The final vector of weights is, as you stated: out$$par/sum(out$$par)
Also, do you realize that optim minimizes by default? Because your code comment says you want to maximize correlation. You can flip it around by doing return(-correl) in your function.
• As of the double normalization I meant Line 1 and 2 of the function, inside f_score there's already a w/sum(w). In my head doing a correlation function turns what would be linear into non-linear because of the variance and covariances. In my optim example I'm using a negative fnscale so that it maximizes instead of minizing. Thanks for your input! – GonzaloXavier Jan 2 '19 at 19:56