I’m trying to use Julia (0.5) and Convex.jl (with ECOS solver) to figure out, given a portfolio of 2 stocks, how can I distribute my allocations (in percent) across both stocks such that I maximize my portfolio return and minimize my risk (std dev of returns). I want to maximize what is known as the Sharpe ratio that is a calculation driven from what percentages I have in each of my 2 stocks. So I want to MAXIMIZE the Sharpe ratio and have the solver figure out what is the optimal allocation for the two stocks (I want it to tell me I need x% of stock 1 and 1-x% of stock 2). The only real constraint is that the sum of the percent allocations adds to 100%. I have code below that runs, but does not give me the optimal weights/allocations I’m expecting (which is 36.3% for Supertech & 63.7% for Slowpoke). The solver instead comes back with 50/50.
My intuition is that I either have the objective function modeled incorrectly for the solver, or I need to do more with constraints. I don’t have a good grasp on convex optimization so I’m winging it. Also, my objective function uses the variable.value attribute to get the correct output and I suspect I need to be working with the Variable expression object instead.
Question is, is what I’m trying to achieve something the Convex solver is designed for and I just have to model the objective function and constraints better, or do I have to just iterate the weights and brute force it?
Code with comments:
using Convex, ECOS Supertech = [-.2; .1; .3; .5]; Slowpoke = [.05; .2; -.12; .09]; A = reshape([Supertech; Slowpoke],4,2) mlen = size(A) R = vec(mean(A,1)) n=rank(A) w = Variable(n) c1 = sum(w) == 1; λ = .01 w.value = [λ; 1-λ] sharpe_ratio = sqrt(mlen) * (w.value' * R) / sqrt(sum(vec(w.value' .* w.value) .* vec(cov(A,1,false)))) # sharpe_ratio will be maximized at 1.80519 when w.value = [λ, 1-λ] where λ = .363 p = maximize(sharpe_ratio,c1); solve!(p, ECOSSolver(verbose = false)); # when verbose=true, says is 'degenerate' because I don't have enough constrains... println(w.value) # expecting to get [.363; .637] here but I get [0.5; 0.5]