Portfolio optimisation with Gurobi Optimizer version 10.0.1 build v10.0.1rc0 (win64)
AnsweredHello!
This is my first time using gurobi and I am trying to generate results for my masters thesis. I have structured the code so far using gurobi examples on portfolio.py and diet.py.
I have an excel file with a portfolio presented as the columns:asset names, emissions, liquidity, volatility and expected returns. The variables emissions, liquidity and volatility contain numbers representing each assets characteristic c02 emissions, liquidity and volatility. The portfolio liquidity and emissions are calculated by asset weight in portfolio multiplied by each variable. The portfolio volatility is calculated by considering the covariance matrix as shown in the code.
In the code attached below, I try and maximize expected returns. The first problem I run into is while not applying the volatility constraint, is the model not having any feasible solutions, although I am able to see one by manually changing weights in the excel file. The second issue comes along when I apply the volatility constraint and reads as " only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices"
model = gp.Model("portfolio_optimization")
weights = model.addVars(assets, lb=0, ub=0.05, name="weights")
# Objective
portfolio_returns = gp.quicksum(returns[i] * weights[i] for i in assets)
model.setObjective(portfolio_returns, gp.GRB.MAXIMIZE)
# Add constraints
#1: Emissions
portfolio_C02e = ftse['Emissions'] * ftse['Weight']
portfolio_C02e = portfolio_C02e.sum()
target_C02e = portfolio_C02e * 0.99
model.addConstr(gp.quicksum(emissions[i] * weights[i] for i in assets) <= target_C02e, "emissions_constraint")
# 2: Volatility
# covariance_matrix = np.cov(portfolioHistRet.fillna(0).T)
# target_volatility = 10
# portfolio_volatility = gp.quicksum(gp.quicksum(covariance_matrix[i, j] * weights[i] * weights[j] for i in assets) for j in assets)
# model.addConstr(portfolio_volatility <= target_volatility, "volatility_constraint")
# 3: Liquidity
portfolio_Liquidity = (ftse['Liquidity'] * ftse['Weight']).sum()
target_Liquidity = portfolio_Liquidity * 0.1
model.addConstr(gp.quicksum(liquidity[i] * weights[i] for i in assets) >= target_Liquidity, "liquidity_constraint")
#4: Total investable capital preference
model.addConstr(weights.sum() == 1, "budget_constraint")
#5: Constraint on the number of nonzero assets
# model.addConstr(np.count_nonzero(weights) >= 15, "min_investable_weights_constraint")
model.optimize()
Please let me know how I can improve this code or if there is anything obvious I am missing?
Thank you
0

Hi Manu,
The issue will be your nested quicksums. The quicksum expects a generator expression or iterable and returns a LinExpr object, so you are trying to sum linear expressions with the outer quicksum which won't work.
I suspect you mean to write
portfolio_volatility = gp.quicksum(covariance_matrix[i, j] * weights[i] * weights[j] for i in assets for j in assets)
 Riley
0
Please sign in to leave a comment.
Comments
1 comment