Portfolio balancing is a complex optimization problem. The problem can be stated as assignment of weights to different stocks in the portfolio so that a metric called Sharpe Ratio is maximized. In this post we will see how Monte Carlo simulation provides a simple solution. The approach is brute force, because with simulation we will be doing random search through the solution space. The Monte Carlo simulation module is part of my Python package matumizi. Here is the GitHub repo. The main focus of matumizi is a Exploratory Data Analysis(EDA) module with over 100 functions
Portfolio Balancing
The goal of balancing is to find a set of optimum weights for stocks in the portfolio. The weights represent the holding of different stocks. Depending on the difference in new weights and current weights, some stocks will be sold and some will be bought. For any given stock, the difference in weight determines the the number of stocks to buy or sell. The optimization criteria is Sharpe Ratio, which is the ratio of stock return and variability of return. The variability is the std deviation of the daily return with respect a base price in some time window. The goal is to choose weights such that Sharpe Ratio is maximized. We will be using Sharpe Ratio for the whole portfolio and the formulation is different.
There is another metric called Sortino Ratio, which is similar to Sharpe Ratio. In Sortino Ratio, only downward price movement is used in the standard deviation calculation.
Monte Carlo Simulation
In Monte Carlo simulation repeated sampling is dome from some specified distributions to perform some computation. For example, we may want to find the expected value of some variable which is a complex functions of several other independent variables with known probability distribution. Analytical solution may be completely intractable. However, you can repeatedly sample the independent variables, compute the dependent variables. After many samples of the dependent variable have been generated, you can take the empirical mean.
We are using Monte Carlo(MC) simulation to generates samples of stock weights based specified weight probability distributions distributions. For weights, uniform distribution is used. For each set of samples weights, we calculate the Sharpe Ratio and keep track of the maximum Sharp Ratio and the corresponding stock weights.
Following samplers are supported by the MC simulator
- Bernoulli
- Poisson
- Uniform
- Triangular
- Normal
- Multi Variate Normal
- Log Normal
- Pareto
- Gamma
- Non Parametric Discrete
- Non Parametric Continuous
- Joint Non Parametric Continuous
- Permutation
- Normal with Trend and Cycle
- Custom
- Discrete Event
- Metropolitan
Solution
The solution presented here is inspired by this article on a stock trading platform based on Machine Learning. To calculate Sharpe Ratio for a whole portfolio we take weighted average of all stocks and weighted average of the stock return covariance as described in the article. The driver code is available in GitHub. Historical stock data for the past 6 months was downloaded from this site. The solution proceeds as follows. The portfolio in this example contains 12 stocks. I have used uniform distribution sampler for all weights. With domain knowledge, some other more appropriate distribution could be used.
1.Predict next day's price for all 12 stocks. I have used exponential smoothing for forecast. it could be replaced with any other forecasting algorithm
2.Calculate return for stocks based on base price 6 months ago
3.Calculate stock proce covariance for the last 6 months
4.Set up MC simulator, using uniform sampler for all 12 weights and providing the num of iterations.Run the simulator. The simulator calls a call back lambda as many time as the num of iterations.
5.In the call back lambda, calculate weighted average return, weighted average covariance and Sharpe Ratio.
Please follow the steps in the tutorial to execute the use case. Here is some sample output. In buy sell recommendations, positive value for number of stocks indicate buy recommendation and negative for sell.
best score 8.282 weights [0.030221735374103685, 0.1318783128268495, 0.007027362043826996, 0.17403360480470265, 0.06380919800738079, 0.004743587596594035, 0.06016697349404936, 0.011843039766740514, 0.19879720793646874, 0.045250278506313205, 0.06758349489504005, 0.20464520474793038] buy and sell recommendations ('WMT', -114) ('PFE', 466) ('NFLX', -205) ('AMD', 233) ('TSLA', -45) ('AMZN', -59) ('META', -55) ('QCOM', -68) ('CSCO', 968) ('MSFT', -19) ('SBUX', 48) ('AAPL', 237)
Wrapping Up
The solution presented is a simple brute force approach. It performs random search. Instead we can make the search more intelligent using heuristic optimization techniques like Evolutionary Algorithm. The solution could also include set of new stocks to be considered along with the existing portfolio stocks. That will be a topic of a future post.