As mentioned in the introduction, we continued the example from the previous two recipes. That is why we had to run Step 1 to 4 from the Finding the Efficient Frontier using Monte Carlo simulations recipe (not shown here for brevity) to have all the required data. As an extra step, we had to import the cvxpy convex optimization library. We additionally converted the historical average returns and the covariance matrix into numpy arrays.
In Step 5, we set up the optimization problem. We started by defining the target variables (weights), the risk-aversion parameter gamma, the portfolio returns and volatility (both using the previously defined weights variable), and lastly, the objective function—the risk-adjusted returns we want to maximize. Then, we created the cp.Problem object, and passed the objective function and a list of constraints as arguments.
In Step 6, we found the Efficient Frontier by solving the convex optimization problem for multiple values of the risk-aversion parameter. To define the values, we used the np.logspace function to get 25 values of γ. For each value of the parameter, we found the optimal solution by running problem.solve(). We stored the values of interest in dedicated arrays or lists.
In Step 7, we plotted the asset allocation per various levels of risk aversion. In the plot, we could see that for very small values of γ, the investor would allocate 100% of their resources to Twitter. As we increased the risk aversion, the allocation to Twitter grew smaller, and more weight was allocated to Microsoft and the other assets. At the other end of the considered values for the parameter, the investor would allocate 0% to Twitter.
In Step 8, we plotted the Efficient Frontier, together with the individual assets.