justin@justin-XPS-13-9360:~/work$ python3 goals_grid.py
home_win 0.45395
away_win 0.24608
draw 0.29997
over_05 0.86466
under_05 0.13534
over_15 0.59399
under_15 0.40601
over_25 0.32332
under_25 0.67668
over_35 0.14288
under_35 0.85712
over_45 0.05265
under_45 0.94735
over_55 0.01656
under_55 0.98344
Last active
October 21, 2019 08:06
-
-
Save jhw/dd7d3dc77bfdce9db48f1713a39417da to your computer and use it in GitHub Desktop.
Simple goals grid model
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 | |
HomeWin, AwayWin, Draw = MatchOdds = ["home_win", "away_win", "draw"] | |
N=10 | |
def poisson(l, x): | |
return (l**x)*math.exp(-l)/math.factorial(x) | |
def correct_score_grid(lx, ly, rho, n): | |
def DC_factor(i, j): | |
if i==0 and j==0: | |
return 1-lx*ly*rho | |
elif i==0 and j==1: | |
return 1+lx*rho | |
elif i==1 and j==0: | |
return 1+ly*rho | |
elif i==1 and j==1: | |
return 1-rho | |
else: | |
return 1 | |
return [[poisson(lx, i)*poisson(ly, j)*DC_factor(i, j) | |
for j in range(n)] | |
for i in range(n)] | |
class CSGrid(list): | |
def __init__(self, data): | |
list.__init__(self, data) | |
def sum(self, filterfn): | |
return sum([self[i][j] | |
for i in range(len(self)) | |
for j in range(len(self)) | |
if filterfn(i, j)]) | |
def match_odds(self, selection): | |
filterfns={HomeWin: lambda i, j: i > j, | |
AwayWin: lambda i, j: i < j, | |
Draw: lambda i, j: i==j} | |
return self.sum(filterfns[selection]) | |
def over_goals(self, strike): | |
filterfn=lambda i, j: i+j > strike | |
return self.sum(filterfn) | |
def under_goals(self, strike): | |
filterfn=lambda i, j: i+j < strike | |
return self.sum(filterfn) | |
def run_model(lx, ly, rho, n=N): | |
# initialise | |
grid=CSGrid(correct_score_grid(lx, ly, rho, n)) | |
table=[] | |
# match odds | |
for attr in MatchOdds: | |
value=grid.match_odds(attr) | |
row={"name": attr, | |
"value": value} | |
table.append(row) | |
# o/u goals | |
for i in range(6): | |
strike=i+0.5 | |
for attr in ["over", "under"]: | |
name="%s_%s" % (attr, str(strike).replace(".", "")) | |
fn=getattr(grid, "%s_goals" % attr) | |
value=fn(strike) | |
row={"name": name, | |
"value": value} | |
table.append(row) | |
# return | |
return table | |
if __name__=="__main__": | |
def format_name(text, n=8): | |
if len(text) > n: | |
return text[:n] | |
else: | |
return text+" ".join(['' for i in range(1+n-len(text))]) | |
for row in run_model(1.2, 0.8, 0): | |
print ("%s\t%.5f" % (format_name(row["name"]), | |
row["value"])) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment