Open Side Menu Go to the Top
Register
Series Price Calculation Series Price Calculation

06-02-2019 , 06:49 PM
Thank you in advance for the help. Couldn't find this by searching here and elsewhere.

Let's say a team is down in a 7-game playoff series 2 games to 1. How do you calculate their odds to win the series, given you are able to input what you believe will be their odds of winning each remaining (as necessary) game? It's hard to just use a parlay calculator because I don't know how to factor in the times where the team loses some of their remaining games but still wins the series. Is there a calculator online for this?
Series Price Calculation Quote
06-02-2019 , 08:22 PM
Let:
P(win at home) = p
P(win on road) = r

They'll have potentially 2 more home games in alternating order. The series probability is the same whether it's HRHR or RHRH. Pick either one and add the probability of each possible way of winning.

P(win series) = rp² + 2(1-p)pr² + (1-r)rp²
= 2(rp² + pr²) - 3p²r²

A transition matrix would also work. Rather than needing 7 different formulas, you'd only need one matrix. I'll show that method if you want.
Series Price Calculation Quote
06-03-2019 , 12:01 PM
Let's say the moneylines are different for each game? And for example it's the current NBA finals where it goes HHRRRHH (2-3-2) where the higher seeded team gets the first at last 2 games at home. (if necessary of course) How can I plug in what I think will be a team's moneyline for each individual game. Especially if I think it will be a different number. For example this NBA series, it is predicted that one of Golden State's best players will be returning from injury in a game or two. I really appreciate your help!
Series Price Calculation Quote
06-03-2019 , 03:29 PM
Quote:
Originally Posted by me
Rather than needing 7 different formulas
Correction: you'd need 15 formulas, though 6 would have a symmetrical counterpart with the variables flipped.

Quote:
Originally Posted by trup_qq
And for example it's the current NBA finals where it goes HHRRRHH (2-3-2)
The finals is 2-2-1-1-1 as of 2014. See for instance 2017, where Game 5 was @GS. And it hasn't changed in 2019 according to this link: https://bleacherreport.com/articles/...tions-and-more

Quote:
How can I plug in what I think will be a team's moneyline for each individual game. Especially if I think it will be a different number.
This makes for 7 variables, so now the matrix method seems preferable. I went ahead and coded it in Julia:

Code:
function seriesprob(h::Vector{Float64}, p::Vector{Float64}, score::Vector{Int64})
    (length(h)≠4 || length(p)≠3 || length(score)≠2) && error("vector lengths should be 4,3,2")
    score[1]==3 && score[1]==3 && return h[4], 1-h[4]
    score[1]==4 && return 1,0
    score[2]==4 && return 0,1
    x = 7 - (score[1] + score[2])
    r = ones(Float64,4)-h
    q = ones(Float64,3)-p
    T = zeros(Float64, 18,18)
    T[1:9, 1] = [1.0, 0.0, h[4], 0.0, 0.0, 0.0, q[3], h[3], q[2]]
    T[2:6, 2] = [1.0, r[4], p[3], r[3], p[2]]
    T[4,3] = q[3]
    T[7,3] = p[3]
    T[5,4] = h[3]
    T[10,4] = r[3]
    T[6,5] = q[2]
    T[11,5] = p[2]
    T[12,6] = p[1]
    T[8:10, 7] = [r[3], 0.0, h[3]]
    T[9,8] = p[2]
    T[13,8] = q[2]
    T[14,9] = q[1]
    T[11:13, 10] = [q[2], 0.0, p[2]]
    T[12,11] = q[1]
    T[15,11] = p[1]
    T[16,12] = r[2]
    T[14:15, 13] = [p[1], q[1]]
    T[17,14] = h[2]
    T[16:17, 15] = [h[2], r[2]]
    T[18,16] = r[1]
    T[18,17] = h[1]
    score[1]==2 && score[2]==3 && return (T^x)[4, 1:2]
    score[1]==1 && score[2]==3 && return (T^x)[5, 1:2]
    score[1]==0 && score[2]==3 && return (T^x)[6, 1:2]
    score[1]==3 && score[2]==2 && return (T^x)[7, 1:2]
    score[1]==3 && score[2]==1 && return (T^x)[8, 1:2]
    score[1]==3 && score[2]==0 && return (T^x)[9, 1:2]
    score[1]==2 && score[2]==2 && return (T^x)[10, 1:2]
    score[1]==1 && score[2]==2 && return (T^x)[11, 1:2]
    score[1]==0 && score[2]==2 && return (T^x)[12, 1:2]
    score[1]==2 && score[2]==1 && return (T^x)[13, 1:2]
    score[1]==2 && score[2]==0 && return (T^x)[14, 1:2]
    score[1]==1 && score[2]==1 && return (T^x)[15, 1:2]
    score[1]==0 && score[2]==1 && return (T^x)[16, 1:2]
    score[1]==1 && score[2]==0 && return (T^x)[17, 1:2]
    return (T^x)[18, 1:2]
end
Let h = P(higher seed wins a home game)
Let p = P(lower seed wins a home game)

The function's parameters are three vectors:
[h1, h2, h3, h4]
[p1, p2, p3]
[score1, score2] where score1 is the higher seed's score

Example: seriesprob([1.0, 1.0, .55, .5], [1.0, .6, .65], [2, 1])

If you're starting at Game 4 like above, then the higher seed's first 2 home probabilities won't affect the answer, nor will the lower seed's first home probability, so you can set them to 1.0 (or 1, but that's a few microseconds slower).

If the probabilities won't change, then instead of typing [.65, .65, .65, .65] you can type fill(.65, 4)

If you'd rather not install Julia, you can run the code here: https://tio.run/#julia1x

Paste the function, then on the next line paste
Code:
println(seriesprob(...))
and replace ... with your parameters.

If you install Julia and run the code in the Julia console, you don't need the println(), just seriesprice(...)

The output is P(higher seed wins) followed by P(lower seed wins).

I checked it against my formula for a 2-1 score and the answer matches.
Series Price Calculation Quote
06-03-2019 , 04:12 PM
Wow! I'm really grateful for your help. I always wanted to learn programming but didn't really have something to use/practice it on so kind of stayed away. Do you recommend a particular language for sports database work? I'm assuming excel vba is probably the first step..
Series Price Calculation Quote
06-03-2019 , 05:51 PM
Or to better phrase that question: How do I figure out how I could go about doing what you just did? I have questions such as where in the code it accounts for the sequential order of the home games (thank you for correcting me on NBA finals home locations btw) and how it all works, but I'd love to be able to have half a clue what I'm looking at before just asking you for all the answers. I suppose the first step is understanding the math and then at that point, knowing how to program said math problem. Thanks again.
Series Price Calculation Quote
06-03-2019 , 11:12 PM
I haven't worked with databases. R and Python are popular choices for data, but Julia is newer and faster with less effort so I bet it's a good choice too (and I'm guessing all 3 are better than VBA, but mine isn't a very educated guess). There is the JuliaDB package which lets you work with tables similar to SQL. Here's the JuliaDB documentation on loading CSV data.

It occurs to me that you might want the probabilities of each final series score, since there are odds listed on that as well as series spreads.

For that, I'll need to resize the matrix to 24x24 and move some entries around, which I'll do tomorrow.
Series Price Calculation Quote
06-04-2019 , 04:37 AM
Here it is:

Code:
import LinearAlgebra.I
function seriesprob(h::Vector{Float64}, p::Vector{Float64}, score1::Int64, score2::Int64)
    (length(h)≠4 || length(p)≠3) && error("vector lengths should be 4 and 3")
    score1==3 && score1==3 && return h[4], 1-h[4]
    score1==4 && return 1,0
    score2==4 && return 0,1
    x = 7 - (score1 + score2)
    r = ones(Float64,4)-h
    q = ones(Float64,3)-p
    T = zeros(Float64, 24,24)
    T[1:8, 1:8] += I
    T[15,1] = q[2]
    T[14,2] = h[3]
    T[13,3] = q[3]
    T[9,4] = h[4]
    T[9,5] = r[4]
    T[10,6] = p[3]
    T[11,7] = r[3]
    T[12,8] = p[2]
    T[10,9] = q[3]
    T[13,9] = p[3]
    T[11,10] = h[3]
    T[16,10] = r[3]
    T[12,11] = q[2]
    T[17,11] = p[2]
    T[18,12] = p[1]
    T[14:16, 13] = [r[3], 0.0, h[3]]
    T[15,14] = p[2]
    T[19,14] = q[2]
    T[20,15] = q[1]
    T[17:19, 16] = [q[2], 0.0, p[2]]
    T[18,17] = q[1]
    T[21,17] = p[1]
    T[22,18] = r[2]
    T[20:21, 19] = [p[1], q[1]]
    T[23,20] = h[2]
    T[22:23, 21] = [h[2], r[2]]
    T[24,22] = r[1]
    T[24,23] = h[1]
    if score1==2 && score2==3 begin V = (T^x)[10, 1:8] end
    elseif score1==1 && score2==3 begin V = (T^x)[11, 1:8] end
    elseif score1==0 && score2==3 begin V = (T^x)[12, 1:8] end
    elseif score1==3 && score2==2 begin V = (T^x)[13, 1:8] end
    elseif score1==3 && score2==1 begin V = (T^x)[14, 1:8] end
    elseif score1==3 && score2==0 begin V = (T^x)[15, 1:8] end
    elseif score1==2 && score2==2 begin V = (T^x)[16, 1:8] end
    elseif score1==1 && score2==2 begin V = (T^x)[17, 1:8] end
    elseif score1==0 && score2==2 begin V = (T^x)[18, 1:8] end
    elseif score1==2 && score2==1 begin V = (T^x)[19, 1:8] end
    elseif score1==2 && score2==0 begin V = (T^x)[20, 1:8] end
    elseif score1==1 && score2==1 begin V = (T^x)[21, 1:8] end
    elseif score1==0 && score2==1 begin V = (T^x)[22, 1:8] end
    elseif score1==1 && score2==0 begin V = (T^x)[23, 1:8] end
    else V = (T^x)[24, 1:8] end
    println("Higher seed win = ",sum(V[1:4]))
    psum = sum(V[1:3])
    if psum>0
        println("Higher seed -1.5 = ",psum)
        psum = sum(V[1:2])
        psum>0 && begin println("Higher seed -2.5 = ",psum) end
    end
    println("Lower seed win = ",sum(V[5:8]))
    psum = sum(V[6:8])
    if psum>0
        println("Lower seed -1.5 = ",psum)
        psum = sum(V[7:8])
        psum>0 && begin println("Lower seed -2.5 = ",psum) end
    end
    return V
end
Note: score is no longer a vector.

Code:
julia> seriesprob(fill(.65,4), [.6, .6, .6], 0, 0)
Higher seed win = 0.5963782500000001
Higher seed -1.5 = 0.38675000000000004
Higher seed -2.5 = 0.24674000000000001
Lower seed win = 0.40362174999999995
Lower seed -1.5 = 0.290745
Lower seed -2.5 = 0.12200999999999998
8-element Array{Float64,1}:
 0.06760000000000001
 0.17914000000000002
 0.14001000000000002
 0.20962825000000002
 0.11287675
 0.168735
 0.07791
 0.04409999999999999
The array gives the probability of each score in order of:
4 - 0
...
4 - 3
3 - 4
...
0-4

Some of the probabilities have floating-point inaccuracy, so when you see 0000000x or 9999999x, that's not supposed to be there. The rounded answer is exact.

But with "print" (which is necessary in the browser), the format is horizontal and rounded:

Code:
julia> print(seriesprob(fill(.65,4), fill(.6,3), 0,0))
...
[0.0676, 0.17914, 0.14001, 0.209628, 0.112877, 0.168735, 0.07791, 0.0441]
Series Price Calculation Quote
06-04-2019 , 11:52 AM
Do you have to actually use the inequality sign? That seems ridiculous
Series Price Calculation Quote
06-04-2019 , 02:54 PM
No, you can also type !=
Series Price Calculation Quote
06-07-2019 , 01:16 PM
Quote:
Originally Posted by heehaww
I haven't worked with databases. R and Python are popular choices for data, but Julia is newer and faster with less effort so I bet it's a good choice too (and I'm guessing all 3 are better than VBA, but mine isn't a very educated guess). There is the JuliaDB package which lets you work with tables similar to SQL. Here's the JuliaDB documentation on loading CSV data.

It occurs to me that you might want the probabilities of each final series score, since there are odds listed on that as well as series spreads.

For that, I'll need to resize the matrix to 24x24 and move some entries around, which I'll do tomorrow.

Wow that's awesome! Thanks so much again.

It seems like Julia/programming could help with my next challenge which is figuring out how to find a breakeven amount on a 3 way (soccer) line when inputting the other 2 amounts using US moneyline odds. Or is this something where using European odds is much much easier?
Series Price Calculation Quote
06-08-2019 , 06:52 AM
American odds aren't a problem.

Here's a function that converts from American odds:

Code:
function oddsconvert(am::Int64, euro=false)
    abs(am)<100 && error("invalid American odds")
    am>99 ? odds=am/100 : odds=abs(100/am)
    euro && return 1+odds
    return odds
end
By default, it will return your net payout, eg: oddsconvert(-150) = .666...

But if you want Euro odds: oddsconvert(-150, true) = 1.666...

I wrote it as a separate function because now you can use it in any other function.
Series Price Calculation Quote
06-09-2019 , 01:58 PM
Quote:
Originally Posted by trup_qq
how to find a breakeven amount on a 3 way (soccer) line when inputting the other 2 amounts using US moneyline odds.
If you're talking about finding the vig-free line, I've whipped up some code to find it for any # of outcomes:

Code:
function oddsconvert(am::Int64, toEuro=false)  # If !toEuro, converts to net payout.
    am>99 ? odds=am/100 : odds = -100/am
    toEuro && return 1+odds
    return odds
end
function oddsconvert(am::Vector{Int64}, toEuro=false)
    len = length(am)
    odds = similar(am,Float64)
    for k=1:len begin am[k]>99 ? odds[k]=am[k]/100 : odds[k] = -100/am[k] end end
    toEuro && return 1 .+ odds
    return odds
end
function oddsconvert(odds::Float64, fromEuro=true)  # If !fromEuro, converts from net payout.
    fromEuro && odds≤1 && error("invalid Euro odds")
    fromEuro && begin odds-=1 end
    odds≥1 && return 100*odds
    return -100/odds
end
function oddsconvert(odds::Vector{Float64}, fromEuro=true)
    fromEuro && any(k -> k≤1, odds) && error("invalid Euro odds")
    len = length(odds)
    am = similar(odds)
    fromEuro && begin odds .-= 1 end
    for k=1:len begin odds[k]≥1 ? am[k]=100*odds[k] : am[k] = -100/odds[k] end end
    return am
end
function novig(odds::Vector{Int64})
    return novig(oddsconvert(odds,true), false)
end
function novig(odds::Vector{Float64}, keepEuro=true)  # Assumes euro odds as input
    imp = 1 ./ odds
    imp /= sum(imp)
    keepEuro && return ((1 .- imp) ./ imp) .+ 1
    return oddsconvert(((1 .- imp) ./ imp .+ 1))
end
I've added some methods for oddsconvert(). If you input an integer, it will convert from American to Euro or Euro-1 depending on the true/false value. If you input a decimal, it will convert to American and its default assumption will be that your input was in Euro format (but if false, it will assume Euro-1). There are also similar methods accepting vectors to convert the entire vector.

For the vig-free line calculation I've written novig(), which accepts a vector.

If it's a vector of American odds, it will return the no-vig line in American odds.

If it's a vector of decimals (which it will assume are Euro), it will return the no-vig line in Euro odds.

Examples:
Code:
julia> novig([-158, 145])
2-element Array{Float64,1}:
 -150.03875968992244
  150.0387596899225

julia> novig([120,150,280])
3-element Array{Float64,1}:
 145.89473684210526
 179.42583732057412
 324.7272727272727
Series Price Calculation Quote

      
m