1 Introduction

Martingale’s Strategy is an approach that some have deemed as a foolproof way to play roulette. Therefore, it has to be evaluated from a statistical viewpoint to justify its flawlessness. A computer simulation was built to run numerous trials of the Martingale’s strategy in roulette to see how well it performs based on average earnings and average winnings. The simulation was also explored to see what would happen if certain variables were adjusted. For instance, if the number of trials were increased or reduced or if the budget and the budget threshold values were adjusted. Another interesting inquiry is to know a player’s financial condition after a certain number of wagers.

1.1 Background

A roulette wheel has 18 red pockets, 18 black pockets and 2 green pockets. Each pocket is designed using the same dimension. Hence, there is an equal chance of landing on any pocket. If a player places a wager (or a bet) in the form of money on whether the black or red pocket will be selected and that same pocket is selected, the player gets his equivalent amount of wager as earnings. In the case of the player’s pocket not being selected, the player loses all their waged money. In the case of a loss, the Martingale’s strategy requires the player to keep waging twice the amount of money waged in the previous play in order to ensure a win in the long run. For example, if I wage a bet of 10 dollars and I lose, I will need to place a bet of 20 dollars in my next try. The computer simulation needed to incorporate variables such as budget, maximum number of plays, budget limit and maximum profit. All these variables will be crucial towards simulating Martingale’s strategy in action. The computer simulation was modified to effectively calculate the number of plays it takes for a player to stop playing a round of roulette based on the following requirements: when he loses all his money, when he has played 1000 times or when he has a net earning of +100 dollars. The simulation is set up to be repeated for 10000 times. The final budget made for each trial is recorded, and 200 dollars is subtracted from each final budget to obtain their earnings. Then, the average earning is calculated by dividing the sum of all the earnings by the number of trials. The code that was used to create the simulation can be seen in the methods section below:

The code was updated to account for the number of plays required before losing or winning a round of playing roulette

2 Methods & Discussion

#' A single play of the Martingale strategy
#'
#' Takes a state list, spins the roulette wheel, returns the state list with updated values (for example, budget, plays, etc)
#' @param state A list with the following entries: 
#'   B              number, the budget
#'   W              number, the budget threshold for successfully stoping
#'   L              number, the maximum number of plays 
#'   M              number, the casino wager limit
#'   plays          integer, the number of plays executed
#'   previous_wager number, the wager in the previous play (0 at first play)
#'   previous_win   TRUE/FALSE, indicator if the previous play was a win (TRUE at first play)
#' @return The updated state list
one_play <- function(state){
  
    # Wager
    proposed_wager <- ifelse(state$previous_win, 1, 2*state$previous_wager)
    wager <- min(proposed_wager, state$M, state$B)
    
    # Spin of the wheel
    red <- rbinom(1,1,18/38)
    
    # Update state
    state$plays <- state$plays + 1
    state$previous_wager <- wager
    if(red){
      # WIN
      state$B <- state$B + wager
      state$previous_win <- TRUE
    }else{
      # LOSE
      state$B <- state$B - wager
      state$previous_win <- FALSE
    }
  state
}


#' Stopping rule
#'
#' Takes the state list and determines if the gambler has to stop
#' @param state A list.  See one_play
#' @return TRUE/FALSE
stop_play <- function(state){
  if(state$B <= 0) return(TRUE)
  if(state$plays >= state$L) return(TRUE)
  if(state$B >= state$W) return(TRUE)
  FALSE
}


#' Play roulette to either bankruptcy, success, or play limits
#'
#' @param B number, the starting budget
#' @param W number, the budget threshold for successfully stopping
#' @param L number, the maximum number of plays 
#' @param M number, the casino wager limit
#' @return A vector of budget values calculated after each play.
one_series <- function(
    B = 200
  , W = 300
  , L = 1000
  , M = 100
){

  # initial state
  state <- list(
    B = B
  , W = W
  , L = L
  , M = M
  , plays = 0
  , previous_wager = 0
  , previous_win = TRUE
  )
  
  # vector to store budget over series of plays
  budget <- rep(NA, L)
  
  # For loop of plays
  for(i in 1:L){
    new_state <- state %>% one_play
    budget[i] <- new_state$B
    if(new_state %>% stop_play){
      return(budget[1:i])
    }
    state <- new_state
  }
  budget    
}

# helper function
get_last <- function(x) x[length(x)] 


# Earnings
# The code is modified to include a chart portraying the earnings over the course of one playing session
set.seed(1)
earning <- one_series(B = 200, W = 300, L = 1000, M = 100) - 200
x <- 1:length(earning)
new_df <- data.frame(x = x, earning = earning)
ggplot(new_df) + geom_line(aes(x = x, y = earning), color = 'blue') + labs(title = sprintf("A typical round of a player winning roulette after %d trials", length(earning)), x = "play number", y = "earning") + theme_classic()

set.seed(5)
earning <- one_series(B = 200, W = 300, L = 1000, M = 100) - 200
x <- 1:length(earning)
new_df <- data.frame(x = x, earning = earning)
ggplot(new_df) + geom_line(aes(x = x, y = earning), color = 'red') + labs(title = sprintf("A typical round of a player losing roulette after %d trials", length(earning)), x = "play number", y = "earning") + theme_classic()

# Simulation
walk_out_money <- rep(NA, 10000)
play_length <- rep(NA, 10000)
for(j in seq_along(walk_out_money)){
  round <- one_series(B = 200, W = 300, L = 1000, M = 100)
  walk_out_money[j] <- round %>% get_last
  play_length[j] <- length(round) # calculating the length of wagers for each round
}

# Walk out money distribution
hist(walk_out_money, breaks = 100)

# Estimated probability of walking out with extra cash
sprintf("The probability of winning is: %.2f", mean(walk_out_money > 200))
## [1] "The probability of winning is: 0.51"
# Estimated earnings
sprintf("The estimated earnings for using Martingale's strategy is: %.2f", mean(walk_out_money - 200))
## [1] "The estimated earnings for using Martingale's strategy is: -47.48"
# Estimated number of plays 
sprintf("The average number of plays before stopping is: %.2f", mean(play_length))## average number of plays
## [1] "The average number of plays before stopping is: 201.82"

The first two images showcase how a playing session is bound to take place. The first one shows what is likely to happen if the player wins. The second one displays what a losing round looks like. The earnings are plotted on the y-axis while the wage number on the x-axis. According to the third image, it can be observed that a player using the Martingale’s approach has a 50.84% chance of winning after 10000 trials, and the player is likely to lose about -47.4754 dollars. On average it takes about 201.8242 trials before stopping.

3 Results

3.1 Tweaking the simulation’s parameters

3.1.1 Changing the number of simulations

simulate <- function(plays) {
  walk_out_money <- rep(NA, plays)
  for(j in seq_along(walk_out_money)){
    walk_out_money[j] <- one_series(B = 200, W = 300, L = 1000, M = 100) %>% get_last
  }

  # Walk out money distribution
  hist(walk_out_money, breaks = 100, main = sprintf("Histogram of final buget for %d trials", plays))
  sprintf("After using Martingale's strategy for %d trials, the probability of winning is: %.2f and the estimated earnings is: %.2f", plays, mean(walk_out_money > 200), mean(walk_out_money - 200))
}

simulate(1000)

## [1] "After using Martingale's strategy for 1000 trials, the probability of winning is: 0.51 and the estimated earnings is: -48.02"
simulate(5000)

## [1] "After using Martingale's strategy for 5000 trials, the probability of winning is: 0.50 and the estimated earnings is: -49.51"
simulate(15000)

## [1] "After using Martingale's strategy for 15000 trials, the probability of winning is: 0.51 and the estimated earnings is: -45.70"

It can be observed that increasing or decreasing the simulation does not have that much of an impact on the expected earnings or the probability of winning. Therefore, it can be inferred that this strategy is likely to yield the same average earnings for a wide range of simulations

3.1.2 Increasing the budget, waging limit and budget limit by 1.5x

walk_out_money <- rep(NA, 10000)
play_length <- rep(NA, 10000)
# changing the budget to 300 dollars and maximum earnings to 150 dollars
for(j in seq_along(walk_out_money)){
  round <- one_series(B = 300, W = 450, L = 1000, M = 150)
  walk_out_money[j] <- round %>% get_last
  play_length[j] <- length(round) # calculating the length of wagers for each round
}

# Walk out money distribution
hist(walk_out_money, breaks = 100)

# Estimated probability of walking out with extra cash
sprintf("The probability of winning is: %.2f", mean(walk_out_money > 300))
## [1] "The probability of winning is: 0.50"
# Estimated earnings
sprintf("The estimated earnings for using Martingale's strategy is: %.2f", mean(walk_out_money - 300))
## [1] "The estimated earnings for using Martingale's strategy is: -74.54"

Here the budget was set to 300 dollars, with the budget limit at 450 dollars and wager limit at 150 dollars. The probability of winning was about 50.06% and the expected earnings was -74.5422 dollars.

3.1.3 Decreasing the budget, waging limit and budget limit by 2x

walk_out_money <- rep(NA, 10000)
play_length <- rep(NA, 10000)
# changing the budget to 100 dollars and maximum earnings to 50 dollars
for(j in seq_along(walk_out_money)){
  round <- one_series(B = 100, W = 150, L = 1000, M = 50)
  walk_out_money[j] <- round %>% get_last
  play_length[j] <- length(round) # calculating the length of wagers for each round
}

# Walk out money distribution
hist(walk_out_money, breaks = 100)

# Estimated probability of walking out with extra cash
sprintf("The probability of winning is: %.2f", mean(walk_out_money > 100))
## [1] "The probability of winning is: 0.54"
# Estimated earnings
sprintf("The estimated earnings for using Martingale's strategy is: %.2f", mean(walk_out_money - 100))
## [1] "The estimated earnings for using Martingale's strategy is: -19.30"

Here the budget was set to 100 dollars, with the budget limit at 150 dollars and wager limit at 50 dollars. The probability of winning was about 53.8% and the expected earnings was -19.3 dollars.

Based on the two results of increasing and decreasing the budget-related variables, it can be inferred that higher the budget-related variables, the more money one is likely to lose.

4 Conclusion

The Martingale’s strategy was an amazing strategy to explore from a statistical standpoint because of it deploys statistical techniques in the real world. Martingale’s theory about his strategy being error-proof was proven wrong because it could only work half of the time. Any one who wants to play a game of roulette using Martingale’s strategy should take note of this information next time before playing so they are not too overconfident in the ability of utilizing this strategy to win. An improvement for this strategy will be to account for what happens when the green pocket is selected on the roulette wheel. Should the player get half of his wager back or should he get nothing? Moreover, the random binomial generator was weighted as 18/38 for red. Therefore, I think that it should either account for green or if it doesn’t consider the green pockets, then the red should be weighted as 18/36. One other limitation of the computer simulation lies in its inability to replicate an actual game of roulette. In the real world, human error is bound to lead to mistakes being made by the people reading the outcome of spinning the roulette wheel. Hence, it should have taken uncertainty into account when calculating the outcome of each wager.