How to Create a Monte Carlo Simulation using Python
Walkthrough an example to learn what a Monte Carlo simulation is and how it can be used to predict probabilities
What is a Monte Carlo Simulation?
A Monte Carlo simulation is a type of computational algorithm that estimates the probability of occurrence of an undeterminable event due to the involvement of random variables. The algorithm relies on repeated random sampling in an attempt to determine the probability. This means simulating an event with random inputs a large number of times to obtain your estimation. You can determine other factors as well, and we will see that in the example. Monte Carlo simulations can be utilized in a broad range of fields spanning from economics, gambling, engineering, energy, and anything in-between. So, no matter what career field you are in, it’s an excellent thing to know about.
When learning how to build Monte Carlo simulations, it’s best to start with a basic model to understand the fundamentals. The easiest and most common way to do that is with simple games, so we will make use of a dice game in this article. You’ve probably heard the saying, “the house always wins,” so for this example, the house (typically a casino) will have an advantage, and we will show what that means for the player’s possible earnings.
The Dice Game
Our simple game will involve two six-sided dice. In order to win, the player needs to roll the same number on both dice. A six-sided die has six possible outcomes (1, 2, 3, 4, 5, and 6). With two dice, there is now 36 possible outcomes (1 and 1, 1 and 2, 1 and 3, etc., or 6 x 6 = 36 possibilities). In this game, the house has more opportunities to win (30 outcomes vs. the player’s 6 outcomes), meaning the house has the quite the advantage.
Let’s say our player starts with a balance of $1,000 and is prepared to lose it all, so they bet $1 on every roll (meaning both dice are rolled) and decide to play 1,000 rolls. Because the house is so generous, they offer to payout 4 times the player’s bet when the player wins. For example, if the player wins the first roll, their balance increases by $4, and they end the round with a balance of $1,004. If they…
Использование метода Монте-Карло для создания портфеля
Начинающие (да и не только) инвесторы часто задаются вопросом о том, как отобрать для себя идеальное соотношение активов входящих в портфель. Часто (или не очень, но знаю про двух точно) у некоторых брокеров эту функцию выполняет торговый робот. Но заложенные в них алгоритмы не раскрываются.
- Портфель с минимальным уровнем риском при желаемой доходности;
- Портфель с максимальной доходностью при установленном риске;
- Портфель с максимальным значением доходности
#Загружаем библиотеки import pandas as pd import yfinance as yf import numpy as np import matplotlib.pyplot as plt # Получаем данные по акциям ticker = ['ATVI','BA','CNP','CMA', 'STZ','GPN','MPC','NEM', 'PKI'] stock = yf.download(ticker,'2017-01-01', '2019-01-31')
Если сложить долю всех акций, входящих в портфель, то сумма должна стремиться к единице (а лучше быть равна). Дальше как обычно проведем подготовку данных для расчетов:
# Выделение скорректированой цены закрытия all_adj_close = stock[['Adj Close']] # ежедневная доходность all_returns = all_adj_close.pct_change() # узнаем среднюю доходность и получаем ковариационную матрицу mean_returns = all_returns.mean() cov_matrix = all_returns.cov()
Теперь можно провести расчет для весов предложенных торговым роботом и узнать доходность данного портфеля за последник три года и стандартное отклонение.
#предложение по весам торгового робота robot = np.array([0.0441, 0.1030, 0.1086, 0.2070, 0.1525, 0.0714, 0.0647, 0.1828, 0.0661]) # доходность, стандартное отклонение и коэффициент Шарпо portfolio_return_robot = np.sum(mean_returns * robot) portfolio_std_dev_robot = np.sqrt(np.dot(robot.T,np.dot(cov_matrix, robot))) sharpo_robot = portfolio_return_robot/portfolio_std_dev_robot # объединим полученные значения в таблицу и выведем ее robot_result = np.array([portfolio_return_robot, portfolio_std_dev_robot, sharpo_robot]) robot_result = np.array([portfolio_return_robot, portfolio_std_dev_robot, sharpo_robot]) robot_result = np.concatenate((robot_result, robot), axis=0) robot_sim_result = pd.DataFrame(robot_result, columns=['Robot'], index=['ret','stdev','sharpe',ticker[0],ticker[1],ticker[2],ticker[3],ticker[4],ticker[5],ticker[6],ticker[7],ticker[8]]) print(robot_sim_result)
Симуляция Монте-Карло
Первоначально небольшое вступительное слово о том, как используется метод Монте-Карла для оптимизации портфеля
Сначала акциям задаются случайные веса, после чего производится расчет доходности и стандартного отклонения. Полученные значения сохраняются. Следующим шагом случайным образом меняются веса (главное не забывать, что их сумма должна составлять единицу) и все повторяется — расчет и сохранение полученного значения. Количество итераций зависит от времени, мощностей компьютера для расчета и рисков, который готов принять инвестор. В этот раз попробуем провести 10000 расчетов для выявления портфеля с минимальным убытком и максимальным значением коэффициента Шарпа.
#создаем массив из нулей num_iterations = 10000 simulation_res = np.zeros((4+len(ticker)-1,num_iterations)) # сама итерация for i in range(num_iterations): #Выбрать случайные веса и нормализовать, чтоб сумма равнялась 1 weights = np.array(np.random.random(9)) weights /= np.sum(weights) #Вычислить доходность и стандартное отклонение portfolio_return = np.sum(mean_returns * weights) portfolio_std_dev = np.sqrt(np.dot(weights.T,np.dot(cov_matrix, weights))) #Сохранить все полученные значения в массив simulation_res[0,i] = portfolio_return simulation_res[1,i] = portfolio_std_dev #Вычислить коэффициент Шарпа и сохранить simulation_res[2,i] = simulation_res[0,i] / simulation_res[1,i] #Сохранить веса for j in range(len(weights)): simulation_res[j+3,i] = weights[j] # сохраняем полученный массив в DataFrame для построения данных и анализа. sim_frame = pd.DataFrame(simulation_res.T,columns=['ret','stdev','sharpe',ticker[0],ticker[1],ticker[2],ticker[3],ticker[4],ticker[5],ticker[6],ticker[7],ticker[8]])
Теперь можно рассчитать портфель с максимальным коэффициентом Шарпа или минимальным риска.
# узнать максимальный Sharpe Ratio max_sharpe = sim_frame.iloc[sim_frame['sharpe'].idxmax()] # узнать минимальное стандартное отклонение min_std = sim_frame.iloc[sim_frame['stdev'].idxmin()] print ("The portfolio for max Sharpe Ratio:\n", max_sharpe) print ("The portfolio for min risk:\n", min_std)
Ну а самое важное представление можно получить, когда данные визуализируешь:
fig, ax = plt.subplots(figsize=(10, 10)) #Создать разноцветный график scatter plot для различных значений коэффициента Шарпо по оси x и стандартного отклонения по оси y plt.scatter(sim_frame.stdev,sim_frame.ret,c=sim_frame.sharpe,cmap='RdYlBu') plt.xlabel('Standard Deviation') plt.ylabel('Returns') plt.ylim(0,.0015) plt.xlim(0.007,0.012) plt.scatter(max_sharpe[1],max_sharpe[0],marker=(5,1,0),color='r',s=600) plt.scatter(min_std[1],min_std[0],marker=(5,1,0),color='b',s=600) plt.scatter(portfolio_std_dev_robot, portfolio_return_robot,marker=(5,1,0),color='g',s=600) plt.show()
Портфель с максимальным коэффициентом Шарпа показан красной звездой, синей — с минимальным стандартным отклонением и зеленой — предложенный роботом. Как видно — портфель, предложенный роботом, не совпадает с этими показателями, но на каком остановиться портфеле — выбор остается за инвестором. А я постараюсь в конце года вернуться к сравнению портфелей. А сейчас все три портфеля находятся в просадке.