robertmartin8 / PyPortfolioOpt

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

Random portfolios very bunched when following cookbook #576

Open cianryan09 opened 5 months ago

cianryan09 commented 5 months ago

I am following the cookbook guide to plot the efficient frontier and optimal portfolio and the random portfolios end up becoming very bunched.

rf = 0.054

mu = capm_return(df, df_BM, risk_free_rate=rf)
S = CovarianceShrinkage(df).ledoit_wolf()

# print(mu)
# print(S)

ef = EfficientFrontier(mu, S, )

fig, ax = plt.subplots()
ef_max_sharpe = ef.deepcopy()
plotting.plot_efficient_frontier(ef, ax=ax, show_assets=False)

# Find the tangency portfolio
ef_max_sharpe.max_sharpe()
ret_tangent, std_tangent, _ = ef_max_sharpe.portfolio_performance()
ax.scatter(std_tangent, ret_tangent, marker="*", s=100, c="r", label="Max Sharpe")

# Generate random portfolios
n_samples = 100
w = np.random.dirichlet(np.ones(ef.n_assets), n_samples)
rets = w.dot(ef.expected_returns)
stds = np.sqrt(np.diag(w @ ef.cov_matrix @ w.T))
sharpes = rets / stds
ax.scatter(stds, rets, marker=".", c=sharpes, cmap="viridis_r")

# Output
ax.set_title("Efficient Frontier with random portfolios")
ax.legend()
plt.tight_layout()
plt.savefig("ef_scatter.png", dpi=200)
plt.show()

My data is the constituents of the S&P500 up until YE 2023. here is how it turns out: EF

Basically the shape ratios end up very close together (0.69 - 0.71 range) so it doesn't really visually represent the whole exercise very well. Has anyone else had this issue?

Also I would suggest a potential edit for the ReadTheDocs - it doesn't specify which modules you have to import at the start, it would be useful for people less used to Python or coding in general to have these written in the example. I had to figure out that it was matplotlib.plt and plotting myself.

cianryan09 commented 5 months ago

I would also like to amend the axis ranges - the expected return of the optimised portfolio is at the bottom of the frontier, preferably it would be in the middle, currently everything gets bunched in the bottom right corner.

In addition, I would like to plot the tangency line from the risk free rate (5.4% in my case) to the max shapre portfolio. Is there a way of doing this?

baobach commented 5 months ago

Have you considered increasing the number of samples for your random portfolios? One hundred seems rather small. Typically, in the Monte Carlo simulation approach, starting with 100,000 samples is advisable. Hypothetically, the higher the number, the closer you get to your target weight allocation.