Flip A Coin

Download as pdf or txt
Download as pdf or txt
You are on page 1of 10

Open in app Get unlimited access

Luís Fernando Torres


Mar 31 · 7 min read · Listen

Save

Flip a Coin — A Monte Carlo Simulation 🪙

Introduction
Have you ever been to Monaco?

The Monte Carlo method is a computational technique that was developed back in
the 1940s in the midsts of the Manhattan Project. It is widely used to model and
analyze different outcomes in situations where there’s a significant degree of
randomness and uncertainty involved.

The Monte Carlo simulation works by running many random trials that are then
used to estimate the probability of different outcomes. It receives its name from
one of the most luxurious and fancy gambling destinations in the world, the Casino
de Monte-Carlo, located in one of the most expensive districts of Monaco. The
casino is famous for the variety of games it features, such as the roulette, dice, and
slot machines, all of which involve elements of chance and unpredictable
outcomes.
In the book “Fooled by Randomness: The Hidden Role of Chance in Life and in the
Markets”, author Nicholas Taleb argues that much of what is generally perceived as
expertise and competence in financial markets is actually nothing but the result of
pure luck. Inspired by this idea, I decided to perform a Monte Carlo simulation to
measure the probability of a trader to have success trading the S&P500 index based
solely on the toss of a coin. The full notebook, on Kaggle, you can see here.

Installing and Importing Libraries


The first thing we must do to run this simulation is to install the yfinance library,
that allow us to extract financial data in Python.

# Installing yfinance
!pip install yfinance

Then, we import all necessary libraries.

# Importing Libraries

import pandas as pd
import numpy as np
from datetime import datetime
import yfinance as yf
import random
import plotly.graph_objects as go
import seaborn as sns
import matplotlib.pyplot as plt
import sys

import warnings
warnings.filterwarnings('ignore')

Loading and Treating the Data


For this experiment, I decided to use the daily returns data of the S&P500 index for
the last five years, starting on January 2ⁿᵈ, 2018 and ending on December 30ᵗʰ,
2022. We use the “^GSPC” symbol to retrieve the data from Yahoo Finance using
yfinance.
# Loading data for the SP500 Index
spy = yf.download('^GSPC',
start = '2018-01-01',
end = '2023-01-01')
spy

[*********************100%***********************] 1 of 1 completed

To get daily returns data, we must use Panda’s pct_change( ) method to compute
the daily changes of the adjusted closing prices, and add a new column to the
dataframe called returns.

# Computing daily returns


spy['returns'] = spy['Adj Close'].pct_change()

Starting the Simulation


Now we must define the number of simulations to run, which in this case will be
10,000. I’m also going to include an additional cost of 0.1% for each trade.
The coins NumPy array will be created to have the same number of rows as the spy
dataframe and the same number of columns as the number of simulations. It will
consist of randomly generated integers between 0 and 1.

number_of_simulations = 10000 # 10,000 simulations


trading_costs = 0.001 # 0.1% of cost per trade

# Creating coins numpy array


coins = np.random.randint(0, 2,
size = (len(spy), number_of_simulations))
# Displaying coins numpy array
coins

array([[1, 0, 1, ..., 0, 0, 0],


[0, 0, 0, ..., 0, 0, 1],
[0, 1, 1, ..., 0, 1, 1],
...,
[0, 0, 1, ..., 0, 0, 0],
[0, 1, 0, ..., 0, 0, 0],
[1, 1, 0, ..., 1, 1, 0]])

To make it more intuitive, in the next code cell, I’ve used NumPy’s where( ) method
to replace 0 values for -1. This is going to make it easier to compute the returns for
each simulation trading by simply multiplying the values in the coins NumPy array
by the daily returns of the S&P500.

So, for instance, if you sell (-1) and the next daily return is a negative number, your
returns will represent a winning trade (-1 * -x = +x). If you buy and the next daily
return is a negative number, you’ll have losses (1 * -x = -x).

# Where value in coins is equal to 0, replace 0 by -1


coins = np.where(coins == 0, -1, 1)
coins

array([[ 1, -1, 1, ..., -1, -1, -1],


[-1, -1, -1, ..., -1, -1, 1],
[-1, 1, 1, ..., -1, 1, 1],
...,
[-1, -1, 1, ..., -1, -1, -1],
[-1, 1, -1, ..., -1, -1, -1],
[ 1, 1, -1, ..., 1, 1, -1]])

Right in the code below, you can see the logic behind the simulation. I am going to
select the first column of the coins NumPy array and multiply its values by the
daily returns in the spy dataframe. Then, we subtract the trading costs per trade
and, finally, apply the cumulative sum of each trade during the period to find the
final result.

# Applying the simulation on the first column in 'coins'


simulation = pd.DataFrame(coins[:,0] * spy['returns'] - trading_costs).cumsum(

This results in the following output:

After doing that, by December 30ᵗʰ, 2022, we will have the final result of the whole
period in the last row of the dataframe.
The same logic is now going to be applied to all the other 9,999 simulations by
iterating over each column in the coins NumPy array and concatenating the results
with the dataframe above.

for i in range(1, number_of_simulations):


simulation = pd.concat([simulation, pd.DataFrame(coins[:,i] * spy['returns

This gives us a new dataframe with 1,259 rows and 10,000 columns, where each
column represents a single simulation, which in this case, we can refer to them as
“trading accounts”.

We can use Plotly to visualize the distribution of the total returns of the
simulations.

# Plotting Histogram of Total Returns


fig = go.Figure(data=[go.Histogram(x = simulation.iloc[-1] * 100)])

fig.update_layout(title_text = 'Flip a Coin - Distribution of Total Returns',


xaxis_title = 'Total Returns',
yaxis_title = 'Frequency')

fig.show()
The large majority of the total returns are negative, with just a few accounts on the
realm of positive returns.

By using NumPy’s where( ) method, we can replace every single value lower than -1
by -1, which represents the loss of the total value in the trading account at -100%.
By multiplying the returns by 100, we have the values in percentage.

for col in simulation.columns:


simulation[col] = np.where(simulation[col] < -1, -1, simulation[col]) # Re

simulation = simulation * 100 # Obtaining values in percentage

Finally, we can plot the cumulative returns over time for all 10,000 trading accounts
and print some final statistics on our data.
# Plotting Cumulative Returns over time for each simulation
plt.figure(figsize = (15,15))
plt.plot(simulation, linewidth = 1.5)
plt.xlabel('Date')
plt.ylabel('Total Returns (%)')
plt.title('Trading the S&P500 Based on the Flip of a Coin - 10,000 Simulations
plt.style.context('seaborn-deep')
plt.show()
# Printing statistics
print(f'\nAverage Total Return: {simulation.iloc[-1].mean().round(2)}%')
print(f'\nMaximum Total Return: {simulation.iloc[-1].max().round(2)}%')
print(f'\nMedian of Total Returns: {simulation.iloc[-1].median().round(2)}%')
print(f'\nUpper Quartile of Total Returns: {np.percentile(simulation.iloc[-1],
print(f'\n95th Percentile of Total Returns: {np.percentile(simulation.iloc[-1]

Average Total Return: -90.45%

Maximum Total Return: 96.29%

Median of Total Returns: -100.0%

Upper Quartile of Total Returns: -92.67%

95th Percentile of Total Returns: -44.3%

Conclusion
Overall, the average return over the past five years was -90.45%. Half of our
“traders” would have blown their account during this period.

75% of accounts would have lost at least 92.67% of their trading capital and.
Looking at the 95th percentile of returns, it’s safe to say that you would’ve had a 5%
chance of achieving returns higher than -44.3% by trading the S&P500 based solely
on the flip of a coin.

However, there are always those who are lucky!

As shown in the plot above, there is one pink line that goes up while all the other
go down. This line represents a single simulated account that have accumulated
96.29% of profits by trading the S&P5000 through coin tosses, already accounting
for the additional trading costs. This could be that “day-trader for a living” you’ve
heard of, or the seemingly successful guru selling books or courses online on how
to get rich trading futures.

At the end of the day, if you’re lucky enough, a simple game of heads or tails can
make you money in the market. But just as long as your luck doesn’t run out.
Thank you for reading,

Luís Fernando Torres

LinkedIn

Kaggle

Monte Carlo Simulation Quantitative Finance Python Data Science

Data Visualization

You might also like