-
-
Save zeratoss/156b07f2cb40f97eaefd156ddd6aeb2c to your computer and use it in GitHub Desktop.
slot simulator
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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