Looking to take a list of stocks and adjust their weight in a portfolio until the overall portfolio beta is 1.0 the output of "stonkBetas" is static and is:
[3.19292010501853,
0.7472001935364129,
1.0889157697158605,
0.8944059912707691,
0.04192080860817828,
1.0011520737327186,
0.9155119223385676]
I then create two functions. One to define how the betas are weighted. The second just as con that will make the constraint that the sum of the minimized weighted portfolio will have an overall summed beta of 1.0.
def betaOpp(weights):
a,b,c,d,e,f,g=weights
f=a*stonkBetas[0]+b*stonkBetas[1]+c*stonkBetas[2]+d*stonkBetas[3]+e*stonkBetas[4]+f*stonkBetas[5]+g*stonkBetas[6]
return f
initial_guess = [.1,.1,.1,.1,.2,.2,.2]
print('hi')
print(sum(initial_guess))
print('bye')
def con(t):
print('this should be zero:')
print(sum(t)-1)
return sum(t) - 1.0
cons = {'type':'eq', 'fun': con}
bnds = ((.02,.8),(.02,.8),(.02,.8),(.02,.8),(.02,.8),(.02,.8),(.02,.8))
res = optimize.minimize(betaOpp,initial_guess, bounds=bnds, constraints=cons)
print(res)
This gives me this output
hi
1.0
bye
this should be zero:
0.0
this should be zero:
0.0
this should be zero:
0.0
this should be zero:
1.4901161193847656e-08
this should be zero:
1.4901161193847656e-08
this should be zero:
1.4901161193847656e-08
this should be zero:
1.4901161193847656e-08
this should be zero:
1.4901161193847656e-08
this should be zero:
1.4901161193847656e-08
this should be zero:
1.4901161193847656e-08
this should be zero:
6.661338147750939e-16
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-30-6567109e94a4> in <module>
16 cons = {'type':'eq', 'fun': con}
17 bnds = ((.02,.8),(.02,.8),(.02,.8),(.02,.8),(.02,.8),(.02,.8),(.02,.8))
---> 18 res = optimize.minimize(betaOpp,x0=initial_guess, bounds=bnds, constraints=cons)
19 print(res)
/opt/miniconda3/lib/python3.6/site-packages/scipy/optimize/_minimize.py in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options)
624 elif meth == 'slsqp':
625 return _minimize_slsqp(fun, x0, args, jac, bounds,
--> 626 constraints, callback=callback, **options)
627 elif meth == 'trust-constr':
628 return _minimize_trustregion_constr(fun, x0, args, jac, hess, hessp,
/opt/miniconda3/lib/python3.6/site-packages/scipy/optimize/slsqp.py in _minimize_slsqp(func, x0, args, jac, bounds, constraints, maxiter, ftol, iprint, disp, eps, callback, finite_diff_rel_step, **unknown_options)
424
425 if mode == -1: # gradient evaluation required
--> 426 g = append(sf.grad(x), 0.0)
427 a = _eval_con_normals(x, cons, la, n, m, meq, mieq)
428
/opt/miniconda3/lib/python3.6/site-packages/scipy/optimize/_differentiable_functions.py in grad(self, x)
186 if not np.array_equal(x, self.x):
187 self._update_x_impl(x)
--> 188 self._update_grad()
189 return self.g
190
/opt/miniconda3/lib/python3.6/site-packages/scipy/optimize/_differentiable_functions.py in _update_grad(self)
169 def _update_grad(self):
170 if not self.g_updated:
--> 171 self._update_grad_impl()
172 self.g_updated = True
173
/opt/miniconda3/lib/python3.6/site-packages/scipy/optimize/_differentiable_functions.py in update_grad()
90 self.ngev += 1
91 self.g = approx_derivative(fun_wrapped, self.x, f0=self.f,
---> 92 **finite_diff_options)
93
94 self._update_grad_impl = update_grad
/opt/miniconda3/lib/python3.6/site-packages/scipy/optimize/_numdiff.py in approx_derivative(fun, x0, method, rel_step, abs_step, f0, bounds, sparsity, as_linear_operator, args, kwargs)
389
390 if np.any((x0 < lb) | (x0 > ub)):
--> 391 raise ValueError("`x0` violates bound constraints.")
392
393 if as_linear_operator:
ValueError: `x0` violates bound constraints.
And I just don't understand where I'm going wrong. The x0 is perfectly 1.0 - I can see it! Hopefully I'm just doing something stupid here. Please help!