Can you get an advantage in Baccarat from knowing the burn card?

In todays issue we'll be exploring whether we can gain advantage in Baccarat just by knowing what the burn card is. This turns into a bit of a rabbit hole, with some very surprising results!
Theoretically, the removal of a few cards should affect the game, and by knowing what the burn card is we can infer that the odds of the game have changed.
What is the burn card?
The burn card is a card drawn at the beginning of each new shoe in baccarat. The dealer will draw the first card after the shuffle, and whatever the value of that card is, they will pull that many additional cards from the shoe and discard them. If the first card out is an Ace, then the dealer will remove one additional card. If it's a 10, J, Q, K then they will remove an additional 10 cards for discard.
This has essentially the same effect as increasing the depth of the cut card. If the cur card is 14 cards from the back, and the burn card is a 10, the cut card is now 25 (14 + 1 + 10).
The Experiment
We'll have a look at how each burn card value affects the expected value of each of the main wagers in baccarat and EZ baccarat.
All the wins will be tracked sorted by burn card value 0 - 9. 0 value cards represent 10, J, Q, K since they're worth 0 in the game, and 1- 9 represents cards A through 9.
We'll be running 100M shoes for this experiment.
The setup
The normal simulation constants
# Game Constants
EZ_BAC = True
NUM_DECKS = 8
NUM_SHOES = 100000000
CUT_CARD = 14
BANKER_PAYOUT = 0.95
if EZ_BAC:
BANKER_PAYOUT = 1
PLAYER_PAYOUT = 1
TIE_PAYOUT = 8
DRAGON_PAYOUT = 40
I'll define some new constants to make tracking and saving cleaner and easier to read
# Burn card tracking index constants
PLAYER_W = 0
BANKER_W = 1
DRAGON_W = 2
TIE_W = 3
TOTAL = 4
Create a nested numpy array to store the wins
burn_card_tracking = np.zeros((10,5), dtype=np.int32)
At the beginning of each shoe the variables are reset, and a card is burnt
for _ in range(NUM_SHOES):
dragon_wins = 0
total_hands = 0
banker_wins = 0
player_wins = 0
tie_wins = 0
burn_card = deck[0]
if burn_card == 0:
indx = 11
else:
indx = burn_card + 1
And at the end of each shoe those wins are sorted by burn card value and saved
for _ in range(NUM_SHOES):
dragon_wins = 0
total_hands = 0
banker_wins = 0
player_wins = 0
tie_wins = 0
burn_card = deck[0]
if burn_card == 0:
indx = 11
else:
indx = burn_card + 1
# Rest of game code
burn_card_tracking[burn_card][BANKER_W] += banker_wins
burn_card_tracking[burn_card][PLAYER_W] += player_wins
burn_card_tracking[burn_card][DRAGON_W] += dragon_wins
burn_card_tracking[burn_card][TIE_W] += tie_wins
burn_card_tracking[burn_card][TOTAL] += total_hands
And then finally after all shoes have completed the stats are calculated
burn_card_tracking = baccarat()
for rank in range(10):
player_wins = burn_card_tracking[rank][PLAYER_W]
banker_wins = burn_card_tracking[rank][BANKER_W]
tie_wins = burn_card_tracking[rank][TIE_W]
dragon_wins = burn_card_tracking[rank][DRAGON_W]
total_hands = burn_card_tracking[rank][TOTAL]
burn_card_results[rank] = calculate_stats(player_wins, banker_wins, tie_wins, dragon_wins, total_hands)
After running the code for EZ Baccarat, I got some interesting results
[[ 1092811263 1067819277 55237962 233202626 -1845896168]]
burn_card = 0
{'EZ_BAC': True,
'banker_ev': 1.353921549502879,
'banker_wins': -57.848285050451445,
'banker_wins_no_tie': -51.359717974036776,
'dragon_he': -222.69143201341754,
'player_ev': 1.6385524020438913,
'player_wins': -59.20220659995432,
'player_wins_no_tie': -52.56177658097376,
'tie_ev': -213.70215022841955,
'tie_wins': -12.633572247602173}
Specifically, we can see that the Banker and Player EV are positive. But there's a problem and after looking at the tracking data I realised that I am getting what's called integer overflow. The problem stems from when I defined the burn_card_tracking
array with dtype=np.int32
. So it'll need to be defined as np.int64
to avoid this. We can tell because the value of total_hands
is -1845896168 - which clearly isnt correct.
After fixing this bug, and re-running the code we have our results
Simulation Results
Raw Data
Here's the raw data used to derive these statistics. The lists are indexed by the burn card (0 index is 10 value cards, 1 - 9 as normal):
# Burn card tracking index key
PLAYER_W = 0
BANKER_W = 1
DRAGON_W = 2
TIE_W = 3
TOTAL = 4
EZ Baccarat:
[[1092642239 1067649291 55239095 233121629 2448652254]
[ 279468428 273100930 14127194 59598235 626294787]
[ 278823193 272501229 14074179 59437055 624835656]
[ 277821597 271576193 14012648 59231505 622641943]
[ 277388731 271150566 13972212 59125958 621637467]
[ 276797547 270463127 13939745 59002051 620202470]
[ 276109295 269766504 13884547 58781918 618542264]
[ 275410333 269149360 13850417 58668522 617078632]
[ 274392101 268033913 13937087 58568073 614931174]
[ 273677223 267329757 13892241 58383089 613282310]]
Standard Baccarat:
[[1092845556 1123057994 0 233188359 2449091909]
[ 279384597 287170339 0 59609605 626164541]
[ 278612883 286388779 0 59411148 624412810]
[ 277973758 285723255 0 59263479 622960492]
[ 277331841 285114058 0 59133201 621579100]
[ 276664101 284234157 0 58960525 619858783]
[ 276079710 283659478 0 58781902 618521090]
[ 275185496 282739732 0 58600112 616525340]
[ 274566738 282129020 0 58590445 615286203]
[ 273827160 281433354 0 58418145 613678659]]
EZ Baccarat
Burn Card | Banker EV (%) | Banker Wins (%) | Player EV (%) | Player Wins (%) | Tie EV (%) | Tie Wins (%) | Dragon HE (%) |
---|---|---|---|---|---|---|---|
Baseline | -1.0184 | 43.6058 | -1.2362 | 44.6242 | -14.3614 | 9.5154 | -7.5595 |
0 | -1.0207 | 43.6015 | -1.2352 | 44.6222 | -14.3163 | 9.5204 | -7.5082 |
1 | -1.0167 | 43.6058 | -1.2390 | 44.6225 | -14.3560 | 9.5160 | -7.5172 |
2 | -1.0118 | 43.6117 | -1.2407 | 44.6234 | -14.3881 | 9.5124 | -7.6491 |
3 | -1.0030 | 43.6168 | -1.2475 | 44.6198 | -14.3836 | 9.5129 | -7.7289 |
4 | -1.0035 | 43.6188 | -1.2441 | 44.6223 | -14.3981 | 9.5113 | -7.8465 |
5 | -1.0213 | 43.6088 | -1.2263 | 44.6302 | -14.3798 | 9.5134 | -7.8479 |
6 | -1.0254 | 43.6133 | -1.2193 | 44.6387 | -14.4703 | 9.5033 | -7.9664 |
7 | -1.0146 | 43.6167 | -1.2299 | 44.6313 | -14.4328 | 9.5075 | -7.9749 |
8 | -1.0340 | 43.5876 | -1.2325 | 44.6216 | -14.2810 | 9.5243 | -7.0757 |
9 | -1.0350 | 43.5900 | -1.2302 | 44.6250 | -14.3220 | 9.5198 | -7.1257 |
Standard Baccarat
Burn Card | Banker EV (%) | Banker Wins (%) | Player EV (%) | Player Wins (%) | Tie EV (%) | Tie Wins (%) | Dragon HE (%) |
---|---|---|---|---|---|---|---|
Baseline | -1.0600 | 45.8598 | -1.2330 | 44.6268 | -14.3790 | 9.5134 | -100.0000 |
0 | -1.0592 | 45.8561 | -1.2336 | 44.6225 | -14.3072 | 9.5214 | -100.0000 |
1 | -1.0497 | 45.8618 | -1.2434 | 44.6184 | -14.3218 | 9.5198 | -100.0000 |
2 | -1.0480 | 45.8653 | -1.2453 | 44.6200 | -14.3675 | 9.5147 | -100.0000 |
3 | -1.0493 | 45.8654 | -1.2440 | 44.6214 | -14.3812 | 9.5132 | -100.0000 |
4 | -1.0415 | 45.8693 | -1.2520 | 44.6173 | -14.3796 | 9.5134 | -100.0000 |
5 | -1.0715 | 45.8547 | -1.2213 | 44.6334 | -14.3926 | 9.5119 | -100.0000 |
6 | -1.0676 | 45.8609 | -1.2255 | 44.6355 | -14.4674 | 9.5036 | -100.0000 |
7 | -1.0677 | 45.8602 | -1.2253 | 44.6349 | -14.4559 | 9.5049 | -100.0000 |
8 | -1.0636 | 45.8533 | -1.2291 | 44.6242 | -14.2978 | 9.5225 | -100.0000 |
9 | -1.0536 | 45.8601 | -1.2394 | 44.6206 | -14.3260 | 9.5193 | -100.0000 |
Notes:
- EV = Expected Value (house edge)
- Dragon HE shows -100.0000% for Standard Baccarat (bet not available)
Baccarat Expected Value Analysis
Impact of Card Removal on Bet Expected Values
Analyzing the Results
Ok, to be honest I did not expect these results. At the beginning of this experiment I did not think that there'd be any real detectable results and if there were, they'd be linearly scaled by burn card value.
But what we're actually seeing is that EV is increasing for the banker bet when 4 and 5 total cards are burnt. That's where our best gain is. We're seeing a parabolic ev curve based on the burn card, and similar results for the other bets. This is odd.
Now, I was a bit skeptical so I did a bit of math. I wasn't convinced that my sample size was large enough so I used the Margin of Error formula to get a confidence interval based on sample size n
.
Margin of Error = z × √(σ²/n)
Where:
σ² = variance of outcomes
n = sample size
z = confidence level z-score
Using burn card 3 for our calculations, we'll need to calculate the variance.
Var(X) = E[X²] - (E[X])²
We need the Expected value of the squared outcomes E[X²]
and the expected value, then squared (E[X])²
EV = (Probability of Win * Payout) - (Probability of Loss * Bet)
We only count winning or losing bets.
E[X] = 0.436168×(+1) + 0.446198×(-1) + 0.1176×(0) = -0.01003
And we get the same EV as in the chart. Now we'll calculate the total number of hands that are won or lost.
E[X²] = 0.436168×(1)² + 0.446198×(-1)² + 0.1176×(0)² = 0.882366
σ² = E[X²] - (E[X])²
σ² = 0.882366 - (-0.01003)²
σ² = 0.882366 - 0.0001 = 0.882266
The margin of error at 99% confidence is:
Margin of Error = z × √(σ²/n)
= 2.576 × √(0.882266/620M)
= 2.576 × 0.0000377
= 0.00009717 × 100
= 0.009717%
Our observed difference for EZ Baccarat using burn card 3 banker EV and baseline banker EV is 1.0184 - 1.0030 = 0.0154%
Our EV range from the baseline should be 1.008683 - 1.028117%
Confidence Level | Z-Score | Margin of Error | Observed Effect vs Margin |
---|---|---|---|
90% | 1.645 | ±0.0062% | 2.5x |
95% | 1.96 | ±0.0074% | 2.1x |
99% | 2.576 | ±0.0097% | 1.6x |
99.9% | 3.29 | ±0.0124% | 1.2x |
99.99% | 3.89 | ±0.0147% | 1.0x |
Our observed difference is statistically significant up to 99% confidence, after that it becomes borderline.
In order to find the number of hands required for a confidence interval of 99.9% we can select a very precise margin of error of 0.00005 and use the following formula.
n = z² × σ² / d²
n = (3.29)² × 0.882266 / (0.00005)²
n = 10.82 × 0.882266 / 0.0000000025
n = 9.546 / 0.0000000025
n = 3,818,400,000 hands
Where:
d = desired margin of error
n = number of trials
This tells us that for each burn card we'd need to track 3.8B hands for the most precise results.
I think having a 99% confidence interval with our margin of error is acceptable.
I've organized all our results in the charts below. I've subtracted the newly calculated house edge (or ev) from the known baseline house edge of the particular wager, and listed the difference in the column beside it.
A positive difference means that burn card is good for the player, and a negative difference means that it's worse for the player.
EZ Baccarat Burn Card EVs and Differences
Card | Banker EV | Banker Diff | Player EV | Player Diff | Tie EV | Tie Diff | Dragon EV | Dragon Diff |
---|---|---|---|---|---|---|---|---|
Baseline | -1.0184 | 0.0000 | -1.2362 | 0.0000 | -14.3614 | 0.0000 | -7.5595 | 0.0000 |
0 | -1.0207 | -0.0023 | -1.2352 | 0.0010 | -14.3163 | 0.0451 | -7.5082 | 0.0513 |
1 | -1.0167 | 0.0017 | -1.2390 | -0.0028 | -14.3560 | 0.0054 | -7.5172 | 0.0423 |
2 | -1.0118 | 0.0066 | -1.2407 | -0.0045 | -14.3881 | -0.0267 | -7.6491 | -0.0896 |
3 | -1.0030 | 0.0154 | -1.2475 | -0.0113 | -14.3836 | -0.0222 | -7.7289 | -0.1694 |
4 | -1.0035 | 0.0149 | -1.2441 | -0.0079 | -14.3981 | -0.0367 | -7.8465 | -0.2870 |
5 | -1.0213 | -0.0029 | -1.2263 | 0.0099 | -14.3798 | -0.0184 | -7.8479 | -0.2884 |
6 | -1.0254 | -0.0070 | -1.2193 | 0.0169 | -14.4703 | -0.1089 | -7.9664 | -0.4069 |
7 | -1.0146 | 0.0038 | -1.2299 | 0.0063 | -14.4328 | -0.0714 | -7.9749 | -0.4154 |
8 | -1.0340 | -0.0156 | -1.2325 | 0.0037 | -14.2810 | 0.0804 | -7.0757 | 0.4838 |
9 | -1.0350 | -0.0166 | -1.2302 | 0.0060 | -14.3220 | 0.0394 | -7.1257 | 0.4338 |
Raw Sum | -0.0020 | 0.0173 | -0.1140 | -0.6455 | ||||
Absolute Sum | 0.0868 | 0.0703 | 0.4546 | 2.6679 |
Standard Baccarat Burn Card EVs and Differences
Card | Banker EV | Banker Diff | Player EV | Player Diff | Tie EV | Tie Diff |
---|---|---|---|---|---|---|
Baseline | -1.0600 | 0.0000 | -1.2330 | 0.0000 | -14.3790 | 0.0000 |
0 | -1.0592 | 0.0008 | -1.2336 | -0.0006 | -14.3072 | 0.0718 |
1 | -1.0497 | 0.0103 | -1.2434 | -0.0104 | -14.3218 | 0.0572 |
2 | -1.0480 | 0.0120 | -1.2453 | -0.0123 | -14.3675 | 0.0115 |
3 | -1.0493 | 0.0107 | -1.2440 | -0.0110 | -14.3812 | -0.0022 |
4 | -1.0415 | 0.0185 | -1.2520 | -0.0190 | -14.3796 | -0.0006 |
5 | -1.0715 | -0.0115 | -1.2213 | 0.0117 | -14.3926 | -0.0136 |
6 | -1.0676 | -0.0076 | -1.2255 | 0.0075 | -14.4674 | -0.0884 |
7 | -1.0677 | -0.0077 | -1.2253 | 0.0077 | -14.4559 | -0.0769 |
8 | -1.0636 | -0.0036 | -1.2291 | 0.0039 | -14.2978 | 0.0812 |
9 | -1.0536 | 0.0064 | -1.2394 | -0.0064 | -14.3260 | 0.0530 |
Raw Sum | 0.0283 | -0.0289 | 0.0930 | |||
Absolute Sum | 0.0891 | 0.0905 | 0.4564 |
I also added raw sum and absolute sum to the bottoms of the tables. The raw sum is all the differences summed, and the absolute sum is the sum of all differences as if they were all positive.
The raw sum tells us that the net analysis either has a more positive effect or negative effect. As in if the raw sum is positive, that means the bet has a more positive sensitivity to the cards being burnt. So the dragon has a negative raw sum because most of the burn cards produce a negative outcome for the bet.
The absolute sum tells us the sensitivity to the burn cards effects. Again, the dragon seems like it has a quite high sensitivity compared to the other bets.
All this is to say that in the end, yes we can gain an advantage just by knowing the burn card.
For all the EZ baccarat bets: the banker bet, if the burn card is a 3 or 4, we gain the largest reduction in the house edge by ~0.015% and a 0.0169% reduction in the house edge for the player bet when the cut card is a 6. The dragon bet's house edge is reduced the most - by 0.48% - when the burn card is an 8. The best burn card for the tie bet is an 8, reducing the house edge by 0.08%
The banker, tie and dragon bets have the least amount of helpful burn cards, while the player has the most.
While these burn cards provide a more advantageous situation we're not actually gaining a winning advantage, but rather a reduction in the house edge.