Math for Devs - Gambler's fallacy and Monte Carlo Simulation
Tags: math, python, tutorial
Published: 2024-01-20 19:14:11

## Understanding the Gambler's Fallacy

The Gambler's Fallacy, often referred to as the Monte Carlo Fallacy, is a common misconception related to probability and independent events. It's the erroneous belief that if an event occurs more frequently than normal over a certain period, it's less likely to happen in the future. Despite its prevalence, this line of thinking is fundamentally flawed.

## Everyday Examples of the Gambler's Fallacy

Let's delve into some everyday instances where the Gambler's Fallacy might surface:

1. **Sports**: How often have we thought, "This team hasn't won in their last 10 matches; they can't keep losing forever. They're due for a win soon, maybe in the next game"?

2. **Casinos**: This is a classic example, and we'll explore it more in-depth later in this article.

3. **Lottery Numbers**: "I'm picking number 23 for sure. It hasn't come up in the last 30 weeks, so it must be due soon, right?" 

## The Historical Context

The Gambler's Fallacy is a fascinating phenomenon that finds its roots in the world of gambling, a domain where luck and chance reign supreme. This fallacy, also known as the "Monte Carlo Fallacy," is named after a notorious event that occurred at the Monte Carlo Casino in 1913. On this day, the roulette wheel landed on black 26 times in a row, an incredibly rare event. Gamblers lost millions betting against blacks, believing that red was due to occur next. This belief stems from the Gambler's Fallacy, the mistaken idea that past random events can influence future ones in a purely random process.

![Monte Carlo Casino](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hqkqqyi5j55y7a8zf588.png)

**The probability of a sequence of either red or black occurring 26 times in a row is around 1 in 66.6 million**. So the gamblers kept thinking "somehow the blacks gotta stop", and it took 26 times to stop, until then, they lost lots of money, and the casino became even richer.

## But why is this a fallacy?

The core of the Gambler's Fallacy lies in the misunderstanding of independence in probability. Take coin tosses, for example. If you flip a coin and get tails three times in a row, you might think heads is "due" next. However, the probability remains 50/50. The coin doesn't remember its past flips; each toss is independent, and the universe doesn't conspire to balance the outcomes. It's all random, with each flip having an equal chance of being heads or tails.

## Demonstrating the Fallacy with Python

To illustrate the Gambler's Fallacy, let's simulate a roulette wheel using Python. This code will show how the outcomes of each spin are independent of each other:

```python
import random

def roulette_spin():
    return 'black' if random.randint(0, 1) == 0 else 'red'

def simulate_spins(num_spins):
    results = {'black': 0, 'red': 0}
    for _ in range(num_spins):
        result = roulette_spin()
        results[result] += 1
    return results

# Simulate 100 spins
spin_results = simulate_spins(100)
print(f"After 1000 spins: {spin_results}")
```

## Monte Carlo Simulation

The Gambler's Fallacy and that memorable event at the Monte Carlo Casino actually led to something pretty cool – the **Monte Carlo Simulation**. Invented in the 1940s by John von Neumann and Stanislaw Ulam, this method is all about running a bunch of simulations, or iterations, of an event we want to predict. These simulations are key for bringing in randomness and getting rid of outliers. Let's dive into this with the same example of coin tosses, and see how it plays out in a Monte Carlo Simulation:

```python
import random

def roulette_spin():
    return 'black' if random.randint(0, 1) == 0 else 'red'

def simulate_spins(num_spins):
    results = {'black': 0, 'red': 0}
    for _ in range(num_spins):
        result = roulette_spin()
        results[result] += 1
    return results

num_of_simulations = int(input("How many simulations do you want to run? "))
spin_results = simulate_spins(num_of_simulations)
print(f"After {num_of_simulations} spins: BLACK: {spin_results['black']/num_of_simulations*100}% RED: {spin_results['red']/num_of_simulations*100}%")
```

The code was adapted to run multiple simulations, to reduce the outliers and get a closer result to the **real probabilities**. That's what Monte Carlo Simulation is about: getting the **real probabilities** of an event by running it many times.

**OBS: NOTICE THAT THE BIGGER THE NUMBER OF SIMULATIONS, MORE ACCURATE IS THE RESULT.**

### 5 coin flips

```
How many simulations do you want to run? 5
After 5 spins: BLACK: 0.0% RED: 100.0%
```

### 10 coin flips

```
How many simulations do you want to run? 10
After 10 spins: BLACK: 70.0% RED: 30.0%
```

### 100 coin flips

```
How many simulations do you want to run? 100
After 100 spins: BLACK: 61.0% RED: 39.0%
```

### 1000 coin flips

```
How many simulations do you want to run? 1000
After 1000 spins: BLACK: 48.3% RED: 51.7%
```

### 10000 coin flips

```
How many simulations do you want to run? 10000
After 10000 spins: BLACK: 49.53% RED: 50.470000000000006%
```

### 100000 coin flips

```
How many simulations do you want to run? 100000
After 100000 spins: BLACK: 49.85% RED: 50.14999999999999%
```

### 1 million coin flips

```
How many simulations do you want to run? 1000000
After 1000000 spins: BLACK: 49.9431% RED: 50.056900000000006%
```

### 1 billion coin flips

```
How many simulations do you want to run? 1000000000    
After 1000000000 spins: BLACK: 49.994978% RED: 50.005022%
```