Peut-on gagner à la roulette ?

A la recherche d'une stratégie payante pour battre le casino.

import numpy as np
import pandas as pd
import plotly.graph_objects as go
from plotly.offline.offline import plot
class PocketSet:
    def __init__(self, choices):
        self.choices = tuple(choices)
    def __hash__(self):
        return hash(self.choices)
    def __eq__(self, other):
        return isinstance(other, PocketSet) and self.choices == other.choices
    def __str__(self):
        return f"{self.choices} ({hash(self)})"
    
    def get_profit(self, sort, amount):
        profit = -amount
        if sort in self.choices:
            profit += amount * 36 / len(self.choices)
        return profit
def play(apply, cases, length, limit):
    sorts = np.random.choice(cases, length)
    profits = np.zeros(length)
    bets = {}
    win = False
    
    for i, sort in enumerate(sorts):
        bets = apply(bets, win)
        if limit and max(bets.values()) > limit:
            profit = 0
        else:
            profit = sum(pocket.get_profit(sort, amount) for pocket, amount in bets.items())
        win = profit > 0
        profits[i] = profit
        
    return profits.cumsum()
def display(scenarios, title):
    fig = go.Figure()
    t = np.arange(scenarios.shape[1])
    mean = np.mean(scenarios, axis=0)

    for i, scn in enumerate(scenarios):
        fig.add_traces(go.Scatter(x=t, y=scn, line=dict(color='rgba(100, 100, 100, 0.15)')))
    fig.add_traces(go.Scatter(x=t, y=mean, line=dict(color='blue', width=3)))
    fig.add_traces(go.Scatter(x=t, y=np.zeros_like(t), line=dict(color='black', width=3)))
    fig.update_layout(title=title, showlegend=False, yaxis_title='Profits', xaxis_title='Nombre de parties')
    return fig
def simulate(apply, title, case=np.arange(0, 37), length=100, players=250, limit=None):
    scenarios =  np.array([play(apply, case, length, limit) for _ in range(players)])
    fig = display(scenarios, title)
    print(plot(fig, include_plotlyjs=False, include_mathjax=False, output_type='div'))

Début simulation

Les mises simples (noir/rouge, pair/impair, etc)

def only_1_to_18(bets, win):
    return {PocketSet(choices=np.arange(1, 19)): 1}
simulate(apply=only_1_to_18, title='Mise Simple')
simulate(apply=only_1_to_18, title='Mise Simple Sans Zero', case=np.arange(1, 37))
def only_1_to_12(bets, win):
    return {PocketSet(choices=np.arange(1, 13)): 1}
simulate(apply=only_1_to_12, title='Mise double')
simulate(apply=only_1_to_12, title='Mise double Sans zero',  case=np.arange(1, 37))
def one_number(bets, win):
    return {PocketSet(choices=[17]): 1}
simulate(apply=one_number, title='Mise sur le 17')
simulate(apply=one_number, title='Mise sur le 17 sans le zéro', case=np.arange(1, 37))

Le Youtube Game

from IPython.display import IFrame
IFrame('https://www.youtube.com/embed/S3bhRnsgwrI', width=560, height=315)

” Avec cette technique vous avez 56% de chance de gagner à chaque tour” – Youtubeur

def royal_square(bets, win):
    return {
        PocketSet(choices=[0]): 6,
        PocketSet(choices=[5, 8]): 6,
        PocketSet(choices=[5, 8, 4, 7]): 15,
        PocketSet(choices=[12, 15, 11, 14]): 15,
        PocketSet(choices=[17, 20, 16, 19]): 15,
        PocketSet(choices=[24, 27]): 6,
        PocketSet(choices=[24, 27, 23, 26]): 15,
        PocketSet(choices=[29, 32]): 6,
        PocketSet(choices=[28, 29]): 6,
        PocketSet(choices=[28, 29, 31, 32]): 15
    }
simulate(apply=royal_square, title="Le Carré Royal de Youtubeur")

Résultat parfaitement prévisible. En effet, il joue sur 21 cases à la fois sur 37, il a donc bien 56% de chance de gagné à chaque tour. Mais ce qui compte pour se faire de l’argent c’est l’espérence mathématique ! Et dans notre cas, elle est de -9.6€ par tour. Le youtubeur perd donc en moyenne 9.6€ par tour…

La seule technique mathématiquement imbattable !!

IFrame('https://www.youtube.com/embed/3JY-0V2XNTk', width=560, height=315)
pd.DataFrame({
    'mise': [2**(n-1) for n in range(1, 15)],
    'somme engagée': [2**n -1 for n in range(1, 15)],
    'gain espéré': [2**n for n in range(1, 15)],
    'proba': [0.5**n for n in range(1, 15)],
}, index=range(1, 15))
mise somme engagée gain espéré proba
1 1 1 2 0.500000
2 2 3 4 0.250000
3 4 7 8 0.125000
4 8 15 16 0.062500
5 16 31 32 0.031250
6 32 63 64 0.015625
7 64 127 128 0.007812
8 128 255 256 0.003906
9 256 511 512 0.001953
10 512 1023 1024 0.000977
11 1024 2047 2048 0.000488
12 2048 4095 4096 0.000244
13 4096 8191 8192 0.000122
14 8192 16383 16384 0.000061
def martingale(bets, win):
    if win or len(bets) == 0:
        return {PocketSet(choices=np.arange(1, 19)): 1}
    else:
        amount, = bets.values()
        return {PocketSet(choices=np.arange(1, 19)): amount * 2}
simulate(martingale, title='La martingale')
simulate(martingale, title='La matingale avec limite de mise à 200€', limit=200)
simulate(martingale, title='La matingale avec limite de mise à 200€ sans zero', limit=200, case=np.arange(1, 37))