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 would like to compare sharpe ratio between my random weights and optimal weights #358

Closed Younghoon-Lee closed 2 years ago

Younghoon-Lee commented 3 years ago

What are you trying to do?

Like I said in the title, I want to compare sharpe ratio between my random weights and optimal weights.

What have you tried?

Here is my code for better explanation. (df is my 1-year stock price data frame )

mu = expected_returns.capm_return(df)
S = risk_models.CovarianceShrinkage(df).ledoit_wolf()
ef = EfficientFrontier(mu, S)
weights = ef.max_sharpe()

Then I changed weights to numpy array. Also I made random weights(_myweights), which is also numpy array.

optimalPortfolioReutrnsMean = np.dot(np.array(mu), weights)
myPortfolioReturnsMean = np.dot(np.array(mu), my_weights)

optimalPortfolioVolatility = np.sqrt(np.dot(weights.T, np.dot(S, weights)))
myPortfolioVolatility = np.sqrt(np.dot(my_weights.T, np.dot(S, my_weights)))

optimalPortfolioSharpeRatio = optimalPortfolioReturnsMean/optimalPortfolioVolatility
myPortfolioSharpeRatio = myPortfolioReturnsMean/myPortfolioVolatility

I assumed that risk-free rate is zero.

Theoretically, optimalPortfolioSharpeRatio has to outscore myPortfolioSharpeRatio (at least same). But I found some cases that myPortfolioSharpeRatio outscores optimalPortfolioSharpeRatio

Is there anything I am missing out?

phschiele commented 3 years ago

@Younghoon-Lee You are right, in theory, the weights returned by max_sharpe() should outperform any other weight vector within the same bounds. Note that the function uses risk_free_rate=0.02 as a default. Can you pass risk_free_rate=0.0 as an argument and repeat your analysis?

Younghoon-Lee commented 2 years ago

@phschiele Sorry for the late reply. You were right. I missed the part that max_sharpe() function uses risk_free_rate=0.02. After pass risk_free_rate=0.0, I got the same result. Appreciate !