I have a covariance matrix and vector of expected returns as my inputs. I have used optim to solve for the weights that maximize the portfolio's return/volatility. I like optim as you can create your own function which you enter into the optimization. I have checked the results against Excel's solver and it works fine.
For the next step I want to maximize the portfolio return for a given target volatility. I am struggling with this as optim only allows one to place constraints on the solved parameters (weights in my case) using method="L-BFGS-B"
I thought I could get around this by using IF statements in my function (which is going to be maximized) such that if the absolute difference between my portfolio volatility and my target volatility is more than a specific threshold, make the portfolio return = 0, otherwise use the calculated portfolio return. I’ve defined how to calculate the portfolio volatility and return in my function. I was hoping that as the optimizer solved the weights it would essentially discard all the solutions I don’t want as their returns would be zero. Unfortunately this didn’t happen.
This is my coding. Does anyone know how I can achieve this using optim or what I am doing wrong?
#generate data set
set.seed(1)
A <- runif(100);head(A)
B <- runif(100);head(B)
C <- runif(100);head(C)
D <- runif(100);head(D)
returns <- cbind(A,B,C,D)
cov(returns)
Weights <-cbind(0.25,0.25,0.25,0.25) #starting point is an equally weighted portfolio
EReturns <- cbind(0.0064,0.0045,-0.0050,0.0028); #Expected Returns
VCV <- cov(returns) #Sample covariance matrix
TargetVol <- 0.01
OptWeightE <- function(Weights, ExpectedReturns, VCV, TargetVol){
Weights <- abs(Weights)/sum(abs(Weights)) #ensures all the weights will be positive and sum to 100%
PReturn <- Weights %*% t(EReturns)
PVol <- ((Weights %*% VCV) %*% Weights)^0.5
if (abs(PVol- TargetVol) > 0.005) {
PReturn <- 0
}
if (abs(PVol - TargetVol) < 0.005) {
PReturn <- Weights %*% t(EReturns)
}
-PReturn #negative the default is to minimise
}
solE <- optim(par = Weights, fn =OptWeightE,ExpectedReturns = EReturns, VCV = VCV, TargetVol = 0.01)
optWE <- abs(solE$par)/sum(solE$par); optWE
sum(optWE)
optVolWE <- ((optWE %*% VCV) %*% t(optWE))^0.5; optVolWE
optRE <- optWE %*% t(EReturns); optRE