Daniel Magal
Daniel Magal

Reputation: 65

Can SciPy minimize with SLSQP work with multiple non-linear constraints?

I'm trying to find an optimal solution under constraints and use SciPy minimize with SLSQP. It works perfectly with no problem with a single constraint. Once I add another constraint, it finishes successfully, but without meeting optimization goals.

I assumed that my problem is with the constraint function definition (constraint 2 is a bit tricky), and decided to learn how to use minimize properly.

I switched to a simple second constraint but got an unoptimized solution again.

The function that is going to be optimized: samples_in_year = 246.5

def get_portfolio_ann_risk(weights, assets_returns_daily, samples_in_year):
   samples_in_data = len(assets_returns_daily)
   cov_matrix = np.cov(assets_returns_daily, rowvar=False, ddof=0)
   weights = np.array([weights])
   weights_mat = np.dot(weights.T, weights)
   daily_var = np.sum(weights_mat * cov_matrix) * (samples_in_data /(samples_in_data - 1))
   daily_risk = np.sqrt(daily_var)
   return daily_risk * np.sqrt(samples_in_year)

The function optimization inputs:

minimal_risk_optimization_data = (assets_returns_daily, samples_in_year)
asset_weight_max = 1
asset_weight_min = 0

bounds = ((asset_weight_min, asset_weight_max),) * asset_count

The constraints:

two_constrain_opt_cons = (
   {'type': 'eq', 'fun': lambda weights: 0.5 - np.max(weights)},
   {'type': 'eq', 'fun': lambda weights: 1.0 - np.sum(weights)}
                        )

The optimization function

two_constrain_opt = minimize(get_portfolio_ann_risk, market_weights, method='SLSQP',
   args=minimal_risk_optimization_data,
   constraints=two_constrain_opt_cons,
   bounds=bounds,
   options={'maxiter': 250, 'ftol': 1e-09}
                            )

With each one of those constraints separately, it works fine, I can not make it work with both of them. I believe that if I'll be able to resolve the "simpler" problem I'll be able to optimize the real problem.

The results for each constrained optimization were correct, the result for the two constraints problem was the default used weight (initial guess)

Upvotes: 2

Views: 2388

Answers (1)

Daniel Magal
Daniel Magal

Reputation: 65

Resolved: Apparently, the problem was in the initial guess. It met the:

{'type': 'eq', 'fun': lambda weights: 1.0 - np.sum(weights)}

Constraint.

I changed the initial guess to not meet the constraint (multiplied it by 0.85), and it works like a charm.

Solution:

two_constrain_opt = minimize(get_portfolio_ann_risk, market_weights * 0.85, method='SLSQP',
   args=minimal_risk_optimization_data,
   constraints=con,
   bounds=bounds,
   options={'maxiter': 250, 'ftol': 1e-09}
                            )

Upvotes: 2

Related Questions