Skip to content

Instantly share code, notes, and snippets.

@seanjtaylor
Created September 8, 2016 15:26
Show Gist options
  • Save seanjtaylor/aac755c28260baad60d38645b0d0cc4d to your computer and use it in GitHub Desktop.
Save seanjtaylor/aac755c28260baad60d38645b0d0cc4d to your computer and use it in GitHub Desktop.
Analysis of Season Win O/Us
library(rvest)
library(stringr)
library(dplyr)
library(ggplot2)
library(tidyr)
min.fun <- function(p, thresh.prob = NULL, thresh = NULL) {
(thresh.prob - pbinom(thresh, 16, p))^2
}
fit.binomial <- function(thresh.prob, thresh) {
o <- optimize(min.fun, interval = c(0, 1), thresh.prob = thresh.prob, thresh = thresh)
o$minimum
}
page <- read_html('https://www.sportsbook.ag/sbk/sportsbook4/nfl-betting/nfl-season-wins.sbk')
teams <- page %>%
html_nodes('span.team') %>%
html_text()
## Convert gambling odds into probabilities
df <- page %>%
html_nodes('div.market') %>%
{data_frame(txtline = html_text(.), team = rep(teams, each = 2))} %>%
mutate(bet = str_extract(txtline, '[OU]'),
games = as.numeric(str_replace(str_extract(txtline, '\\d{1,2}(\\.\\d)?\\('), '\\(', '')),
line = as.numeric(str_extract(txtline, '[-+]\\d{3}')),
line = ifelse(is.na(line), 100, line)) %>%
mutate(prob = ifelse(line < 0,
abs(line) / (abs(line) + 100),
100 / (line + 100)))
## The Under prob is equivalent to
## P(wins < K) == P(wins <= K-1)
## P(wins < 8.5) == P(wins <= 8)
## P(wins < 8) == P(wins <= 7)
## The Over prob is equivalent to
## P(wins > K) == 1 - P(wins <= K)
## P(wins > 8) == 1 - P(wins <= 8)
## P(wins > 8.5) == 1 - P({wins <= 8)
df2 <- df %>%
group_by(team, bet, txtline, line, games) %>% do({
if(.$bet == 'U') {
gwp <- fit.binomial(.$prob, floor(.$games - 0.5))
} else {
gwp <- fit.binomial(1 - .$prob, floor(.$games))
}
data_frame(gwp = gwp)
})
df2 %>%
ungroup %>%
select(team, bet, games, gwp) %>%
spread(bet, gwp) %>%
## Average the O and U implied probs
mutate(expected.wins.over = 16 * O,
expected.wins.under = 16 * U,
expected.wins = 8 * (O + U)) %>%
select(team, expected.wins, ou.games = games) %>%
ggplot(aes(x = reorder(team, expected.wins), y = expected.wins)) +
geom_point() +
geom_point(aes(y = ou.games), shape = '+') +
geom_text(aes(label = format(expected.wins, digits = 2, nsmall = 1), y = 4.7), hjust = 'right') +
coord_flip() +
theme_bw() +
theme(legend.position = 'bottom') +
scale_y_continuous(breaks = 4:11) +
xlab('Team') +
ylab('Implied Number of Wins Implied by Odds')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment