-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.py
187 lines (154 loc) Β· 6.17 KB
/
main.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""
Main file for the Sports Bet project
"""
import argparse
import pandas as pd
import numpy as np
from typing import Dict, Union, List
from game import League
from predictions import ResultsPredictor
from betting import BettingStrategy
pd.options.display.width = 0
np.seterr(divide='ignore', invalid='ignore')
betting_platforms = ['B365', 'BW', 'IW', 'PS', 'WH', 'VC']
def parse_arguments(args: Union[None, List] = None) -> Dict:
"""
:param args: List of argument names and values. If not provided, the command line arguments will be considered.
:return: Validated keyword arguments to provide as input to the downstream classes
"""
parser = argparse.ArgumentParser()
# Game
parser.add_argument(
'--country',
required=True,
type=str,
help="Name of the league's country, among {Italy, France, Spain, England, Germany}."
)
parser.add_argument(
'--division',
type=int,
default=1,
help="Division level, e.g. 1 for Premier League in England. By default, set to 1."
)
parser.add_argument(
'--start_season',
required=True,
type=str,
help="Two digit year indicating the first season analyzed, e.g. 04 for the 2004/2005 season."
)
parser.add_argument(
'--end_season',
required=False,
type=str,
help="Two digit year indicating the last season analyzed, e.g. 05 for the 2004/2005 season. If not "
"specified, we consider the season indicated by the start_season argument."
)
# Betting
parser.add_argument(
'--betting_platform',
required=False,
type=str,
default="B365",
help="Ticker of the betting platform, among {B365, BW, IW, PS, WH, VC}. Some platform may not be available for "
"the chosen league. See data/notes.txt file to get the names behind these tickers. "
"By default, set to B365."
)
parser.add_argument(
'--initial_bankroll',
type=float,
default=100,
help="Initial amount allowed for betting. By default, set to 100."
)
parser.add_argument(
'--stake_per_bet',
type=float,
default=1,
help="Stake for each bet. By default, set to 1."
)
parser.add_argument(
'--do_value_betting',
action="store_true",
default=False,
help="If true, bet only if the expected value of a result is positive, "
"i.e. if its predicted probability is above the inverse of its odd from the betting "
"platform. If false, we always bet on the most likely predicted result, whatever its odd."
)
parser.add_argument(
'--value_betting_on_all_results',
action="store_true",
default=False,
help="If true, perform value betting on the three results, i.e. victory of the home, away team "
"and draw. If false, perform value betting only on the most likely predicted result."
)
parser.add_argument(
'--analyze_betting_platforms_margins',
action="store_true",
default=False,
help="If true, compute the average margins of the betting platforms over the given seasons."
)
# Features
parser.add_argument(
'--match_history_length',
default=None,
type=int,
help="Number of previous matches for each facing team included in the model features. "
"If a value k is provided, then we consider the last k home for the home team and the last k away "
"matches for the away team. If not specified, we do not consider the game history."
)
parser.add_argument(
'--number_previous_direct_confrontations',
default=3,
type=int,
help="Use the last k direct confrontations between the two teams as features. By default, k is set to 3."
)
parser.add_argument(
'--match_results_encoding',
default='points',
type=str,
help="In the feature vectors, encode the result of a match either with a categorical value among 'Win', "
"'Draw' and 'Loose' or with a numerical value, i.e. the number of won points which is respectively 3, 1"
" and 0. The value of this argument is chosen among {categorical, points}. By default, set to "
"points."
)
# Model
parser.add_argument(
'--model_name',
default='LogisticRegression',
type=str,
help="Chosen predictive model following the scikit-learn nomenclature. Supported values are "
"{LogisticRegression, MLPClassifier, DecisionTreeClassifier, RandomForestClassifier}. By default, "
"set to LogisticRegression."
)
parser.add_argument(
'--config_name',
default=None,
type=str,
help="Model configuration name or path. By default, search for the file $model_name.json in the models folder"
)
args = parser.parse_args(args)
countries = ['Italy', 'France', 'Spain', 'England', 'Germany']
assert args.country in countries, '%s is not in the list of supported countries (%s)' % (
args.country, countries)
assert args.betting_platform in betting_platforms, '%s is not in the list of supported betting platforms (%s)' % (
args.betting_platform, betting_platforms)
models = ['LogisticRegression', 'MLPClassifier', 'DecisionTreeClassifier', 'RandomForestClassifier']
assert args.model_name in models, '%s is not in the list of supported models (%s)' % (
args.model_name, models)
if not args.end_season:
args.end_season = '%s' % (str((int(args.start_season) + 1) % 100).zfill(2))
return vars(args)
def main():
kwargs = parse_arguments()
# Set the game
league = League(betting_platforms, **kwargs)
league.run()
if kwargs['analyze_betting_platforms_margins']:
league.analyze_betting_platforms_margins()
results_predictor = ResultsPredictor(league, **kwargs)
results_predictor.train()
results_predictor.eval()
betting_strategy = BettingStrategy(results_predictor, **kwargs)
league.seasons[-1].run(betting_strategy)
betting_strategy.display_results()
if __name__ == '__main__':
main()