When testing the code in video tutorial "Eikon Data API - Python Quants Tutorial 6 - Portfolio Theory", I found it's hard to have minimized volatility by the sample code demonstrated in the video.
The average weight as initial guess will always be the optimization result. If a portfolio consists 5 stocks, the optimized weighting would be [0.2,0.2,0.2,0.2,0.2]. Is there anything missed by me or in the video?
@Yufeng.Ling FYI I have just written a Jupyter notebook that goes through different portfolio optimisation methods using a recent library called mlfinlab. You can download the source from our github repo here. I hope this can help.
Hi @Yufeng.Ling thanks for your question. The initial guess is given by an equal weighted portfolio - in our case of 5 instruments. So in terms of the minimize function in our example:
minimize(fun, x0, bounds=None, constraints=()) where:
fun is the function to be minimized (lambda x: portfolio_volatility(rics, x))
x0 is the initial guess (len(rics) * [1 / len(rics)]) : with a 5 instrument array this gives us our equal weighted portfolio as below:
bounds is our boundary condition that each weighting be between 0 and 1 (len(rics) * [(0, 1)] - this gives us a five element array of min,max.
constraints is our condition that all weights must sum to 1 or our single equality constraint.
Now in our example after the minimize function we have a new set of weights.
fun: 0.05627559333731446 jac: array([0.06615351, 0.05769502, 0.05610596, 0.05649973, 0.05631664]) message: 'Optimization terminated successfully.' nfev: 70 nit: 10 njev: 10 status: 0 success: True x: array([8.53371115e-18, 0.00000000e+00, 3.66747487e-01, 1.97838465e-01, 4.35414048e-01])
If we have a look at the output from the minimize function we can see that:
x: is the solution of the optimization - in our case the first two terms are near zero - so we only have weights for the last 3 instruments.
fun: is the value of the objective function and
jac: its jacobian
nfev: is the number of function evaluations
nit: is the number of iterations
If I look at the output from your minimize function I can see that your jac: is a zero vector (which doesn't seem correct), also the nfev: is 7 versus 70 in our example and nit: is 1 in yours and 10 in our example. And this is for a similar 5 instrument portfolio.
So whilst I cannot see the code prior to the result output you posted. It seems that what is being handed to the minimize function is in someway not correct. This points to errors up above in the code. You can test the values of the inputs at any point against our example and try to debug there. I would look at evaluating the initial guess to see if an equal weighted array is returned. Or perhaps there is an error in the Portfolio_Volatility function. I hope this has provided a slightly clearer explanation for you.
Thanks for helping me on the issue. I tried to replicate the result after minimization but in vain. The sco.minimize() function always return initial guess as result. Please have my complete code as pasted below. Anything I'm wrong with?
Also pasted with version of each package below:
By adding parameter "method='SLSQP' , jac='rosen_der'" in sco.minimize(), it start to work to solve the minimal value optimization. But the result could vary a lot depending on initial guess.
Wonder if the scipy.optimize() is suitable to determine portfolio's minimal volatility. Appreciate if you can instruct on how to adjust the parameter or shall we use other Python package to solve the problem.