Automation Strategies

Learn sports betting strategies and discuss key factors to consider when placing a bet.
Post Reply
PeterLe
Posts: 3715
Joined: Wed Apr 15, 2009 3:19 pm

As promised; here's the code you need, Thanks to Birchy on the Slack Group

import os
from random import random
from matplotlib import pyplot
from tkinter import *
from tkinter import filedialog
from time import time

gui = Tk()
home_path = os.path.expanduser('~')
init_dir = os.path.join(home_path, 'Downloads')
init_path = os.path.join(init_dir, 'BetHistory.csv')
csv_path = StringVar(gui, value=init_path)
mc_iters = IntVar(gui, value=10) # initial number of MC iterations
csv_bets = []

def update_file_path():
hist_path = filedialog.askopenfilename(
parent=gui,
initialdir=init_dir,
title='Choose BetHistory file',
filetypes=[('csv', '*.csv')]
)
if hist_path:
# update label
csv_path.set(hist_path)

def load_csv():
global csv_bets
csv_bets = []
with open(csv_path.get(), 'r') as f:
for row in reversed(f.readlines()[1:]):
cols = list(row.split(','))
if len(cols) != 12:
continue # corrupted csv data
# convert csv strings to floats
for i, v in enumerate(cols):
if i < 7: continue
try:
if '(' in cols:
cols = cols.replace('(', '-').partition(')')[0]
cols = float(cols)
except:
pass
cols[2] = cols[2].upper() # bet side
# add extra info for Monte Carlo lookups
side = cols[2] # 'BACK', 'LAY'
stake = cols[8] # bet stake
price = cols[10] # avg price matched
payout = round(stake * (price - 1), 2) # back win or lay payout
mc_lookup = {
'p_win': 1 / price, # implied probability
True: 0.0, # return if runner wins
False: 0.0, # return if runner loses
}
if side == 'BACK':
mc_lookup[True] = payout # return if runner wins
mc_lookup[False] = -stake # return if runner loses
elif side == 'LAY':
mc_lookup[True] = -payout # return if runner wins
mc_lookup[False] = stake # return if runner loses
cols.append(mc_lookup)
# update cache
csv_bets.append(cols)

def calc_actual_pnl():
"""returns (P&L, ROI, PLOT) tuple"""
load_csv()
total_pnl = 0.0
total_risk = 0.0
roi = 0.0
pnl_plots = []
for bet in csv_bets:
if bet[2] == 'BACK': bet[9] = bet[8] # liability = stake
total_risk = round(total_risk + bet[9], 2)
total_pnl = round(total_pnl + bet[11], 2)
pnl_plots.append(total_pnl)
if total_risk > 0:
roi = round(100 * (total_pnl / total_risk), 2)
return total_pnl, roi, pnl_plots

def plot_graph():
total_pnl, roi, pnl_plots = calc_actual_pnl()
if total_pnl:
# maximise plot window
mngr = pyplot.get_current_fig_manager()
try:
mngr.window.state('zoomed') # OS = WINDOWS
except:
# not tested on OSX/Linux!
pass
pyplot.plot(pnl_plots)
pyplot.xlabel('BETS')
pyplot.ylabel('P&L')
title = 'P&L: %.2f ROI: %.2f%%' % (total_pnl, roi)
pyplot.title(title)
pyplot.show()

def run_monte_carlo():
# calc actual P&L
total_pnl, roi, pnl_plots = calc_actual_pnl()
# run MC
label_mc_result['text'] = ''
button_path['state'] = 'disabled'
button_mc_start['state'] = 'disabled'
button_plot['state'] = 'disabled'
mc_better_count = 0
mc_run_count = int(mc_iters.get() * 1000)
iupdate = 0
start_time = time()
max_drawdown = 0.0
dd_mean_sum, dd_mean_count = 0.0, 0
for i in range(mc_run_count):
mc_pnl, max_pnl = 0.0, 0.0
iupdate += 1
if iupdate > 50:
# update gui
prog = 'Running: %d/%d' % (i, mc_run_count)
label_mc_result['text'] = prog
gui.update()
iupdate = 0
sample_dd = 0.0
for bet in csv_bets:
mc_lookup = bet[12]
runner_wins = random() <= mc_lookup['p_win'] # MC random result
mc_pnl += mc_lookup[runner_wins]
if mc_pnl > max_pnl: max_pnl = mc_pnl
dd = max_pnl - mc_pnl
if dd > sample_dd: sample_dd = dd
if sample_dd > max_drawdown: max_drawdown = sample_dd
dd_mean_sum += sample_dd
dd_mean_count += 1
# did MC P&L beat our actual P&L?
if mc_pnl > total_pnl:
mc_better_count += 1
# outputs
run_time = time() - start_time
eval_count = mc_run_count * len(csv_bets) # total evaluations
mc_better_percentage = 100 * (mc_better_count / mc_run_count)
msg = 'Statistics:\n'
msg += '* Completed %.1fM evaluations in %.2fs\n' % (eval_count / 1e6, run_time)
msg += '* Analysed %d strategy bets\n' % len(csv_bets)
msg += '* Monte Carlo beats strategy: '
msg += '%d times in %d runs (%.2f%%)\n' % (mc_better_count, mc_run_count, mc_better_percentage)
msg += '* Drawdown: max = %.2f, mean = %.2f' % (max_drawdown, dd_mean_sum / dd_mean_count)
label_mc_result['text'] = msg
button_path['state'] = 'normal'
button_plot['state'] = 'normal'
button_mc_start['state'] = 'normal'
gui.update()

# set main window size & header font
gui.geometry('450x300') # main window size
gui.title('BetHistory.csv Analysis')

# file path gui
button_path = Button(gui, text='Change', command=update_file_path)
button_path.place(x=20, y=16)
label_file = Label(gui, text='FILE:')
label_file.place(x=85, y=20)
label_path = Label(gui, textvariable=csv_path)
label_path.place(x=120, y=20)

# plotting gui
button_plot = Button(gui, text='Plot P&L Graph', command=plot_graph)
button_plot.place(x=20, y=80)

# Monte Carlo gui
input_mc_iters = Entry(gui, textvariable=mc_iters, justify='center')
input_mc_iters.place(x=140, y=141, width=40, height=24)
button_mc_start = Button(gui, text='Run Monte Carlo', command=run_monte_carlo)
button_mc_start.place(x=20, y=140)
label_mc = Label(gui, text='x1000 iterations')
label_mc.place(x=180, y=142)
label_mc_result = Label(gui, justify=LEFT)
label_mc_result.place(x=20, y=170)

gui.mainloop()
User avatar
goat68
Posts: 2019
Joined: Tue Jun 30, 2020 3:53 pm
Location: Hampshire, UK

It is essentially just replaying your bets in random "buckets" in random "orders" so you can assess drawdown and such... not sure it can truly help you know how "fitted" your strategy is?
I actually think the random exit idea is a possible way of helping understand how "fitted" your strategy might be see ref here: https://www.seeitmarket.com/3-of-many-u ... ing-18266/
User avatar
goat68
Posts: 2019
Joined: Tue Jun 30, 2020 3:53 pm
Location: Hampshire, UK

Here's a Monte Carlo random exit variation of my bot, looks fairly good, and quite pretty!:
Screenshot 2021-05-12 at 17.59.38.png
User avatar
Realrocknrolla
Posts: 1903
Joined: Fri Jun 05, 2020 7:15 pm

goat68 wrote:
Wed May 12, 2021 6:01 pm
Here's a Monte Carlo random exit variation of my bot, looks fairly good, and quite pretty!:
Screenshot 2021-05-12 at 17.59.38.png
I like colours.

But i cant do shit like that. My skills are not up there yet.
User avatar
goat68
Posts: 2019
Joined: Tue Jun 30, 2020 3:53 pm
Location: Hampshire, UK

Realrocknrolla wrote:
Wed May 12, 2021 6:16 pm
goat68 wrote:
Wed May 12, 2021 6:01 pm
Here's a Monte Carlo random exit variation of my bot, looks fairly good, and quite pretty!:
Screenshot 2021-05-12 at 17.59.38.png
I like colours.

But i cant do shit like that. My skills are not up there yet.
Yes, i'm good at "shit" stuff, rubbish at "trading" :lol: :lol:
User avatar
Realrocknrolla
Posts: 1903
Joined: Fri Jun 05, 2020 7:15 pm

goat68 wrote:
Wed May 12, 2021 6:20 pm
Realrocknrolla wrote:
Wed May 12, 2021 6:16 pm
goat68 wrote:
Wed May 12, 2021 6:01 pm
Here's a Monte Carlo random exit variation of my bot, looks fairly good, and quite pretty!:
Screenshot 2021-05-12 at 17.59.38.png
I like colours.

But i cant do shit like that. My skills are not up there yet.
Yes, i'm good at "shit" stuff, rubbish at "trading" :lol: :lol:
Lol

I can manual trade fine. Automation and programming im dump at. 🤣
Post Reply

Return to “Betfair trading strategies”