In [29]:
    
%%file roll.py
"""
rolls a slightly biased (100-sided) die
"""
import random
import numpy as np
import numpy.random as npr
def win(x):
    '''
    a simple win/loss: where win if (100 > x > 50)
    '''
    return int(bool(100 > x > 50))
def die():
    '''     
    a simple win/loss: where win if (100 > random(1,100) > 50)
    '''         
    return win(random.randint(1,100))
_win = np.vectorize(win)
def dice(N=1):
    '''
    a simple win/loss: where win if (100 > random(1,100,N) > 50)
    '''
    return _win(npr.randint(1,100,N))
def many_die(N=1):
    '''roll simple (biased) win/loss N times'''
    rolls = []
    for i in range(N):
        rolls.append(die())
    return rolls
# EOF
    
    
In [2]:
    
%%file strategy.py
"""
betting strategies
forked from: http://pythonprogramming.net/dashboard/#tab_montecarloyo
"""
import roll
import numpy as np
def trajectory(N=1):
    """convert dice rolls True/False to +1/-1"""
    results = np.empty(N+1)
    results[0] = 0
    results[1:] = np.asarray(roll.dice(N), int)
    record = results[1:]
    record[record == 0] = -1
    return results
def clip(x):
    """clip all values to zero upon first non-positive value"""
    x[x <= 0] = 0
    x[np.logical_not(np.logical_and.accumulate(x))] = 0
    return x
def vsimple(funds, initial_wager, wager_count, *args):
    '''Simple (numpy) bettor, betting the same amount each time.'''
    wager = initial_wager
    return clip(funds + (wager * np.cumsum(trajectory(wager_count))))
def vmartingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    wager = float(initial_wager)
    history = trajectory(wager_count)
    won = history.copy()
    won[1:] = history[:-1] > -1  # also treat '0' as 'win'
    # upon losing, double the bet
    # upon winning, bet the initial
    # can't bet more than you have
    for i,w in enumerate(won[1:]):
        n = i+1
        if w:
            won[n] = 1
            continue
        scale = wscale if history[i] == 1 else lscale
        won[n] = min(scale * won[i], funds/wager + sum(history[:n] * won[:n]))
    '''# calculation looks something like this...
    history = [0, 1, 1,-1,-1, 1, 1,-1,-1,-1]
        won = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
        bet = [0, 1, 1, 1, 2, 4, 1, 1, 2, 4]
      value = [0, 1, 1,-1,-2, 4, 1,-1,-2,-4]
    '''
    return clip(funds + (wager * np.cumsum(history * won)))
def simple(funds, initial_wager, wager_count, *args):
    '''
    Simple bettor, betting the same amount each time.
    '''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    currentWager = 1
    while currentWager <= wager_count:
        if roll.die():
            value += wager
            history[currentWager] = value
        else:
            value -= wager
            if value <= 0:
                break
            history[currentWager] = value
        currentWager += 1
    return history
def martingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    '''martingale bettor, "doubling-down" (actually, "*scaling-down")'''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    currentWager = 1
    # since we'll be betting based on previous bet outcome #
    previousWager = 'win'
    # since we'll be doubling #
    previousWagerAmount = initial_wager
    while currentWager <= wager_count:
        if previousWager == 'win':
            if roll.die():
                value += wager
                history[currentWager] = value
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        elif previousWager == 'loss':
            if roll.die():
                wager = previousWagerAmount * wscale
                if (value - wager) < 0:
                    wager = value
                value += wager
                history[currentWager] = value
                wager = initial_wager
                previousWager = 'win'
            else:
                wager = previousWagerAmount * lscale
                if (value - wager) < 0:
                    wager = value
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        currentWager += 1
    return history
def dAlembert(funds, initial_wager, wager_count, *args):
    '''d'Alembert bettor'''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    currentWager = 1
    # since we'll be betting based on previous bet outcome #
    previousWager = 'win'
    # since we'll be doubling #
    previousWagerAmount = initial_wager
    while currentWager <= wager_count:
        if previousWager == 'win':
            if wager == initial_wager:
                pass
            else:
                wager -= initial_wager
            if roll.die():
                value += wager
                history[currentWager] = value
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        elif previousWager == 'loss':
            wager = previousWagerAmount + initial_wager
            if (value - wager) < 0:
                wager = value
            if roll.die():
                value += wager
                history[currentWager] = value
                previousWager = 'win'
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        currentWager += 1
    return history
# for vector monte carlo
''' # could be nice, but history has different lengths
v_simple = np.vectorize(simple)
v_martingale = np.vectorize(martingale)
v_dAlembert = np.vectorize(dAlembert)
'''
# EOF
    
    
In [3]:
    
%%file trials.py
"""
monte carlo trials for betting strategies, and measures of success
"""
import numpy as np
def monte(bettor, initial_funds, initial_bet, number_bets, number_players, W,L):
    "monte carlo run for a betting strategy"
    history = []
    while len(history) < number_players:
        history.append(bettor(initial_funds, initial_bet, number_bets, W,L))
    return np.array(history)
def alive(history, number_players):
    "find the percentage of players that are not broke"
    return 100. * sum(np.asarray(history, bool).T[-1])/number_players
def gains(history, number_players, initial_funds):
    "find the percentage of players that have profited"
    return 100. * sum(history.T[-1] > initial_funds)/number_players
def profit(history, number_players, initial_funds):
    "find the total profit"
    return np.max(history.T[-1]) - initial_funds
def margin(history, number_players, initial_funds):
    "find the percentage the return on investment is over the initial funds"
    initial = number_players * initial_funds
    return 100.* (sum(history.T[-1]) - initial)/initial
# EOF
    
    
In [1]:
    
%%file use_trials2.py
"""
usage testing of trials
"""
import numpy as np
import matplotlib.pylab as mpl
import trials
import time
def plot_trajectories(bettor, initial_funds, initial_bet, number_bets, number_players, W,L):
    "plot the Monte Carlo trajectories of a 100-sided die for the selected strategy"
    history = trials.monte(bettor, initial_funds, initial_bet, number_bets, number_players, W,L)
    mpl.plot(history.T)
    mpl.plot(initial_funds * np.ones(number_bets+1), lw=2)
    print "survived: {}%".format(trials.alive(history, number_players))
    print "profited: {}%".format(trials.gains(history, number_players, initial_funds))
    funds = trials.margin(history, number_players, initial_funds)
    funds = np.mean(funds)*initial_funds
    win = funds >= 0
    print "ave profit: {}${:.2f}".format('' if win else '-', funds if win else -funds)
    funds = trials.profit(history, number_players, initial_funds)
    win = funds >= 0
    print "max profit: {}${:.2f}".format('' if win else '-', funds if win else -funds)
    return 
def use_monte():
    import strategy
    initial_funds = 10000
    initial_bet = 100
    number_bets = 1000
    number_players = 100
    bettor = strategy.martingale
    W = L = 2.0
    return trials.monte(bettor, initial_funds, initial_bet, number_bets, number_players, W,L)
def use_vmonte():
    import strategy
    initial_funds = 10000
    initial_bet = 100
    number_bets = 1000
    number_players = 100
    bettor = strategy.vmartingale
    W = L = 2.0
    return trials.monte(bettor, initial_funds, initial_bet, number_bets, number_players, W,L)
def use_trials():
    import strategy
    initial_funds = 10000
    initial_bet = 100
    number_bets = 1000
    number_players = 100
    bettor = strategy.martingale
    W = L = 2.0
    plot_trajectories(bettor, initial_funds, initial_bet, number_bets, number_players, W,L)
    mpl.show()
def use_vtrials():
    import strategy
    initial_funds = 10000
    initial_bet = 100
    number_bets = 1000
    number_players = 100
    bettor = strategy.vmartingale
    W = L = 2.0
    plot_trajectories(bettor, initial_funds, initial_bet, number_bets, number_players, W,L)
    mpl.show()
    
# EOF
    
    
In [9]:
    
%matplotlib inline
    
In [14]:
    
import numpy as np
import random
np.random.seed(123)
random.seed(123)
    
In [15]:
    
use_trials()
    
    
    
In [16]:
    
np.random.seed(123)
random.seed(123)
    
In [17]:
    
use_trials()
    
    
    
In [18]:
    
np.random.seed(123)
random.seed(123)
    
In [19]:
    
use_vtrials()
    
    
    
In [21]:
    
np.random.seed(123)
random.seed(123)
%timeit -n 10 use_monte()
np.random.seed(123)
random.seed(123)
%timeit -n 10 use_vmonte()
    
    
In [9]:
    
import profiling
import roll
%timeit roll.dice(1000)
%timeit roll.many_die(1000)
profiling.profile('roll.dice(1000)')
profiling.profile('roll.many_die(1000)')
    
    
In [22]:
    
%%file profile_strategy.py
"""
betting strategies
forked from: http://pythonprogramming.net/dashboard/#tab_montecarloyo
"""
import roll
import numpy as np
import random
@profile
def trajectory(N=1):
    """convert dice rolls True/False to +1/-1"""
    results = np.empty(N+1)
    results[0] = 0
    results[1:] = np.asarray(roll.dice(N), int)
    record = results[1:]
    record[record == 0] = -1
    return results
@profile
def clip(x):
    """clip all values to zero upon first non-positive value"""
    x[x <= 0] = 0
    x[np.logical_not(np.logical_and.accumulate(x))] = 0
    return x
@profile
def vsimple(funds, initial_wager, wager_count, *args):
    '''Simple (numpy) bettor, betting the same amount each time.'''
    wager = initial_wager
    return clip(funds + (wager * np.cumsum(trajectory(wager_count))))
@profile
def vmartingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    wager = float(initial_wager)
    history = trajectory(wager_count)
    won = history.copy()
    won[1:] = history[:-1] > -1  # also treat '0' as 'win'
    # upon losing, double the bet
    # upon winning, bet the initial
    # can't bet more than you have
    for i,w in enumerate(won[1:]):
        n = i+1
        if w:
            won[n] = 1
            continue
        scale = wscale if history[i] == 1 else lscale
        won[n] = min(scale * won[i], funds/wager + sum(history[:n] * won[:n]))
    '''# calculation looks something like this...
    history = [0, 1, 1,-1,-1, 1, 1,-1,-1,-1]
        won = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
        bet = [0, 1, 1, 1, 2, 4, 1, 1, 2, 4]
      value = [0, 1, 1,-1,-2, 4, 1,-1,-2,-4]
    '''
    return clip(funds + (wager * np.cumsum(history * won)))
@profile
def simple(funds, initial_wager, wager_count, *args):
    '''
    Simple bettor, betting the same amount each time.
    '''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    currentWager = 1
    while currentWager <= wager_count:
        if roll.die():
            value += wager
            history[currentWager] = value
        else:
            value -= wager
            if value <= 0:
                break
            history[currentWager] = value
        currentWager += 1
    return history
@profile
def martingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    '''martingale bettor, "doubling-down" (actually, "*scaling-down")'''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    currentWager = 1
    # since we'll be betting based on previous bet outcome #
    previousWager = 'win'
    # since we'll be doubling #
    previousWagerAmount = initial_wager
    while currentWager <= wager_count:
        if previousWager == 'win':
            if roll.die():
                value += wager
                history[currentWager] = value
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        elif previousWager == 'loss':
            if roll.die():
                wager = previousWagerAmount * wscale
                if (value - wager) < 0:
                    wager = value
                value += wager
                history[currentWager] = value
                wager = initial_wager
                previousWager = 'win'
            else:
                wager = previousWagerAmount * lscale
                if (value - wager) < 0:
                    wager = value
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        currentWager += 1
    return history
def run_trajectory(initial_funds, initial_bets, number_bets, *args, **kwds):
    "plot the rolls of a 100-sided die for all strategies"
    bettors = (simple, martingale, vsimple, vmartingale)
    for bettor in bettors:
        np.random.seed(123)
        random.seed(123)
        _ = bettor(initial_funds, initial_bets, number_bets, *args, **kwds)
    return
if __name__ == '__main__':
    initial_funds = 10000
    initial_bet = 100
    number_bets = 1000
    W = L = 2
    run_trajectory(initial_funds, initial_bet, number_bets, W,L)
# EOF
    
    
In [23]:
    
%%bash
kernprof -lv profile_strategy.py
    
    
In [24]:
    
%%file profile_strategy2.py
"""
betting strategies
forked from: http://pythonprogramming.net/dashboard/#tab_montecarloyo
"""
import roll
import numpy as np
import random
#@profile
def trajectory(N=1):
    """convert dice rolls True/False to +1/-1"""
    results = np.empty(N+1)
    results[0] = 0
    results[1:] = np.asarray(roll.dice(N), int)
    record = results[1:]
    record[record == 0] = -1
    return results
#@profile
def clip(x):
    """clip all values to zero upon first non-positive value"""
    x[x <= 0] = 0
    x[np.logical_not(np.logical_and.accumulate(x))] = 0
    return x
#@profile
def vsimple(funds, initial_wager, wager_count, *args):
    '''Simple (numpy) bettor, betting the same amount each time.'''
    wager = initial_wager
    return clip(funds + (wager * np.cumsum(trajectory(wager_count))))
#@profile
def vmartingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    wager = float(initial_wager)
    history = trajectory(wager_count)
    won = history.copy()
    won[1:] = history[:-1] > -1  # also treat '0' as 'win'
    # upon losing, double the bet
    # upon winning, bet the initial
    # can't bet more than you have
    for i,w in enumerate(won[1:]):
        n = i+1
        if w:
            won[n] = 1
            continue
        scale = wscale if history[i] == 1 else lscale
        won[n] = min(scale * won[i], funds/wager + sum(history[:n] * won[:n]))
    '''# calculation looks something like this...
    history = [0, 1, 1,-1,-1, 1, 1,-1,-1,-1]
        won = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
        bet = [0, 1, 1, 1, 2, 4, 1, 1, 2, 4]
      value = [0, 1, 1,-1,-2, 4, 1,-1,-2,-4]
    '''
    return clip(funds + (wager * np.cumsum(history * won)))
@profile
def simple(funds, initial_wager, wager_count, *args):
    '''
    Simple bettor, betting the same amount each time.
    '''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    roll_die = roll.dice(wager_count+1)
    currentWager = 1
    while currentWager <= wager_count:
        if roll_die[currentWager]:
            value += wager
            history[currentWager] = value
        else:
            value -= wager
            if value <= 0:
                break
            history[currentWager] = value
        currentWager += 1
    return history
@profile
def martingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    '''martingale bettor, "doubling-down" (actually, "*scaling-down")'''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    roll_die = roll.dice(wager_count+1)
    currentWager = 1
    # since we'll be betting based on previous bet outcome #
    previousWager = 'win'
    # since we'll be doubling #
    previousWagerAmount = initial_wager
    while currentWager <= wager_count:
        if previousWager == 'win':
            if roll_die[currentWager]:
                value += wager
                history[currentWager] = value
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        elif previousWager == 'loss':
            if roll_die[currentWager]:
                wager = previousWagerAmount * wscale
                if (value - wager) < 0:
                    wager = value
                value += wager
                history[currentWager] = value
                wager = initial_wager
                previousWager = 'win'
            else:
                wager = previousWagerAmount * lscale
                if (value - wager) < 0:
                    wager = value
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        currentWager += 1
    return history
def run_trajectory(initial_funds, initial_bets, number_bets, *args, **kwds):
    "plot the rolls of a 100-sided die for all strategies"
    bettors = (simple, martingale, vsimple, vmartingale)
    for bettor in bettors:
        np.random.seed(123)
        random.seed(123)
        _ = bettor(initial_funds, initial_bets, number_bets, *args, **kwds)
    return
if __name__ == '__main__':
    initial_funds = 10000
    initial_bet = 100
    number_bets = 1000
    W = L = 2
    run_trajectory(initial_funds, initial_bet, number_bets, W,L)
# EOF
    
    
In [25]:
    
%%bash
kernprof -lv profile_strategy2.py
    
    
In [26]:
    
%%file strategy.py
"""
betting strategies
forked from: http://pythonprogramming.net/dashboard/#tab_montecarloyo
"""
import roll
def simple(funds, initial_wager, wager_count, *args):
    '''
    Simple bettor, betting the same amount each time.
    '''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    roll_die = roll.dice(wager_count+1)
    currentWager = 1
    while currentWager <= wager_count:
        if roll_die[currentWager]:
            value += wager
            history[currentWager] = value
        else:
            value -= wager
            if value <= 0:
                break
            history[currentWager] = value
        currentWager += 1
    return history
def martingale(funds, initial_wager, wager_count, wscale=1, lscale=1):
    '''martingale bettor, "doubling-down" (actually, "*scaling-down")'''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    roll_die = roll.dice(wager_count+1)
    currentWager = 1
    # since we'll be betting based on previous bet outcome #
    previousWager = 'win'
    # since we'll be doubling #
    previousWagerAmount = initial_wager
    while currentWager <= wager_count:
        if previousWager == 'win':
            if roll_die[currentWager]:
                value += wager
                history[currentWager] = value
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        elif previousWager == 'loss':
            if roll_die[currentWager]:
                wager = previousWagerAmount * wscale
                if (value - wager) < 0:
                    wager = value
                value += wager
                history[currentWager] = value
                wager = initial_wager
                previousWager = 'win'
            else:
                wager = previousWagerAmount * lscale
                if (value - wager) < 0:
                    wager = value
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        currentWager += 1
    return history
def dAlembert(funds, initial_wager, wager_count, *args):
    '''d'Alembert bettor'''
    value = funds
    wager = initial_wager
    wager_count = int(wager_count)
    history = [funds] + [0]*(wager_count)
    roll_die = roll.dice(wager_count+1)
    currentWager = 1
    # since we'll be betting based on previous bet outcome #
    previousWager = 'win'
    # since we'll be doubling #
    previousWagerAmount = initial_wager
    while currentWager <= wager_count:
        if previousWager == 'win':
            if wager == initial_wager:
                pass
            else:
                wager -= initial_wager
            if roll_die[currentWager]:
                value += wager
                history[currentWager] = value
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        elif previousWager == 'loss':
            wager = previousWagerAmount + initial_wager
            if (value - wager) < 0:
                wager = value
            if roll_die[currentWager]:
                value += wager
                history[currentWager] = value
                previousWager = 'win'
            else:
                value -= wager
                if value <= 0:
                    break
                history[currentWager] = value
                previousWager = 'loss'
                previousWagerAmount = wager
        currentWager += 1
    return history
# EOF
    
    
In [28]:
    
np.random.seed(123)
random.seed(123)
import use_trials2
%timeit -n 10 use_trials2.use_monte()