Reputation: 65
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
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