robertmartin8 / PyPortfolioOpt

Financial portfolio optimisation in python, including classical efficient frontier, Black-Litterman, Hierarchical Risk Parity
https://pyportfolioopt.readthedocs.io/
MIT License
4.38k stars 940 forks source link

I am not sure that I am using right models #351

Closed Younghoon-Lee closed 3 years ago

Younghoon-Lee commented 3 years ago

What are you trying to do? I am trying to optimize my portfolio Based on my own Investment Universe, which has 20 ETF in it. First, I made a combination sets of assets in my Universe(portfolio size is 5, which is decided in advance). Then I applied mean-Variance Optimization to each combination set(based on ETF NAV prices). Finally, compare all combination sets and finds the one has best sharpe ratio.

What have you tried? Here's the code for better explanation. df is ETF NAV price DataFrame which contains all assets in each combination set.

return_matrix = expected_returns.mean_historical_return(df)
risk_model = risk_models.CovarianceShrinkage(df).ledoit_wolf()
ef = EfficientFrontier(return_matrix, risk_model, weight_bounds=(0,0.5))
ef.add_objective(objective_functions.L2_reg, gamma=1)
weights = ef.efficient_return(0.2) 
weights = ef.clean_weights()

I am quite not sure that I am using right return matrix, risk model and efficient frontier model. I used Ledoit Wolf shrinkage for risk model because you recommend it for most use cases on the document. (Normally, I used covariance model for risk model) Is it okay to use efficient frontier model(mean-variance optimization) with Ledoit Wolf shrinkage model?

Please advise me it there's any applicable improvement in my case.

robertmartin8 commented 3 years ago

Hi @Younghoon-Lee,

(this is not investment advice etc).

My main criticism is with the use mean_historical_return. It's worth thinking carefully about whether you think that the average of historical returns is a good predictor of future returns. An alternative would be capm_returns, which I think has a little more theoretical justification.

Ledoit Wolf shrinkage is a sensible default option. In practice, I have found that exp_cov works well.

I'm not sure about your approach to constructing sets of 5. The problem here is that there are 20C5 = 15504 combinations. Alternatively, you could loop through different values of gamma to see which has exactly 5 nonzero assets. Or you can try a cardinality constraint, but this may not play nicely with a max_sharpe objective.

Best, Robert

Younghoon-Lee commented 3 years ago

Thanks for you rapid reply.

I applied combination method to look through every possible combination set(and choose the portfolio that has the highest sharpe ratio) . I know it takes quite a time to loop through 15504 combinations but I thought it would be the most accurate method. Honestly I don't get your advice to loop through different values of gamma to see 5 nonzero assets portfolio. Do you mean I should change values of gamma in L2 regularisation to see which portfolio has 5 nonzero assets?

Appreciate your advice once again :)

Younghoon-Lee commented 3 years ago

And I am getting warning message after I changed return matrix from mean_historical_return to capm_return

UserWarning: Solution may be inaccurate. Try another solver, adjusting the solver settings, or solve with verbose=True for more information.

robertmartin8 commented 3 years ago

@Younghoon-Lee

Do you mean I should change values of gamma in L2 regularisation to see which portfolio has 5 nonzero assets?

Yup!

And I am getting warning message after I changed return matrix

Can you post the expected returns vectors for mean_historical_return and capm_return? Feel free to remove the tickers if you'd prefer to keep them private.

Best, Robert

robertmartin8 commented 3 years ago

Closing due to inactivity. The code you provided should work – I don't think I've encountered a situation where swapping from one well-formed expected returns vector to another causes issues.

Younghoon-Lee commented 3 years ago

Sorry for late reply.

Here is the return vectors of mean_historical_return and capm_return

//CAPM 
219390    0.981933
314250    0.561641
150460    0.221039
192090    0.336597
195930    0.350724
219480    0.405802
298770    0.240219
309230    0.408460
354350    0.451097
245710    0.211569
238720    0.247388
283580    0.329715
182480    0.396027
280930    0.593878
329750    0.013996
292560   -0.000116
305080   -0.001563
302190    0.016196
329650    0.126725
261240    0.013860
//Mean historical return
219390    0.911987
314250    0.697636
150460    0.401910
192090    0.106899
195930    0.257583
219480    0.404235
298770    0.539913
309230    0.363905
354350    0.613074
245710    0.849652
238720    0.267026
283580    0.130460
182480    0.308363
280930    0.614865
329750   -0.055557
292560   -0.088310
305080   -0.089527
302190   -0.032771
329650    0.074050
261240   -0.051657

However, due to my combination method, it is hard to tell which one of my combination sets is causing resolver problem. I applied your advice to change values of gamma, but it never showed me portfolio that has only 5 nonzero weights.

Thank you