Skip to content

Instantly share code, notes, and snippets.

@zeratoss
Created March 9, 2020 17:18
Show Gist options
  • Save zeratoss/156b07f2cb40f97eaefd156ddd6aeb2c to your computer and use it in GitHub Desktop.
Save zeratoss/156b07f2cb40f97eaefd156ddd6aeb2c to your computer and use it in GitHub Desktop.
slot simulator
import math
import pandas as pd
import time
import matplotlib.pyplot as plt
import slots
# start timer to calculate duration
start = time.time()
# TODO: let user choose table
# USER INPUT
# slot, choices are slots.bluejay, slots.inthemoney, slots.blazing7s, slots.rwb_reno, slots.dd_deluxe, slots.ll_lobster, slots.rwb_wizard
selected_slot = slots.dd_deluxe
# should rtp be adjusted? select rtp to adjust probability tables (0-1)
adjust = False
rtp = 0.98
# how much did we deposit? how much bonus money?
deposit = 100
bonus = 50
bank = deposit + bonus
# how much do we need to wager?
w_requirement = 3000
# stake size
stake = 5
# number of spins necessary rounded up
spins = math.ceil(w_requirement / stake)
# number of simulations
universes = 1000
# END USER INPUT
# Calculate one run of our slot from probability table, stored in slots.py, and stake
def result():
multi = adjusted_paytable.Multiplier.sample(weights=adjusted_paytable.Probability)
# TODO sample returns series we only want value
multi = multi.iloc[0]
win = stake * multi - stake
return win
# Play until we are broke or wagering requirement is met
def simulate(spins_s, bank_s):
for i in range(spins_s):
if bank_s >= stake:
bank_s += result()
else:
break
return bank_s
# calculate the rtp of a probability dataframe rtp = 1 - house edge
def calc_rtp(dataframe):
dataframe["pxp"] = dataframe["Multiplier"] * dataframe["Probability"]
return dataframe["pxp"].sum()
# calculate the standard deviation of a dataframe as measurement of volatility
def calc_sd(dataframe):
dataframe["pxp"] = dataframe["Multiplier"] * dataframe["Probability"]
rtp = dataframe["pxp"].sum()
dataframe["Variance"] = ((dataframe["Multiplier"] - 1) - (1 - rtp)) ** 2 * dataframe["Probability"]
return math.sqrt(dataframe["Variance"].sum())
# Adjust paytable to new rtp by increasing/decreasing every win chance by the same value
def set_rtp(rtp_new, dataframe):
rtp_old = calc_rtp(dataframe)
if rtp_old != rtp_new:
dataframe["pxp"] = dataframe["Multiplier"] * dataframe["Probability"]
rtp_diff = abs(rtp_new - rtp_old)
rtp_category = rtp_diff / len(dataframe.index)
if rtp_new > rtp_old:
print("Increasing RTP from", rtp_old, "to", rtp_new, "SD was", calc_sd(dataframe))
dataframe["pxp"] += rtp_category
dataframe["Probability"] = dataframe["pxp"] / dataframe["Multiplier"]
dataframe.iat[0, 1] = 1 - dataframe.iloc[1:, [1]].sum()
print("new rtp", round(calc_rtp(dataframe), 4), "new sd", calc_sd(dataframe))
return dataframe
else:
print("Lowering RTP from", rtp_old, "to", rtp_new, "SD was", calc_sd(dataframe))
dataframe["pxp"] -= rtp_category
dataframe["Probability"] = dataframe["pxp"] / dataframe["Multiplier"]
# reducing probabilities can lead to negative values, set them = 0
dataframe[dataframe < 0] = 0
dataframe.iat[0, 1] = 1 - dataframe.iloc[1:, [1]].sum()
print("new rtp", round(calc_rtp(dataframe), 4), "new sd", calc_sd(dataframe))
return dataframe
else:
print("RTP is already", rtp_new, "nothing to be done..")
return dataframe
# initialize variables
bust_nr = 0
loss_nr = 0
result_list = []
print("Slot =", selected_slot.name)
# Adjust paytable if flag is set
if adjust is True:
adjusted_paytable = set_rtp(rtp,selected_slot)
else:
print("Not adjusting rtp")
adjusted_paytable = selected_slot
# Simulate the number of universes TODO: need to speed this up
for i in range(universes):
value = simulate(spins, bank)
result_list.append(value)
# Present results and do statistics
# Calculate average win
ev = (sum(result_list) / universes) - deposit
# Count number of losses and busts
for i in result_list:
if i < deposit:
loss_nr += 1
if i < stake:
bust_nr += 1
# Create lists of wins for all universes
win_list = [x - deposit for x in result_list]
# Explain outcome to user
print("Deposit", deposit, "Bonus", bonus, "Wagering Requirement", w_requirement)
print("After", universes, "simulations with stake size", stake )
print("EV is", round(ev, 2))
bust_percent = bust_nr / universes * 100
print(round(bust_percent, 2), "% percent bust rate")
loss_percent = loss_nr / universes * 100
print(round(loss_percent, 2), "% percent loss rate")
#Create histograms of winnings TODO: better understand and choose axis/bin size
histogram = plt.hist(win_list, bins='auto') # arguments are passed to np.histogram
plt.title("Histogram of Winnings")
end = time.time()
elapsed = end - start
print("Finished in", elapsed, "seconds")
plt.show()
# TODO: plot graphs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment