Introduction

This report uses the 2021-2022 season (excluding playoffs) for comparing bet results vs. the markets. The win/loss models and the xG models are tuned separately as minor parameter changes will push the model toward better performance on different metrics.

Win/Loss Model

Model Performance

Win/Loss Model performance:

## Log Loss: 0.65301
## Accuracy: 62.31%
## AUC: 0.6605

This model was trained by reducing Log Loss

NOTE Previous editions of this had a minor issue in the model code, incorrectly normalizing the prediction of tied games.

Basic Market Calculations:

Not using market lines with vigs as percent win/loss (instead adding 0.02 to the database odds). Calculating American odds from the percents given, with rounding (toward zero) any decimal -> so if calculated american odds were +225.4, then using +225, and if -142.9 then using -142.

Presuming we place a bet if our predictions for the winner differ by 5%, the bet results from the whole season are as follows:

HomeBets 95.00
AwayBets 185.00
HomeBetResults -1659.00
AwayBetResults 2856.00
HomeUnits -17.46
AwayUnits 15.44
TotalBets 280.00
TotalResults 1197.00
TotalUnits 4.28

Detailed Breakdowns

Team Breakdown (Click to expand)

The results of betting broken down by each team we would have bet on:

BetTeam Number_of_Bets Total_Bet_Result
Anaheim Ducks 6 -604
Arizona Coyotes 61 73
Boston Bruins 13 -171
Buffalo Sabres 13 42
Carolina Hurricanes 9 685
Colorado Avalanche 4 -55
Columbus Blue Jackets 9 197
Dallas Stars 1 -100
Detroit Red Wings 1 -100
Edmonton Oilers 10 368
Florida Panthers 3 62
Los Angeles Kings 1 214
Minnesota Wild 1 124
Montreal Canadiens 19 721
Nashville Predators 11 -238
New Jersey Devils 11 518
New York Islanders 10 -553
New York Rangers 3 137
Ottawa Senators 33 661
Philadelphia Flyers 3 -300
Pittsburgh Penguins 11 -397
San Jose Sharks 2 180
Seattle Kraken 10 -788
St. Louis Blues 7 -92
Tampa Bay Lightning 9 154
Vancouver Canucks 5 319
Vegas Golden Knights 8 223
Washington Capitals 3 -46
Winnipeg Jets 3 -37
Favourite/Underdog Breakdown (Click to expand)

The results of betting broken down by whether we bet on favourites or underdogs:

Check if we would make more money betting with or against the favourite (based on + 100 or < -100 we bet with favourite).

FavBet Number_of_Bets Total_Bet_Result
Bet Against Favourite 241 1259
Bet Favourite 39 -62
Win/Loss by Confidence Level (Click to expand)

Check if there’s a bias in win/loss by confidence level. This same info is shown in graphical form below.

BetDiffNom Number_of_Bets Total_Bet_Result
0.05 46 1099
0.06 63 -1216
0.07 45 694
0.08 36 618
0.09 34 -115
0.10 24 -1022
0.11 14 24
0.12 11 1071
0.13 2 -200
0.14 3 -300
0.17 2 544

Lets take a look at a few of those biggest disagreements (model vs market):

GameID HomeTeam AwayTeam HomePred AwayPred HomeOdds AwayOdds BetTeam BetDiff
2021020270 Arizona Coyotes Detroit Red Wings 0.5874 0.4126 0.4137 0.6263 Arizona Coyotes 0.1738
2021021287 Dallas Stars Arizona Coyotes 0.6314 0.3686 0.8413 0.1987 Arizona Coyotes 0.1700
2021020667 Detroit Red Wings Buffalo Sabres 0.4971 0.5029 0.6801 0.3599 Buffalo Sabres 0.1430
2021020999 San Jose Sharks Arizona Coyotes 0.5272 0.4728 0.7095 0.3305 Arizona Coyotes 0.1423
2021020814 Arizona Coyotes Los Angeles Kings 0.4427 0.5573 0.3060 0.7340 Arizona Coyotes 0.1367
2021021230 Arizona Coyotes Chicago Blackhawks 0.5280 0.4720 0.3956 0.6444 Arizona Coyotes 0.1324
2021020137 Philadelphia Flyers Arizona Coyotes 0.5631 0.4369 0.7302 0.3098 Arizona Coyotes 0.1271
2021020908 St. Louis Blues Ottawa Senators 0.6219 0.3781 0.7858 0.2542 Ottawa Senators 0.1239
2021020607 Arizona Coyotes Chicago Blackhawks 0.5374 0.4626 0.4137 0.6263 Arizona Coyotes 0.1237
2021020844 Arizona Coyotes Winnipeg Jets 0.4578 0.5422 0.3350 0.7050 Arizona Coyotes 0.1227

Plots

Plot a few things!

Plot of bet results as the season progress (Click to expand)

Total season bet results:

Bet Results by Team (Click to expand)

Bet Results by Team. The total bet results by team are listed above as well.

Win/Loss by Confidence Level (Click to expand)

Check if there’s a bias in win/loss by confidence level. This same info is shown in tabular form above.

Last Seasons Bet results

Click to Expand

Using the model outputs from last year, run through the same code, we get the following results:

## Log Loss: 0.65173
## Accuracy: 62.96%
## AUC: 0.6627
HomeBets 484.00
AwayBets 424.00
HomeBetResults -233.00
AwayBetResults 1340.00
HomeUnits -0.48
AwayUnits 3.16
TotalBets 669.00
TotalResults 1107.00
TotalUnits 1.22

Total season bet results:

Totals/xG Model

Model performance

This doesn’t mean as much because we’re looking for totals, but here’s the model performance for win/loss. Naturally, a xG model would be expected to have reasonable W/L performance as a byproduct of being good at predicting goal performance.

## Log Loss: 0.66601
## Accuracy: 58.46%
## AUC: 0.6457

In addition, the model performance for total xG vs. G (this is the important part):

## Test R2: 0.0121
## Test RMSE: 2.35

We trained the model using RMSE as the optimized metric.

Bet Results

Setting up bet results of over/under bets placed with a difference in 0.5 xG:

OverBets 44.00
UnderBets 82.00
OverBetResults 88.00
UnderBetResults 198.00
OverUnits 2.00
UnderUnits 2.41
TotalBets 126.00
TotalResults 286.00
TotalUnits 2.27

Optimization

This feels like it could be improved - very good performance to betting overs, but poor performance with unders. The betdiff of 0.5 xG was just a random number.

We’ll tune the over/under cutoffs by using the training data (2017-2018 to 2020-2021), and then use that to determine what we would have expected to get from 2021-2022

Click to view code!

optresults<-expand.grid(
  "over"=c(0.5, 0.6, 0.7, 0.8, 0.9, 1),
  "under"=c(0.1, 0.2, 0.3, 0.4, 0.5)
  )
optresults$TotalResults<-NA_real_
optresults$TotalUnits<-NA_real_
optresults$NumBets<-NA_integer_
optresults$Units_2122<-NA_real_
optresults$Results_2122<-NA_real_
optresults$NumBets_2122<-NA_real_

for(i in 1:nrow(optresults)){
  b<-HockeyModel:::compare_market_line_xg(predictions_xg$train, overbetdiff = optresults[i,]$over, underbetdiff = optresults[i,]$under, juice = juice)
  optresults[i,]$TotalResults<-b$TotalResults
  optresults[i,]$TotalUnits<-round(b$TotalUnits, 2)
  optresults[i,]$NumBets<-b$TotalBets
  b<-HockeyModel:::compare_market_line_xg(predictions_xg$test, overbetdiff=optresults[i,]$over, underbetdiff = optresults[i,]$under, juice=juice)
  optresults[i,]$Results_2122<-b$TotalResults
  optresults[i,]$Units_2122<-round(b$TotalUnits,2)
  optresults[i,]$NumBets_2122<-b$TotalBets
}

Our best results come from betting overs if we differ by 0.8 and betting unders by differing by 0.3, In doing so, we got final results of $8502 (or 14.97 units on 568 bets). Remember that this was a 4 season performance (a total of 4877 games) so these values are picked to ‘on average’ produce those results across a long period of time.

Using those parameters, we get a result of $-2175, or -9.62 units for the 2021-2022 season.

The top 20 mixes of over/under bet (sorted on Total profit on 2017-2021) are shown below, as are the results of those parameters applied to the 2021-2022 season.

over under TotalResults TotalUnits NumBets Units_2122 Results_2122 NumBets_2122
0.8 0.3 8502 14.97 568 -9.62 -2175 226
0.6 0.3 8298 10.73 773 -6.84 -1676 245
0.9 0.3 7933 14.91 532 -9.62 -2175 226
0.7 0.3 7792 12.35 631 -8.39 -1964 234
0.8 0.1 7639 6.14 1245 -11.07 -4241 383
0.5 0.3 7474 7.36 1015 -7.73 -2087 270
0.6 0.1 7435 5.13 1450 -9.31 -3742 402
1.0 0.3 7184 13.90 517 -9.62 -2175 226
0.9 0.1 7070 5.85 1209 -11.07 -4241 383
0.7 0.1 6929 5.30 1308 -10.31 -4030 391
0.5 0.1 6611 3.91 1692 -9.73 -4153 427
0.8 0.2 6326 7.37 858 -12.29 -3700 301
1.0 0.1 6321 5.29 1194 -11.07 -4241 383
0.6 0.2 6122 5.76 1063 -10.00 -3201 320
0.9 0.2 5757 7.00 822 -12.29 -3700 301
0.7 0.2 5616 6.10 921 -11.29 -3489 309
0.5 0.2 5298 4.06 1305 -10.47 -3612 345
1.0 0.2 5008 6.21 807 -12.29 -3700 301
0.8 0.4 4597 13.17 349 -2.81 -424 151
0.6 0.4 4393 7.93 554 0.44 75 170

All that’s left is to decide how many bets/season you’re looking for, and optimize for that with total performance taken into consideration.

We’ll look at over/under of 0.8/0.3 xG to direct our bets from now on.

OverBets 8.00
UnderBets 226.00
OverBetResults 211.00
UnderBetResults -2175.00
OverUnits 26.38
UnderUnits -9.62
TotalBets 234.00
TotalResults -1964.00
TotalUnits -8.39

Determining the Market xG

There are multiple methods of determining the market’s xG value. This is a possible opportunity to enhance the model performance - if you can get an edge on the market here, it can make or break a model’s performance.

The market data provided contains a determined market xG using the one listed above. An alternative method could be considered using Poisson fitting. Testing the market with this to see if they’re different.

OverBets 37.00
UnderBets 111.00
OverBetResults 601.00
UnderBetResults 609.00
OverUnits 16.24
UnderUnits 5.49
TotalBets 148.00
TotalResults 1210.00
TotalUnits 8.18

Digging into the differences a bit further, we’ll plot the correlation between the supplied market xG and the poisson determined xG:

## Warning: Removed 94 rows containing missing values (geom_point).
## Warning: Removed 94 rows containing non-finite values (stat_bin).

We can dig further into each method of determination by plotting the histogram of each xG implied method:

## Warning: Removed 94 rows containing non-finite values (stat_bin).

Lets look at the difference between our suspected xG and see what we have as a cause for it. Remember from above that most differences are <0.5 xG value.

## Warning: Removed 94 rows containing missing values (geom_point).

Lets look at the highest diff values to see if a tabular form helps us understand.

GameID Totals OverOdds UnderOdds ImpliedxG ImpliedxGPoisson ImpliedDiff
2021020883 6.0 -135 -118 6.432090 5.552015 0.8800752
2021020504 6.0 -125 -133 6.293083 5.413719 0.8793640
2021020726 6.5 -138 -110 6.971515 6.184691 0.7868235
2021020934 5.5 -139 -110 5.984436 5.209304 0.7751323
2021020649 6.0 -133 -105 6.405244 5.828398 0.5768452
2021020511 6.5 -125 -111 6.793083 6.239732 0.5533509
2021020626 6.0 -118 -118 6.188190 5.652752 0.5354379
2021021023 6.0 -118 -118 6.188190 5.652752 0.5354379
2021020998 6.0 -139 102 6.484436 5.952844 0.5315921
2021020767 6.0 -118 -115 6.188190 5.711087 0.4771035

It looks like a pretty large juice on these - that might explain the discrepancy. It also looks like these all happened in the last half of the most recent season, despite us comparing 9 season’s worth of games.

Now that we know there’s a correlation, but meaningful difference between xG methods, let’s optimize the xGPoisson betting cutoffs. This has the same format as above, so…
Click to expand!

Our best results come from betting overs if we differ by 0.8 and betting unders by differing by 0.3, In doing so, we got final results of $8003 (or 13.82 units on 579 bets).

Using those parameters, we get a result of $1210, or 8.18 units for the 2021-2022 season.

The top 20 mixes of over/under bet (sorted on Total profit on 2017-2021) are shown below, as are the results of those parameters applied to the 2021-2022 season.

over under TotalResults TotalUnits NumBets Units_2122 Results_2122 NumBets_2122
0.8 0.3 8003 13.82 579 8.18 1210 148
0.9 0.3 7823 14.65 534 7.55 1012 134
0.8 0.1 7230 5.62 1287 -2.20 -635 288
0.8 0.2 7214 8.09 892 3.10 673 217
0.6 0.3 7059 8.17 864 5.53 1245 225
0.9 0.1 7050 5.68 1242 -3.04 -833 274
0.9 0.2 7034 8.30 847 2.34 475 203
1.0 0.3 6928 13.50 513 4.70 602 128
0.7 0.3 6776 10.07 673 3.00 537 179
0.6 0.1 6286 4.00 1572 -1.64 -600 365
0.6 0.2 6270 5.33 1177 2.41 708 294
1.0 0.1 6155 5.04 1221 -4.64 -1243 268
1.0 0.2 6139 7.43 826 0.33 65 197
0.5 0.3 6085 5.46 1114 2.03 599 295
0.7 0.1 6003 4.35 1381 -4.10 -1308 319
0.7 0.2 5987 6.07 986 0.00 0 248
0.5 0.1 5312 2.92 1822 -2.86 -1246 435
0.5 0.2 5296 3.71 1427 0.17 62 364
0.8 0.4 3157 8.77 360 19.75 2034 103
0.9 0.4 2977 9.45 315 20.63 1836 89

We’re likely happiest picking over/under cutoffs of (again) 0.8/0.3, this leaves us with the following performance for 2021-2022:

OverBets 37.00
UnderBets 111.00
OverBetResults 601.00
UnderBetResults 609.00
OverUnits 16.24
UnderUnits 5.49
TotalBets 148.00
TotalResults 1210.00
TotalUnits 8.18