Open Side Menu Go to the Top
Register
Sportbetting Probability Question Sportbetting Probability Question

05-19-2021 , 05:55 PM
Suppose you made 1000 sports bets on Moneyline (straight bets), and you had 500 underdogs and 500 favorites. Let's say the average underdog is +115 and the average fave is -120.

Breakeven for +115 games is .465% and b/e of -120 is .545%
Combined these would be .505%

Each baseball outcome is independent from the group of course. If you picked say, 51% of games correctly, would you always have a profit?
Sportbetting Probability Question Quote
05-19-2021 , 10:07 PM
Running a simulation per your description several times, it looks like you could expect to have a profitable season (assuming "1 season" = 1,000 bets) roughly 60% of the time. Under the same conditions, you'd have to pick games correctly at a rate of 53.05% to have a profitable season roughly 95% of the time.

Here's the quick and dirty Python script I wrote to run the simulation, if you want to play with it:

Code:
import numpy as np

def simulate_season_wagering(underdog_odds, favorite_odds, n_bets, win_pct):
    """This function simulates a season of wagering, risking $100 on underdogs, and risking to win $100 on favorites."""
    underdog_pl = 0 # profit & loss betting underdogs
    favorite_pl = 0 # profit & loss betting favorites
    n_bets_split = int(n_bets/2) # bet half underdogs, half favorites
    # draw size=n random samples from a binomial distribution with a success rate of win_pct
    # 1 is a winning bet, 0 is a losing bet
    dog_bets = np.random.binomial(n=1, p=win_pct, size=n_bets_split)
    fave_bets = np.random.binomial(n=1, p=win_pct, size=n_bets_split)
    #tally up the profit and loss for the simulated season of wagers
    for i in range(n_bets_split):
            if dog_bets[i] == 0:
                underdog_pl -= 100
            else:
                underdog_pl += underdog_odds

            if fave_bets[i] == 0:
                favorite_pl += favorite_odds
            else:
                favorite_pl += 100
    return underdog_pl, favorite_pl

bets_per_season = 1000
seasons = 100
dog_odds = 115
fave_odds = -120
win_rate = 0.51
dog_pl = 0 # profit and loss of betting underdogdogs
fave_pl = 0 # profit and loss of betting favorites
season_pl = list() # combined PnL for underdog and favorite bets per each season
winning_seasons = 0

for i in range(seasons):
    dog_pl, fave_pl = simulate_season_wagering(underdog_odds=dog_odds,favorite_odds=fave_odds,
                                               n_bets=bets_per_season,win_pct=win_rate)
    season_wagering_results = dog_pl + fave_pl
    season_pl.append(season_wagering_results)
    if season_wagering_results > 0:
        winning_seasons += 1

print(f'Over {seasons} simulated seasons where you picked winners at a rate of {win_rate*100:.2f}%,\
 wagering was profitable {winning_seasons/seasons*100:.2f}% of the time')
Sportbetting Probability Question Quote
05-20-2021 , 03:33 AM
Hey that's pretty cool!

Currently my 'real' bets are 30 underdogs with a breakeven of .455 and 150 faves at a breakeven of .574

Is there a way for me to adjust this code to weight these two types of bets and still get a reliable number?
Sportbetting Probability Question Quote
05-20-2021 , 01:10 PM
A quick idea is to add the argument 'fave_ratio' to the simulate_season_wagering function's inputs. So if you wanted to simulate wagering on 700 favorites out of 1000 bets, set fave_ratio=0.70. Then instead of the line 'n_bets_split=...', add
n_fave = int(n_bets*fave_ratio)
n_dog = n_bets - n_fave
and then replace the other lines that used n_bets_split as input with n_fave or n_dog. Would also need to make separate For loops inside simulate_season_wagering with ranges of n_fave and n_dog so you don't get an 'index out of range' error. You probably already noticed that you can adjust the break even odds directly by changing the variables 'dog_odds' and 'fave_odds'.

But yeah, I think you asked a really good question, if you don't mind please share any further insights you come across while exploring the idea.
Sportbetting Probability Question Quote
05-20-2021 , 03:10 PM
I tried those steps, but I am definitely a noob when it comes to Python. Anything aside from running a script someone else wrote is out of my element!
Sportbetting Probability Question Quote
05-21-2021 , 01:28 AM
Thinking more about the simulation method, I'm curious how it would change the forecasts if you could also set different average win rates for the bets on +odds and -odds. I should have a few minutes in the morning to update the script and re-post it here.
Sportbetting Probability Question Quote
05-21-2021 , 02:06 PM
Quote:
Originally Posted by VeniceMerchant
Currently my 'real' bets are 30 underdogs with a breakeven of .455 and 150 faves at a breakeven of .574
I updated the script so that by default, it runs a simulation reflecting your real numbers, but with 1,000 simulated bets per season and assuming your probability of picking a winner when betting dogs or favorites is 0.005 greater than their respective breakeven rates.

First, here is the code to import the numerical module and define the simulator:
Code:
# import numpy module and define simulator
import numpy as np

def simulate_season_wagering(dog_be_odds=120,fav_be_odds=-135,win_p_dog=0.46,win_p_fav=0.579,n_bets=1000,fav_ratio=0.83):
    """
        This function simulates a season of wagering, risking $100 on underdogs, and risking to win $100 on favorites.
        dog_be_odds = breakeven rate for betting underdogs, expressed in American odds
        fav_be_odds = breakeven rate for betting favorites, expressed in American odds
        win_p_dog = the probabilitiy of success when betting on an underdog
        win_p_fav = the probability of success when betting on a favorite
        n_bets = the number of bets in a season
        fav_ratio = the ratio of favorite to underdog bets
    """
    underdog_pl = 0 # profit & loss betting underdogs
    favorite_pl = 0 # profit & loss betting favorites
    n_fav = int(n_bets*fav_ratio)
    n_dog = n_bets - n_fav
    # draw n random samples from a binomial distribution with probability of success = win_p_dog or win_p_fav
    # 1 is a winning bet, 0 is a losing bet
    dog_bets = np.random.binomial(n=1, p=win_p_dog, size=n_dog)
    fave_bets = np.random.binomial(n=1, p=win_p_fav, size=n_fav)
    #tally up the profit and loss for the simulated season of wagers
    for i in range(n_dog):
            if dog_bets[i] == 0:
                underdog_pl -= 100
            else:
                underdog_pl += dog_be_odds
    for i in range(n_fav):
            if fave_bets[i] == 0:
                favorite_pl += fav_be_odds
            else:
                favorite_pl += 100
                
    return underdog_pl, favorite_pl
Here is the code you can use to run a default simulation:
Code:
# run default simulation
epochs = 10
seasons = 100
epoch_win_pct = list() # hold the percentage of profitable seasons per epoch in a list
for i in range(epochs):
    dog_pl = 0 # profit and loss of betting underdogdogs
    fav_pl = 0 # profit and loss of betting favorites
    winning_seasons = 0
    for j in range(seasons):
        dog_pl, fav_pl = simulate_season_wagering()
        season_wagering_results = dog_pl + fav_pl
        if season_wagering_results > 0:
            winning_seasons += 1
    epoch_win_pct.append(winning_seasons/seasons)
    
epoch_win_pct = np.array(epoch_win_pct)
print(f'Over {epochs} epochs containing {seasons} simulated seasons each,\
 a profitable season occurred an average of {epoch_win_pct.mean()*100:.2f}% of the time.')
Which on a typical run prints out something like "Over 10 epochs containing 100 simulated seasons each, a profitable season occurred an average of 60.90% of the time."

Say you want to customize the simulation run by just changing the probability of a success when betting dogs and faves to be 0.01 and 0.02 better than their respective breakeven rates, here is a code example:
Code:
win_p_dog = 0.455 + 0.01
win_p_fav = 0.574 + 0.02

epochs = 10
seasons = 100
epoch_win_pct = list() # hold the percentage of profitable seasons per epoch in a list
for i in range(epochs):
    dog_pl = 0 # profit and loss of betting underdogdogs
    fav_pl = 0 # profit and loss of betting favorites
    winning_seasons = 0
    for j in range(seasons):
        dog_pl, fav_pl = simulate_season_wagering(win_p_dog=win_p_dog,win_p_fav=win_p_fav)
        season_wagering_results = dog_pl + fav_pl
        if season_wagering_results > 0:
            winning_seasons += 1
    epoch_win_pct.append(winning_seasons/seasons)
    
epoch_win_pct = np.array(epoch_win_pct)
print(f'Over {epochs} epochs containing {seasons} simulated seasons each,\
 a profitable season occurred an average of {epoch_win_pct.mean()*100:.2f}% of the time.')
Which will print something like "Over 10 epochs containing 100 simulated seasons each, a profitable season occurred an average of 88.70% of the time."

The likelihood of having a profitable season drops to around 50% when setting the probability of making a successful bet equal to the breakeven rate, and drops to around 25% when setting the probability of a successful bet to 0.01 less than the breakeven rate.
Sportbetting Probability Question Quote
05-21-2021 , 02:59 PM
Ok, it's saying simulate_season_wagering is not defined

Quote:
# run default simulation
epochs = 10
seasons = 100
epoch_win_pct = list() # hold the percentage of profitable seasons per epoch in a list
for i in range(epochs):
dog_pl = 30 # profit and loss of betting underdogdogs
fav_pl = 150 # profit and loss of betting favorites
winning_seasons = 0
for j in range(seasons):
dog_pl, fav_pl = simulate_season_wagering()
season_wagering_results = dog_pl + fav_pl
if season_wagering_results > 180:
winning_seasons += 1
epoch_win_pct.append(winning_seasons/seasons)

epoch_win_pct = np.array(epoch_win_pct)
print(f'Over {epochs} epochs containing {seasons} simulated seasons each,\
a profitable season occurred an average of {epoch_win_pct.mean()*100:.2f}% of the time.')
Did I plug the values in wrong? Do you put the cash value in the dog_pl and fav_pl or the win-loss?
Sportbetting Probability Question Quote
05-21-2021 , 03:19 PM
Sorry I didn't make that clear, you gotta run the code block with the "import" and "def" statements first, so putting it all together for a default run would look like this:

Code:
# import numpy module and define simulator
import numpy as np

def simulate_season_wagering(dog_be_odds=120,fav_be_odds=-135,win_p_dog=0.46,win_p_fav=0.579,n_bets=1000,fav_ratio=0.83):
    """
        This function simulates a season of wagering, risking $100 on underdogs, and risking to win $100 on favorites.
        dog_be_odds = breakeven rate for betting underdogs, expressed in American odds
        fav_be_odds = breakeven rate for betting favorites, expressed in American odds
        win_p_dog = the probabilitiy of success when betting on an underdog
        win_p_fav = the probability of success when betting on a favorite
        n_bets = the number of bets in a season
        fav_ratio = the ratio of favorite to underdog bets
    """
    underdog_pl = 0 # profit & loss betting underdogs
    favorite_pl = 0 # profit & loss betting favorites
    n_fav = int(n_bets*fav_ratio)
    n_dog = n_bets - n_fav
    # draw n random samples from a binomial distribution with probability of success = win_p_dog or win_p_fav
    # 1 is a winning bet, 0 is a losing bet
    dog_bets = np.random.binomial(n=1, p=win_p_dog, size=n_dog)
    fave_bets = np.random.binomial(n=1, p=win_p_fav, size=n_fav)
    #tally up the profit and loss for the simulated season of wagers
    for i in range(n_dog):
            if dog_bets[i] == 0:
                underdog_pl -= 100
            else:
                underdog_pl += dog_be_odds
    for i in range(n_fav):
            if fave_bets[i] == 0:
                favorite_pl += fav_be_odds
            else:
                favorite_pl += 100
                
    return underdog_pl, favorite_pl

# run default simulation
epochs = 10
seasons = 100
epoch_win_pct = list() # hold the percentage of profitable seasons per epoch in a list
for i in range(epochs):
    dog_pl = 0 # profit and loss of betting underdogdogs
    fav_pl = 0 # profit and loss of betting favorites
    winning_seasons = 0
    for j in range(seasons):
        dog_pl, fav_pl = simulate_season_wagering()
        season_wagering_results = dog_pl + fav_pl
        if season_wagering_results > 0:
            winning_seasons += 1
    epoch_win_pct.append(winning_seasons/seasons)
    
epoch_win_pct = np.array(epoch_win_pct)
print(f'Over {epochs} epochs containing {seasons} simulated seasons each,\
 a profitable season occurred an average of {epoch_win_pct.mean()*100:.2f}% of the time.')
Sportbetting Probability Question Quote
05-21-2021 , 07:24 PM
This is amazing! Thanks a ton

So, here's my results for my current sample so far:

Over 10 epochs containing 100 simulated seasons each, a profitable season occurred an average of 92.40% of the time.

My gut was to wait until 500 bets before increasing my bet size to ensure that I have enough data to continue. Is this something where 99% is achievable? Or is there always going to be some amount of variability that I have to live with?
Sportbetting Probability Question Quote
05-22-2021 , 12:43 AM
Glad to hear the simulator was useful.

Due to the effect of sample size error, you'll always have to live with some variability. The simulator assumes the probability of winning a bet that the user inputs is perfectly accurate, but in reality we can't know that win rate with perfect accuracy because of sample size error.

For example, assume a winning bet is counted as a 1, and a losing bet is counted as a 0, and over 100 bets you had 55 wins and 45 losses for a win rate of 55%. Using that vector of 55 1's and 45 0's, if you calculate the mean and standard deviation, and then use those statistics to generate a 95% confidence interval around the observed 55% win rate, you'll see that the true win rate could be anywhere between 45.25% and 64.75%.

Here's a python script to check that:
Code:
import numpy as np
sample_size = 100
win_rate = 0.55
win_count = int(sample_size*win_rate)
loss_count = sample_size - win_count
wins = np.ones(win_count, dtype=int)
losses = np.zeros(loss_count, dtype=int)
results = np.append(wins, losses)
moe = 1.96*(results.std()/np.sqrt(sample_size)) # margin of error, calculated with z=1.96 for a 95% confidence interval
ci_lb = win_rate - moe # 95% confidence interval lower bound
ci_ub = win_rate + moe # 95% confidence interval upper bound
print(f'for n={sample_size} and a win rate of {results.mean():.4f}, the 95% confidence interval lower bound={ci_lb:.4f} and the upper bound={ci_ub:.4f}')
If you play with the "sample_size" variable you'll see that doubling the sample size does decrease the range of the 95% confidence interval, but not as much as one might expect. For example, here is what that script spit out for n of 200, 500, and 1000 respectively:
"for n=200 and a win rate of 0.5500, the 95% confidence interval lower bound=0.4811 and the upper bound=0.6189"
"for n=500 and a win rate of 0.5500, the 95% confidence interval lower bound=0.5064 and the upper bound=0.5936"
"for n=1000 and a win rate of 0.5500, the 95% confidence interval lower bound=0.5192 and the upper bound=0.5808"
Sportbetting Probability Question Quote
05-22-2021 , 02:26 AM
Yeah, I guess there's always going to be an element of risk for anything predictive like this. It's nice to finally have a way to quantify that my +EV live results are in line with the model.

Thanks for all your help man
Sportbetting Probability Question Quote
05-22-2021 , 11:32 AM
For sure man rock on.
Sportbetting Probability Question Quote
06-24-2021 , 06:08 PM
Would this be applicable to any sport or just baseball? I've been looking into predicting soccer matches using various scripts and tools similar to yours. But none of it feels right. Yours looks pretty legit, tho.

Last edited by MaxDrogo112; 06-24-2021 at 06:34 PM.
Sportbetting Probability Question Quote
06-24-2021 , 08:41 PM
It's applicable to any sport, as I wrote the simulation scripts assuming the original question was entirely about betting moneylines (rather than modeling a specific sport.)

As for predicting soccer match outcomes, in the Sports Betting forum there is a soccer betting thread if you wanted to bounce sport specific questions around. Also plenty of discussion on statistical/computer modeling in the Crowdsource Syndicate Sports Betting thread.
Sportbetting Probability Question Quote

      
m