Как мне написать симуляцию в r для "азартной" задачи и вероятности возврата? - PullRequest
3 голосов
/ 10 ноября 2019

Я пытаюсь запустить симуляцию в R, и я не совсем уверен, с чего начать. Проблема в следующем:

"У вас 100 долларов, и вы делаете ставки в честной игре на 10 долларов. Какова вероятность того, что вы потеряете все свои деньги к тому моменту, когда сделаете свою сотую ставку?"

Пока что я написал небольшую функцию для генерации случайных результатов из «броска монеты», но это все, что я получил.

win.lose <- function(x){
  sample(0:1, x, rep=TRUE)
}

Меня беспокоит то, что эта функция нене думаю зарабатывать деньги на выигрыше. Некоторая помощь в написании лучшей функции для вышеуказанной задачи будет принята с благодарностью. Спасибо!

Ответы [ 5 ]

2 голосов
/ 10 ноября 2019

лучше всего работает с использованием векторизации. Вместо цикла мы должны выбирать все сразу:

sample(c(-1, 1), 100, replace = TRUE)

Мы также знаем, что если мы получим 10 потерь, мы будем разорены. Переводит в кумулятивную сумму:

cumsum(sample(c(-1, 1), 100, replace = TRUE))

any(cumsum(sample(c(-1, 1), 100, replace = TRUE)) == -10)

Наконец, мы можем использовать replicate(), чтобы повторить ту же самую симуляцию:

#specify simulation criteria
n <- 100 
n_sim <- 10

# betting criteria
n_broke <- 10 #if we have 10 net losses, we're broke
bet <- 10 #each bet is $10

# way 1
set.seed(123)
replicate(n_sim, cumsum(sample(c(-1, 1), n, replace = TRUE))) 

#or with actual money totals - note, 1st row is the initial money amount
set.seed(123)
replicate(n_sim, cumsum(c(n_broke * bet, bet * sample(c(-1, 1), n, replace = TRUE))))

#or a summary of it:
set.seed(123)
table(replicate(n_sim, ifelse(any(cumsum(sample(c(-1, 1), n, replace = TRUE)) == -n_broke), 'Out_of_Money', 'Has_Money')))

#faster way to do it:
set.seed(123)
table(
  ifelse(
    apply(matrix(sample(c(-1,1), n * n_sim, replace = TRUE), ncol = n_sim),
          2,
          function(x) min(cumsum(x)) <= -n_broke),
    'Out_of_Money', 'Has_Money')
)

Для n_sim = 10000:

   Has_Money Out_of_Money 
        6783         3217 

И что происходит за кадром:

set.seed(123)
replicate(n_sim, cumsum(c(n_broke * bet, bet * sample(c(-1, 1), n, replace = TRUE))))
       [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
  [1,]  100  100  100  100  100  100  100  100  100   100
  [2,]   90   90  110  110   90  110  110  110   90   110
  [3,]   80  100  120  120   80  120  120  100   80   120
  [4,]   70  110  130  110   70  130  130   90   90   110
  [5,]   80  100  120  120   60  140  120   80  100   100
  [6,]   70  110  130  110   50  130  110   90   90   110
  [7,]   80  120  140  100   40  120  100   80   80   120
  [8,]   90  110  150  110   50  110   90   70   70   130
  [9,]  100  100  140  100   40  100  100   60   60   120
2 голосов
/ 10 ноября 2019

Это простая проблема с распределением binomial.

  • Сначала : так как нам интересно вычислить вероятность ' к тому времени, когда вы разместилиВаша 100-ая ставка ', нам нужно рассчитать максимальное количество успехов, которое мы можем сделать до 100-го испытания, чтобы не хватило денег: уравнение, которое необходимо решить: 100 + 20*X + (99 - X)*(-10) <= 0, где X - этонеобходимое количество успехов , которое должно быть сделано среди 99 испытаний. Это приводит только к 36 успехам.
  • Второй : поскольку мы уже знаем, что нам нужно 36 успехов из 99 ставок, мы можем использовать pbinomфункция для расчета вероятности получения 36 или менее успехов , если мы сыграли 99 раз:

    pbinom(36,99,0.5)

, которые приводят к вероятностииз 0.004316793.

Это общая основа для честной игры, которую можно использовать с любым количеством начального богатства, ставками и пробным выходом.

Примечание: Кстати, это вычисляет точную вероятность по сравнению с любым методом моделирования!

1 голос
/ 10 ноября 2019

Мы можем написать функцию для sample -10 (проиграл) и 20 (выиграл) 100 раз и вернуть TRUE, если в любое время в 100 ставках мы потеряем все наши деньги (100 $).

lost.balance <- function() {
  total <- cumsum(sample(c(-10, 20), 100, replace = TRUE))
  any(total <= -100)
}

Мы можем смоделировать, используя replicate n раз, и рассчитать коэффициент, используя table

n <- 10000
table(replicate(n, lost.balance()))/n

#   FALSE   TRUE 
#  0.9902 0.0098 
.
1 голос
/ 10 ноября 2019

Вы можете сделать симуляцию из 100 ставок, например, так.

library(dplyr)

current_balance <- 100
bet <- 10
odds <- 0.5

for(i in 1:100) {

  current_balance <- current_balance - bet # place bet

  outcome <- ifelse(runif(1) > 0.5, 
                    bet * 2, # win: receive twice the bet ($20)
                    0) # lose and the initial $10 is lost

  current_balance <- current_balance + outcome

  paste("Balance after", i, "bets is:", current_balance) %>% print

  if(current_balance <= 0) { stop() }
}

Вы можете обернуть все это в другой цикл, чтобы запустить симуляцию более одного раза и записать результаты, например, так:

ending_balances <- c()

for(s in 1:10) {

current_balance <- 100
bet <- 10
odds <- 0.5

  for(i in 1:100) {

    current_balance <- current_balance - bet # place bet

    outcome <- ifelse(runif(1) > 0.5, 
                      bet * 2, # win: receive twice the bet ($20)
                      0) # lose and the initial $10 is lost

    current_balance <- current_balance + outcome

    # paste("Balance after", i, "bets is:", current_balance) %>% print

    if(current_balance <= 0) { 

      ending_balances[s] <- current_balance
      break() 
      }

    ending_balances[s] <- current_balance

  }

}



> ending_balances
 [1]   0  80 220  60   0 120   0  80   0 200
0 голосов
/ 10 ноября 2019

Поскольку у вас есть 100, вы используете 10, тогда у вас есть только 90. Хитрость в том, какова ваша выгода, если вы выиграете. Если удвоится, вам нужно sample(c(-1,2), 100, rep=TRUE).

win.lose <- function(){
    total <- 90
        for(i in c(1:100)){
                bet_output <- sample(c(-1,2), 1, rep=TRUE)
                total <- total + 10 * bet_output
                if(total<0) return(total)
        }
        return(total)
}

sim_y <- unlist(lapply(c(1:10000), function(i){win.lose()} ))
sum(sim_y < 0)/length(sim_y)
...