Optimal Portfolio with multiple constraints on weights allocation - Mixed-integer quadratic program using Python CVXPY

Viewed 34

I'm trying to solve the classical Markowitz optimal portfolio problem, but adding multiple constraints on the weights allocation:

  1. Each asset should have a weight on the interval [0,10%] (long-only strategy);
  2. The vector of weights vector should sum 100%;
  3. For the assets whose weight is greater than 5%, the aggregate sum should not be greater than 40%.

This problem can be classified as a Mixed-Integer quadratic program. To solve it, I'm using CVXPY library from Python. The code that I have developed is structured as follows:

  1. Two continuous-variable vectors w and w_5, which represent the weights vector for assets whose weight is w <= 5% and w_5 > 5% respectively.
  2. Two boolean-variable vector d and d_5, to indicate if an asset is in the w vector or in the w_5 vector.
  3. In addition, the corresponding variables to solve the classic mean-variance optimization problem (this works without problem if I do not introduce constraint #3)

The code looks like this:

# Expected annualized yield
mu = np.mean(df_yield, axis = 0).values
    
# Annualized covariance matrix
sigma = df_yield.cov().values
    
# Number of assets
n = sigma.shape[0]

# Efficient Frontier (Mean-Covariance Optimization) - Parameters
w = cp.Variable(n)
w_5 = cp.Variable(n)
d = cp.Variable(n, boolean = True)
d_5 = cp.Variable(n, boolean = True)
gamma = cp.Parameter(nonneg = True)
ret = mu.T @ w
risk = cp.quad_form(w, sigma)

# Markowitz Efficient Frontier (Mean-Covariance Optimization) - Constraints
eps = 10e-10
constraints = [
   # Assets with weight <= 5%
   w <= 0.05 * d,
   w >= 0,
   # Assets with weight > 5%
   w_5 <= 0.10 * d_5,
   w_5 >= (0.05 + eps) * d_5,
   # Total sum thresholds
   cp.sum(w) + cp.sum(w_5) == 1,
   cp.sum(d) + cp.sum(d_5) == n,
   cp.sum(w) >= 0.4,
   cp.sum(w_5) <= 0.4,]

# Markowitz Efficient Frontier (Mean-Covariance Optimization) - Problem
prob = cp.Problem(cp.Maximize(ret - gamma * risk), constraints)
    
# Markowitz Efficient Frontier (Mean-Covariance Optimization) - Simulation
risk_data = np.zeros(n_samples)
ret_data = np.zeros(n_samples)
gamma_vals = np.logspace(gamma_low, gamma_high, num = n_samples)
portfolio_weights = []
for i in range(n_samples):
    gamma.value = gamma_vals[i]
    prob.solve()
    risk_data[i] = np.sqrt(risk.value)
    ret_data[i] = ret.value
    portfolio_weights.append(w.value)

# Maximum Sharpe Ratio
sharpes = ret_data / risk_data

The resulting output is:

SolverError: Either candidate conic solvers (['GLPK_MI']) do not support the cones output by the problem (SOC, NonNeg, Zero), or there are not enough constraints in the problem.

From this I can infer that I'm missing some additional constraint, but not idea how to solve it. Any guess?

0 Answers
Related