This blog is aimed at helping sharp freshmen understand Roulette Strategies using computer simulation.
This is clear in the assignment instruction.
The Roulette Strategies discussed today is Martingale Strategy. Students could open the following link to get an elementary understanding of Martingale: https://www.statisticshowto.com/martingale-definition/
The following code simulates the Martingale strategy:
#' 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
library(tidyverse)
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.2 ──
## ✔ ggplot2 3.3.6 ✔ purrr 0.3.4
## ✔ tibble 3.1.8 ✔ dplyr 1.0.9
## ✔ tidyr 1.2.0 ✔ stringr 1.4.0
## ✔ readr 2.1.2 ✔ forcats 0.5.1
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
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 stoping
#' @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
}
Show 5 simulations of gamler’s earnings:
for(i in 1:5){
leger<-one_series()
plot(leger, type = "l", lwd = 5, xlab = "Game Index", ylab = "Budget")
}
From above we could see that the earnings are random and could not find
any possible patterns.
Let’s increasing the repeating times and see what’s the average earnings and the distribution.
The following shows the average earnings and bar chart of winning or losing times repeating from 10 to 100,000 times.
# helper function
get_last <- function(x) x[length(x)]
# repeat 10 times:
walk_out_money <- rep(NA, 10)
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)
# Estimated probability of walking out with extra cash
mean(walk_out_money > 200)
## [1] 0.6
# Estimated earnings
mean(walk_out_money - 200)
## [1] -20
# repeat 100 times:
walk_out_money <- rep(NA, 100)
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)
# Estimated probability of walking out with extra cash
mean(walk_out_money > 200)
## [1] 0.54
# Estimated earnings
mean(walk_out_money - 200)
## [1] -38
#repeat 1000 times:
walk_out_money <- rep(NA, 1000)
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)
# Estimated probability of walking out with extra cash
mean(walk_out_money > 200)
## [1] 0.497
# Estimated earnings
mean(walk_out_money - 200)
## [1] -51.026
#repeat 10000 times:
walk_out_money <- rep(NA, 10000)
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)
# Estimated probability of walking out with extra cash
mean(walk_out_money > 200)
## [1] 0.5103
# Estimated earnings
mean(walk_out_money - 200)
## [1] -46.8492
walk_out_money <- rep(NA, 100000)
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)
# Estimated probability of walking out with extra cash
mean(walk_out_money > 200)
## [1] 0.51037
# Estimated earnings
mean(walk_out_money - 200)
## [1] -46.85258
From above we could see that as times increasing, the frequencies of winning 100 and losing 200 is approaching 0.5 and the mean of the earnings is about -50
Will changes in parameters change the average meanings? Of course! Because average earnings equal expectation as times increasing: \[E(Earnigs)=P(Earnings)*Earnings+ P(Loss) * Loss\] Lets change the input parameters: Fisrt change start money from 100 to 1000, given other parameters unchanged.
b_vec<-c(100,200,300,400,500,600,700,800,900,1000)
earning_mean<-rep(NA,length(b_vec))
i<-1
for (bb in b_vec){
walk_out_money <- rep(NA,bb)
for(j in seq_along(walk_out_money)){
walk_out_money[j] <- one_series(B = bb, W = 300, L = 1000, M = 100) %>% get_last
}
# Estimated probability of walking out with extra cash
earning_mean[i]<-mean(walk_out_money - bb)
i<-i+1
}
b_df<-data.frame(b_vec,earning_mean)
plot(b_df, type = "l", lwd = 5, xlab = "Starting Money", ylab = "Average earnings")
Then change stop thresh hold from 300 to 1000, given other parameters unchanged.
t_vec<-c(300,400,500,600,700,800,900,1000)
earning_mean<-rep(NA,length(t_vec))
i<-1
for (tt in t_vec){
walk_out_money <- rep(NA,bb)
for(j in seq_along(walk_out_money)){
walk_out_money[j] <- one_series(B = 200, W = tt, L = 1000, M = 100) %>% get_last
}
# Estimated probability of walking out with extra cash
earning_mean[i]<-mean(walk_out_money - 200)
i<-i+1
}
t_df<-data.frame(t_vec,earning_mean)
plot(t_df, type = "l", lwd = 5, xlab = "Thresh Hold", ylab = "Average earnings")
The more you want, the less you are likely to gain:( The following code
shows how to calculate average number of plays till game ends: Lets
repeat 1000 times first:
times <- rep(NA,1000)
for (tm in 1:1000){
times[tm]<-length(one_series())
}
times
## [1] 187 192 34 19 148 189 253 281 188 218 200 284 209 118
## [15] 14 205 169 213 433 50 236 131 13 218 194 50 170 19
## [29] 257 213 225 316 159 191 133 395 185 79 24 80 98 233
## [43] 321 270 32 197 267 269 197 20 18 126 194 312 207 654
## [57] 192 114 241 178 45 20 294 145 151 42 40 194 189 211
## [71] 472 658 514 137 189 82 194 184 129 70 312 90 215 198
## [85] 197 280 189 169 260 445 146 555 130 90 64 35 376 215
## [99] 130 21 15 215 266 16 164 292 180 108 89 196 202 302
## [113] 217 118 318 445 35 210 228 265 204 201 167 223 54 219
## [127] 192 23 178 265 212 187 175 89 374 8 268 249 96 95
## [141] 211 583 270 270 148 203 27 402 210 139 204 73 197 184
## [155] 200 229 27 35 11 38 211 272 168 213 27 267 285 310
## [169] 194 10 87 196 269 438 359 265 185 224 53 194 200 187
## [183] 75 90 297 205 279 537 292 204 76 205 338 546 209 208
## [197] 273 42 46 203 167 88 680 236 256 173 248 64 364 194
## [211] 62 119 214 19 208 265 213 200 52 235 163 211 228 200
## [225] 218 183 200 285 118 14 70 199 37 187 249 378 57 197
## [239] 831 223 46 39 204 200 48 90 431 657 202 155 280 1000
## [253] 37 481 358 277 267 312 51 281 279 503 52 24 86 25
## [267] 173 13 271 64 218 720 148 62 270 214 271 75 185 39
## [281] 301 327 378 190 197 198 195 279 185 249 15 199 77 213
## [295] 201 141 268 330 134 230 29 258 254 220 17 196 49 218
## [309] 210 222 216 165 42 394 207 145 244 196 212 61 94 146
## [323] 220 187 201 46 352 193 211 87 344 212 593 365 89 215
## [337] 357 171 340 179 191 220 187 259 159 209 109 237 156 52
## [351] 74 181 185 210 50 179 199 277 103 228 197 8 190 73
## [365] 182 244 148 240 133 135 189 77 269 183 161 16 161 207
## [379] 201 300 24 187 270 276 215 674 111 364 194 71 259 115
## [393] 86 474 215 207 255 156 111 26 355 10 131 112 188 282
## [407] 247 687 201 205 221 218 176 220 15 38 220 197 63 194
## [421] 269 220 263 271 62 235 105 77 37 283 234 201 416 100
## [435] 364 210 62 311 199 66 215 250 331 33 168 356 31 415
## [449] 111 201 79 214 30 44 222 46 13 288 248 185 94 285
## [463] 195 206 220 189 200 177 199 320 548 269 252 191 302 228
## [477] 216 53 312 188 201 211 185 270 278 206 70 263 45 235
## [491] 72 199 234 192 14 184 210 193 199 450 393 235 230 19
## [505] 261 9 204 216 234 194 216 263 130 49 128 305 205 262
## [519] 186 201 23 210 198 97 13 319 279 89 180 204 363 183
## [533] 281 167 290 287 314 21 214 523 167 224 215 575 78 269
## [547] 162 193 181 206 192 280 208 315 53 37 69 235 187 206
## [561] 195 169 494 219 214 227 403 41 207 284 291 30 89 185
## [575] 192 150 62 231 186 189 196 87 197 110 178 134 177 95
## [589] 211 216 365 207 218 292 121 31 315 201 252 164 358 279
## [603] 222 263 11 327 189 261 329 224 496 110 229 102 275 13
## [617] 239 214 363 60 204 180 155 247 237 178 197 201 206 282
## [631] 306 210 128 214 194 8 46 218 194 268 193 46 199 229
## [645] 205 677 404 25 116 167 198 182 218 86 106 261 227 367
## [659] 44 293 59 92 311 277 201 271 269 47 136 110 243 117
## [673] 92 107 204 183 33 194 190 202 214 200 43 614 251 224
## [687] 372 81 488 208 24 115 201 32 207 191 373 264 192 47
## [701] 262 63 12 201 191 193 200 206 206 372 128 205 196 138
## [715] 403 200 268 208 35 176 266 262 106 534 42 166 47 287
## [729] 115 229 161 208 245 31 261 237 9 308 79 31 208 246
## [743] 315 403 201 98 227 19 188 431 323 209 254 116 174 63
## [757] 38 232 278 95 203 203 209 225 962 39 54 222 204 196
## [771] 313 15 51 192 199 282 24 65 313 274 188 261 46 70
## [785] 284 214 330 184 216 159 256 215 350 181 191 183 497 267
## [799] 198 198 156 149 214 168 273 266 186 22 273 329 199 595
## [813] 236 323 55 71 211 52 212 648 98 195 731 192 173 170
## [827] 287 111 359 217 276 41 170 54 421 265 546 363 310 335
## [841] 240 63 207 85 8 312 32 189 222 206 242 209 319 186
## [855] 620 298 624 26 204 79 211 214 175 207 115 197 248 52
## [869] 208 205 215 27 189 258 219 207 104 258 21 620 81 222
## [883] 205 256 180 262 181 277 196 248 180 1000 215 527 211 199
## [897] 13 32 81 224 262 204 34 190 222 185 296 226 197 108
## [911] 204 209 301 249 147 287 251 42 202 17 146 69 193 202
## [925] 206 195 267 227 793 131 169 9 83 29 285 195 386 13
## [939] 205 203 22 112 165 173 353 315 258 229 202 272 31 212
## [953] 200 143 206 167 195 193 37 25 212 245 222 199 349 194
## [967] 198 187 34 206 201 161 248 233 282 207 216 89 208 193
## [981] 15 336 192 25 298 30 72 89 10 79 66 79 261 197
## [995] 225 271 256 136 44 273
mean(times)
## [1] 202.034
Increasing to 100,000 times to get more precise average times:
times <- rep(NA,100000)
for (tm in 1:100000){
times[tm]<-length(one_series())
}
mean(times)
## [1] 201.2659
In this blog, the definition of Roulette Strategy is first displayed. Then the code is pulled to simulate the gamble gaming. By changing parameters, the average earnings also vary. In the long run, the house always wins because the expectation is minus, so do not risk all your money on gambling.