Probability of Getting a Jack-high flop holding Jack-high hole cards¶
If you're playing Texas Hold'em with two hole cards that are 'jack-high', you have some jack high hand (J2, J3, ..., J10). What are the odds you get to see a Jack high flop (Jxx, where x is some card ranked less than or equal to a Jack)?¶
TLDR For an easily rememberable probability of an x-high hand hitting an x-high flop, it is close enough to estimate that for x = (9,10,J,Q,K,A), the probability of a 9-high flop is 6% and increases about 2.3% each card rank. See below for exact figures:¶
Assuming theres no cards missing, there's 50 cards and 3 jacks left in the deck.
The odds are P(Jxx), where x is some card ranked equal to or below a J.
The favorable cards for x, is 2 through 10 (36 cards), minus the 1 low card we have in our hand (35 cards), plus the other 2 remaining jacks in the deck after we select our starter jack (37 cards).
Therefore, p(jxx) = (3c1 * 37c2)/ 50c3
import math
pjhi = (math.comb(3,1)*math.comb(37,2))/math.comb(50, 3)
print(f'The probability of a jack high flop is {pjhi*100}%')
The probability of a jack high flop is 10.193877551020408%
So we established the probability of getting a jack high flop is 10.19%. Is there a way to estimate our probability, based on whatever "x high" hand we may have?
Lets compute the probabilities for cards 5 through ace using the same logic as the Jack high flop:
import pandas as pd
import matplotlib.pyplot as plt
from tabulate import tabulate
def flop_x_high():
total_cards = 50
results=[]
for x in range(5,15):
num_ranks_higher = 14-x
num_cards_higher = num_ranks_higher * 4 +1
remaining_cards = total_cards - (num_cards_higher)
prob_x_high = ((math.comb(3,1) * math.comb(remaining_cards, 2)) / math.comb(50,3))
results.append((x,round(prob_x_high, 4)))
return results
x_high_board_probs = flop_x_high()
df= pd.DataFrame(x_high_board_probs, columns=['X-high board','Probability'])
# Compute the differences
df['Increase'] = df['Probability'].diff().fillna(0)
print(tabulate(df, headers='keys',tablefmt='psql'))
plt.bar(df['X-high board'], df['Probability'], color = 'mediumseagreen',)
for i, prob in enumerate(df['Probability']):
plt.text(df['X-high board'][i], prob + 0.002, f'{prob:.4f}', ha='center', fontsize=10)
plt.xlabel("Rank of Card 5 to 14 (where JQKA = 11, 12, 13, 14)")
plt.ylabel("Probability")
plt.title("Probability distribution for X high flop")
plt.show()
+----+----------------+---------------+------------+ | | X-high board | Probability | Increase | |----+----------------+---------------+------------| | 0 | 5 | 0.0119 | 0 | | 1 | 6 | 0.0208 | 0.0089 | | 2 | 7 | 0.0321 | 0.0113 | | 3 | 8 | 0.0459 | 0.0138 | | 4 | 9 | 0.0621 | 0.0162 | | 5 | 10 | 0.0808 | 0.0187 | | 6 | 11 | 0.1019 | 0.0211 | | 7 | 12 | 0.1255 | 0.0236 | | 8 | 13 | 0.1515 | 0.026 | | 9 | 14 | 0.18 | 0.0285 | +----+----------------+---------------+------------+
Lets examine the difference in these probabilities, and come up with some formula to to fit the line.
# Compute the differences
df['Increase'] = df['Probability'].diff().fillna(0)
print(tabulate(df, headers='keys', tablefmt='psql'))
# Plot bar chart showing probability and increase
plt.figure(figsize=(10,6))
plt.bar(df['X-high board'], df['Probability'], color='mediumseagreen', label="Probability")
plt.plot(df['X-high board'], df['Increase'], color='red', marker='o', linestyle='dashed', label="Increase")
#labels
for i, prob in enumerate(df['Probability']):
plt.text(df['X-high board'][i], prob + 0.002, f'{prob:.6f}', ha='center', fontsize=10)
for i, inc in enumerate(df['Increase'][1:], start=1):
plt.text(df['X-high board'][i], df['Probability'][i] - 0.002, f'+{inc:.6f}', ha='center', fontsize=9, color='red')
plt.xlabel("Rank of Card 5 to 14 (where JQKA = 11, 12, 13, 14)")
plt.ylabel("Probability")
plt.title("Probability Distribution for X-high Flop with Increase")
plt.legend()
plt.show()
+----+----------------+---------------+------------+ | | X-high board | Probability | Increase | |----+----------------+---------------+------------| | 0 | 5 | 0.0119 | 0 | | 1 | 6 | 0.0208 | 0.0089 | | 2 | 7 | 0.0321 | 0.0113 | | 3 | 8 | 0.0459 | 0.0138 | | 4 | 9 | 0.0621 | 0.0162 | | 5 | 10 | 0.0808 | 0.0187 | | 6 | 11 | 0.1019 | 0.0211 | | 7 | 12 | 0.1255 | 0.0236 | | 8 | 13 | 0.1515 | 0.026 | | 9 | 14 | 0.18 | 0.0285 | +----+----------------+---------------+------------+
import numpy as np
# Fit a linear regression to the Increase values
x_values = df['X-high board'].values.reshape(-1, 1) # Reshape for fitting
y_values = df['Increase'].values
# Perform linear regression
coeffs = np.polyfit(df['X-high board'], df['Increase'], 1)
slope, intercept = coeffs
# Display equation of the line
equation = f"The equation for the increase line is = {slope:.6f}*X + {intercept:.6f}"
equation
'The equation for the increase line is = 0.002801*X + -0.009796'
Based on the given probabilities, it is close enough to estimate that for cards 9 through Ace, the probability starts at 6% and increases about 2.3% each rank. This is an easy way to estimate your odds of a X-high flop on the fly (x = 9,10,J,Q,K,A)
starting at card 9 = 6% chance for a 9 high flop, these estimations would look like this:
import matplotlib.pyplot as plt
df1 = [6, 8.3, 10.6, 12.9, 15.2, 17.5]
df2 = [9, 10, 11, 12, 13, 14]
plt.bar(df2, df1, color="mediumseagreen")
plt.xlabel("Card Rank 'X'")
plt.ylabel("X-High Flop Probabilities")
plt.title("Estimations Based on 2.3% increase")
for i, prob in enumerate(df1):
plt.text(df2[i], prob + 0.002, f'{prob:.2f}%', ha='center', fontsize=10)
plt.show()
This is very close to the actual distribtution from 9 to 14.
I now want to look at cases where the J-high flop is monotone. The probability of a jack high flop of the same 'x' suit is the probability we draw some jack of suit x, then the reamining 2 cards of also suit x, excluding Q,K,A (to remain a J-high flop).
There are two cases, 1 where we have a flush draw with our second card, and the other where we do not. If we do not have a flush draw, there are 9 cards of the available suit remaining and 2 suits to choose from. If we do have a flush draw, there's 1 suit to choose from, and 8 cards of that suit remaining (because one is in our hand).
samesuitnotyours = (2 * math.comb(1,1)*math.comb(9,2)) / math.comb(50,3)
samesuityours = math.comb(1,1)*math.comb(8,2) / math.comb(50,3)
pjhinoflush = pjhi - (samesuitnotyours + samesuityours)
print(f'The probability of same suit jack high flop that is not your second cards suit is {samesuitnotyours*100}%')
print(f'The probability of same suit jack high flop, of the same suit that your unknown second card is: {samesuityours*100}%')
print(f'The probability of jack high not all of 1 suit {pjhinoflush*100}%')
print(f'The conditional probability of you having the flush draw given a J high flop of the same suit: {((samesuityours)/(samesuitnotyours+samesuityours)*100)}%')
The probability of same suit jack high flop that is not your second cards suit is 0.36734693877551017% The probability of same suit jack high flop, of the same suit that your unknown second card is: 0.14285714285714285% The probability of jack high not all of 1 suit 9.683673469387754% The conditional probability of you having the flush draw given a J high flop of the same suit: 28.000000000000004%
Here, you might think, "if the j-high flop is all 1 suit, then the probability my second card is also of that suit is 1/4 or 25%," but that is not the case due to dependence.
By using the CDF of the negative binomial distribution below, we are able to see the cumulative probability of getting 1 success within 10 trials is 0.6738.
Note: This does not change individual independent probabilities.
from scipy.stats import binom,nbinom
#what is the odds of seeing 10 trials before the first jack high flop
print(f'probability of seeing 1 success in 10 trials: {nbinom.cdf(9,1,0.106)}')
probability of seeing 1 success in 10 trials: 0.6738816863291575
Now, you're obviously not alone at a poker table, which means if theres 5 other players, then there are 10 more hole cards unaccounted for. However, since all players are drawing from the same unknown distribution, using the 50-card deck assumption is still reasonable for preflop decision making in an unknown opponent scenario, and is commonly used to calculate texas-hold'em probabilities.