BJW Blackjack/AP Formula Inventory¶
Date: 2026-03-16
Public site note: This page mirrors the current BJW formula inventory maintained in the main project docs.
Purpose¶
This document inventories the blackjack and advantage-play formulas implemented in BJW code.
For each formula family, it states:
- where the formula lives
- what the formula is trying to do
- where the inputs come from in the BJW pipeline
- what the variables mean
- what output the formula is expected to produce
- what terms to search for in books or online if you want to verify the underlying idea yourself
Scope¶
Included:
- core simulator runtime math
- parallel aggregation math
- betting VM math
- result helper math
- validation/comparison math
- experiment/optimizer/reporting math that derives blackjack/AP metrics from results
- QA/statistical formulas that materially affect blackjack result interpretation
Excluded:
- static basic-strategy/deviation tables
- pure formatting with no arithmetic
- tests that only restate formulas already implemented elsewhere
Important High-Level Findings¶
- BJW’s core simulator does not compute blackjack EV from closed-form house-edge formulas. It simulates rounds and measures EV/variance from outcomes.
- BJW’s current canonical counted-risk path is observed per-round variance, not legacy
chapter10math. - Legacy
chapter10/di_adjustedvariance math still exists in audit/helpers/older scripts, but it is not the canonical runtime contract on this branch. - The repo currently contains more than one definition of some named metrics:
DIis sometimes1000 * EV / SDand sometimes plainEV / SD.N0is sometimes(SD / EV)^2and sometimes(1.96 * SD / EV)^2.- Older counted experiment scripts still read
chapter10fields.
Those semantic drifts are called out explicitly below.
Formula Status Legend¶
- Canonical runtime: defines BJW’s primary simulator result contract
- Diagnostic/legacy: retained for research, audits, or backward compatibility
- Reporting/helper: derived outside the simulator for display or scripting
- Statistical comparison: used to compare runs or assess confidence
How To Use This Document¶
If you are trying to verify a formula yourself:
- Start from the operation index below.
- Jump to the canonical runtime section first if one exists.
- If the same name appears elsewhere, check the drift index before assuming the formulas are identical.
- Use the
Search termsblock in that section to look for the external concept in books, BJ Attack, CVData discussions, or online references.
This document intentionally distinguishes:
- the formula BJW currently uses in active runtime
- helper/reporting formulas that only post-process results
- legacy or diagnostic formulas kept for audits
When a section gives a provenance note, the intended meanings are:
Standard external concept: common blackjack/statistics/math idea, but this document does not yet record an exact page citationBJW contract choice: a runtime or reporting convention BJW chose and enforcesBJW-authored model/heuristic: an explicit BJW approximation, policy model, or threshold that should not be mistaken for sourced literatureLegacy unsourced: retained for compatibility or audit only and not currently backed by a verified external citation
When a section gives a citation-status note, the intended meanings are:
Exact reference recorded: this document includes a specific external source in 15. Exact References RecordedNo verified citation recorded: this pass did not verify an exact external source for that formula or exact implementation
Formula Map By Operation¶
- Counting and count conversion: 1.1 Running Count Tag Update, 1.3 Decks Remaining, 1.4 Deck Quantization, 1.5 True Count, 1.6 TC Bucket Rounding and Clamping
- Wonging and table-entry logic: 1.8 Wonging Entry/Exit Thresholds, 1.9 Wonging Round Accounting, 1.10 Penetration to Cut-Card Conversion
- Kelly betting: 2.2 Kelly Edge Model, 2.3 Kelly Variance Model, 2.4 Kelly Fraction and Bet Size, 2.5 Kelly Edge-Table Discretization, 10.3 Kelly Cap Warning Threshold
- Progressions and non-count betting systems: 2.1 Count Spread Lookup, 2.6 Progression Bet Formulas, 2.7 State-Machine Special Calculation
- Blackjack hand and round settlement: 3.1 Hand Total with Ace Adjustment, 3.2 Dealer Play Rule, 3.7 Insurance Settlement, 3.8 Insurance Effective Probability and EV, 3.10 Natural, Surrender, Win/Loss/Push Settlement
- Canonical performance and risk metrics: 4.1 Observed Sample Variance via Welford, 4.2 EV per Hand, per Round, per Initial Bet, and Average Bet, 4.3 Primary Risk Basis Selection, 4.4 SCORE, 4.5 Desirability Index (DI), 4.6 Canonical Runtime N0, 4.7 Risk of Ruin (RoR) Approximation
- Parallel aggregation and contract sync: 5.1 Worker-Result Pooled Variance, 4.3 Primary Risk Basis Selection
- Per-bucket and decision telemetry: 6.1 EV-by-Bucket Variance, 6.2 Exact Decision Variable SD
- Legacy variance paths and audits: 7.1 Legacy
chapter10Variance Decomposition, 7.2 Legacydi_adjustedReconstruction, 7.3 RMS SD Validation Heuristic - Helpers, optimizers, and reweighting: 8.1 Sharpe-Like Ratio, 8.2 Reweighting Formulas for Spread Optimization, 8.3 Helper/API DI Formula, 8.4 Helper/API SCORE Formula, 8.5 Helper/API N0(Confidence) Formula
- Statistical comparison and QA gates: 9.1 Standard Error / Confidence Interval, 9.4 Z-Score for Run-to-Run Comparison, 10.1 Initial Pair Baseline Tolerance
Same Name, Different Formula Index¶
DI: canonical runtime 4.5 Desirability Index (DI), helper copy 8.3 Helper/API DI Formula, drift summary 11.1 DI Scaling DriftN0: canonical runtime 4.6 Canonical Runtime N0, confidence-style helper 8.5 Helper/API N0(Confidence) Formula, drift summary 11.2 N0 Definition Drift- Counted risk basis: canonical contract 4.3 Primary Risk Basis Selection, old counted scripts 11.3 Counted-Risk Basis Drift in Older Scripts, top-level field mismatch 11.4 Top-Level Per-Hand Fields vs
risk_primary - Legacy variance blocks: diagnostic only 7.1 Legacy
chapter10Variance Decomposition, 7.2 Legacydi_adjustedReconstruction - Kelly inputs vs Kelly output: edge model 2.2 Kelly Edge Model, variance model 2.3 Kelly Variance Model, final bet formula 2.4 Kelly Fraction and Bet Size
1. Counting and Decision-Variable Formulas¶
Section citation status
No verified citation recorded section-wide. These are BJW implementations of standard counting conventions and manifest semantics, but this pass did not attach exact external references for each convention.
1.1 Running Count Tag Update¶
Status: Canonical runtime
Formula
RC_new = RC_old + tag(exposed_card)
Primary locations
src/typescript/simulator_lite/src/simulator.tscountTag(...),revealCard(...)src/typescript/simulator_lite/src/utils.tscountTag(...),toCountTag(...)
What it is for
Updates the running count whenever a card becomes visible to the player.
Variables
RC: current running counttag(card): count-system tag value for the exposed card
Where the variables come from
RCis simulator state carried through the shoe- tag values come from
manifest.counting.card_values - Red Seven / suit-aware tags are resolved from the actual card rank+suit
Expected output
An integer or fractional running count, depending on the count system definition.
Search terms
running count updatecount tag valuesHi-Lo tagsKO tagsRed Seven tag values
1.2 Theoretical Running Count Bounds¶
Status: Reporting/helper
Formula
RC_max = Σ max(0, tag_i)
RC_min = Σ min(0, tag_i)
RC_end = RC_max + RC_min
Primary locations
src/python/configurator/transpilers/betting_to_bvm.py_calculate_rc_bounds(...)
What it is for
Computes the theoretical min/max/end-of-shoe running count for a count system and deck count.
Variables
tag_i: tag value of each physical card in the shoeRC_end: total shoe unbalance
Where the variables come from
tag_icomes from the count-system tag map underdata/rules/counting/...- the “physical cards in the shoe” come from the configured deck count and shoe composition used by the transpiler when it enumerates all cards
RC_endis the sum of all shoe tags, so for balanced systems it should end near0, while for unbalanced systems it represents the system’s full-shoe unbalance
Interpretation
This section is not reading live simulator state. It is doing a static whole-shoe audit of the counting system definition.
Expected output
The minimum possible RC, maximum possible RC, and final end-of-shoe RC if the whole shoe were revealed.
Search terms
running count boundsend of shoe running countunbalanced count shoe endkey count
1.3 Decks Remaining¶
Status: Canonical runtime
Formula
decks_remaining = cards_remaining / 52
or, when divisor basis is configured as cards dealt:
decks_remaining = decks_total - quantize(cards_dealt / 52)
with a lower clamp:
decks_remaining = max(0.0001, decks_remaining)
Primary locations
src/typescript/simulator_lite/src/simulator.tsdecksRemaining(...)src/typescript/simulator_lite/src/utils.tsdecksRemaining(...)
What it is for
Provides the divisor for true-count conversion and several diagnostic outputs.
Variables
cards_remainingcards_dealtdecks_total
Where the variables come from
cards_remaining = shoe.length - shoePtrcards_dealt = shoePtrdecks_total = manifest.environment.ruleset.decks
Interpretation
This is the raw shoe-depth input before the true-count formula in 1.5 True Count.
Expected output
A positive estimate of decks remaining, optionally quantized.
Search terms
decks remainingtrue count divisorhalf deck estimationquarter deck estimation
1.4 Deck Quantization¶
Status: Canonical runtime
Formula
full_deck: round(x)
half_deck: round(2x) / 2
quarter_deck: round(4x) / 4
continuous: x
Primary locations
src/typescript/simulator_lite/src/utils.tsquantizeDecksRemaining(...)- used by
src/typescript/simulator_lite/src/simulator.ts
What it is for
Replicates common card-counter deck-estimation granularity before true-count division.
Variables
x: continuous decks remaining or decks dealt
Where the variables come from
xis produced immediately before quantization from either:cards_remaining / 52, orcards_dealt / 52- which one BJW uses depends on the divisor-basis path described in 1.3 Decks Remaining
Interpretation
This section is only about how BJW rounds deck estimates. It does not itself choose between cards-remaining and cards-dealt semantics.
Expected output
A quantized deck estimate consistent with the configured divisor mode.
Search terms
half deck true countquarter deck true countdeck estimation granularity
1.5 True Count¶
Status: Canonical runtime
Formula
TC = RC / decks_remaining
Primary locations
src/typescript/simulator_lite/src/simulator.tstrueCount(...)src/typescript/simulator_lite/src/utils.tstrueCount(...)
What it is for
Converts running count to a depth-normalized count for balanced systems and TC-based policies.
Variables
RC: running countdecks_remaining: result of the current divisor policy
Where the variables come from
RCcomes from the running count state updated by 1.1 Running Count Tag Updatedecks_remainingcomes from 1.3 Decks Remaining, including any configured quantization from 1.4 Deck Quantization
Interpretation
This is the continuous true count before bucket rounding and clamping in 1.6 TC Bucket Rounding and Clamping.
Expected output
A continuous true count before integer bucketing/clamping.
Search terms
true count formularunning count divided by decks remaining
1.6 TC Bucket Rounding and Clamping¶
Status: Canonical runtime
Formula
nearest: round(TC)
away_from_zero:
if TC >= 0: floor(TC + 0.5)
else: ceil(TC - 0.5)
bucket = clamp(raw_bucket, bucket_min, bucket_max)
Primary locations
src/typescript/simulator_lite/src/simulator.tssrc/typescript/simulator_lite/src/utils.tscalculateBucketWithMode(...)
What it is for
Maps continuous TC into integer bins for bet spreads, EV-by-bucket, and deviation thresholds.
Variables
TCbucket_min,bucket_maxrounding_mode
Where the variables come from
TCis the continuous value from 1.5 True Count or an insurance-specific TC path when insurance bucketing is activebucket_minandbucket_maxcome frommanifest.bucketing.range.min/max(mirrored fromcounting.bucketing.range)rounding_modecomes fromcounting.tc_bucket_rounding_mode
Interpretation
This is the stage where BJW turns a continuous count into the integer decision variable actually used by spreads, deviations, and bucket telemetry.
Expected output
A final integer bucket used by policies and telemetry.
Search terms
true count roundinground away from zerocount bucket clamp
1.7 Depth-Adjusted Running Count Bucket¶
Status: Canonical runtime for systems that use depth adjustment
Formula
adjustment = base + multiplier * decks_played
adjusted_rc_bucket = round(RC - adjustment)
Primary locations
src/typescript/simulator_lite/src/simulator.tscalculateBucket(...)
What it is for
Allows RC-based systems with a depth adjustment to bucket the same way their betting policy decides.
Variables
RCbasemultiplierdecks_played = shoePtr / 52
Where the variables come from
RCis the live running count statebaseandmultipliercome frombucket_spread.depth_adjustmentin the BVM produced by the betting-policy transpilerdecks_played = shoePtr / 52
Interpretation
This is a betting-policy alignment step. BJW uses it so EV bucketing and bet-spread matching are based on the same adjusted RC decision variable.
Expected output
An integer depth-adjusted RC bucket.
Search terms
running count depth adjustmentwarm counteffective running count
1.8 Wonging Entry/Exit Thresholds¶
Status: Canonical runtime
Formula
enter if TC >= tc_ge or RC >= rc_ge
exit if TC <= tc_le or RC <= rc_le
Primary locations
src/typescript/simulator_lite/src/simulator.tsshouldEnterTable(...),shouldExitTable(...)
What it is for
Controls back-counting / wonging in and out of the game.
Search terms
wong in thresholdwong out thresholdback-counting entry count
1.9 Wonging Round Accounting¶
Status: Canonical runtime
Formula
total_rounds_observed += 1 each time entry/exit is rechecked
if wongingActive:
rounds_played += 1
else:
rounds_sat_out += 1
pct_time_at_table = 100 * rounds_played / total_rounds_observed
Primary locations
src/typescript/simulator_lite/src/simulator.tswonging state update insideplayOneRound(...)src/typescript/simulator_lite/src/index.tsderived recomputation ofpct_time_at_table
What it is for
Separates rounds the player actually plays from rounds merely observed while back-counting.
Important note
- If
when_out = sit_outorwhen_out = reshuffle, the observed round can increment wonging counters without incrementinground_summary.rounds. - If
when_out = flat_min, the round is still played and contributes to normal round/hand EV and variance.
Search terms
wonging rounds played vs observedback-counting sit-out accountingtime at table percentage
1.10 Penetration to Cut-Card Conversion¶
Status: Canonical runtime
Formula
penetration_fraction = penetration_pct / 100
cut_card = max(1, floor(shoe_size_cards * penetration_fraction))
start new shoe before next round if shoePtr >= cut_card
with the consistency constraint:
burn_cards < cut_card
Primary locations
src/typescript/simulator_lite/src/simulator.tspenetration parsing andcutCardsetupsrc/typescript/simulator_lite/src/simulator.tspre-round reshuffle check inplayOneRound(...)
What it is for
Turns manifest penetration into the actual deepest card position BJW will deal before reshuffling.
Important note
Penetration does not enter EV through a closed-form blackjack formula. It changes which late-shoe count states are reachable, which then changes bucket occupancy, betting opportunities, and observed EV/variance.
Search terms
blackjack penetration cut card formulacut card position shoe gamepenetration effect on true count distribution
2. Betting Formulas¶
Section citation status
Mixed. Some formulas below trace to general Kelly literature; others are BJW policy semantics or BJW-authored models with no verified external citation recorded for the exact implementation.
2.1 Count Spread Lookup¶
Status: Canonical runtime
Formula
No algebraic formula. BJW range-matches the current bucket against authored spread ranges:
if lo <= bucket <= hi: use units_for_that_range
Primary locations
src/typescript/simulator_lite/src/simulator.tsunitsFromCountBasedBetPolicy(...)
What it is for
Implements ordinary RC- or TC-tiered bet ramps.
Provenance status
BJW contract choice. This is the simulator’s implementation of an authored spread schedule, not a standalone blackjack theorem.
Citation status
No verified citation recorded. This is a BJW range-matching execution rule for authored spread schedules.
Search terms
bet spread by true counttiered spreadcount-based bet ramp
2.2 Kelly Edge Model¶
Status: Canonical runtime when a Kelly policy is used
Formula
Table-driven option:
edge = edge_table[count_index]
Fallback slope/cap option:
edge = min(max(0, count_value * edge_slope), edge_cap)
Primary locations
src/typescript/simulator_lite/src/betting_vm.tscalculateKellyUnits(...)- Kelly params produced by
src/python/configurator/transpilers/betting_to_bvm.py
What it is for
Produces a modeled per-hand edge for Kelly bet sizing.
Provenance status
BJW-authored model/heuristic. Kelly bet sizing itself is an external concept, but this particular edge parameterization and its defaults are authored policy/model inputs inside BJW rather than a verified closed-form blackjack edge law.
Citation status
No verified citation recorded for this exact BJW edge model.
Variables
count_value: TC for balanced systems, RC/effective count for unbalanced systemsedge_slope/edge_capedge_table
Where the variables come from
count_valuecomes frombucket_spread.input_varin the active BVM context:- balanced systems usually feed TC
- unbalanced systems usually feed RC or an effective RC-style value
edge_tablecomes frommanifest.betting.policy_vm.bucket_spread.kelly_params.edge_table- it is a lookup table keyed by integerized count values after the discretization rule in 2.5 Kelly Edge-Table Discretization
edge_slopecomes fromkelly_params.edge_per_tcif present, otherwisekelly_params.edge_slope, otherwise BJW falls back to0.005edge_capcomes fromkelly_params.edge_cap, otherwise BJW falls back to0.025
Interpretation
edge_tablemeans “for this count bucket, assume this per-unit edge”edge_slopemeans “increase modeled edge linearly as count rises”edge_capmeans “stop increasing the modeled edge beyond this ceiling”
These are authored model parameters, not values inferred from the current simulation at runtime.
Expected output
A modeled edge in units-per-unit-bet, used only for Kelly sizing.
Related formulas
- Kelly variance term: 2.3 Kelly Variance Model
- Kelly bet conversion: 2.4 Kelly Fraction and Bet Size
- Edge-table lookup rule: 2.5 Kelly Edge-Table Discretization
- Kelly saturation warning: 10.3 Kelly Cap Warning Threshold
Search terms
Kelly blackjack edge modeledge per true countedge cap
2.3 Kelly Variance Model¶
Status: Canonical runtime when a Kelly policy is used
Formula
variance = clamp(
variance_base + max(0, count_value) * variance_tc_multiplier,
1.0,
3.0
)
Primary locations
src/typescript/simulator_lite/src/betting_vm.tscalculateKellyUnits(...)
What it is for
Provides the variance term in the Kelly fraction model.
Provenance status
BJW-authored model/heuristic. The Kelly denominator concept is external, but BJW’s count-dependent variance parameterization and clamps are implementation/model choices.
Citation status
No verified citation recorded for this exact BJW variance model.
Variables
variance_basevariance_tc_multipliercount_value
Where the variables come from
variance_basecomes fromkelly_params.variance_base, otherwisekelly_params.base_variance, otherwise BJW falls back to1.3variance_tc_multipliercomes fromkelly_params.variance_tc_multiplier, otherwise BJW falls back to0.02count_valueis the same betting-context input described in 2.2 Kelly Edge Model
Interpretation
variance_baseis the modeled baseline variance at neutral or low countsvariance_tc_multipliersays how much modeled variance increases as count rises- the final
clamp(..., 1.0, 3.0)is a BJW guardrail to keep the Kelly denominator in a bounded range
Expected output
A positive modeled variance estimate for the current count.
Related formulas
- Kelly edge model: 2.2 Kelly Edge Model
- Kelly bet conversion: 2.4 Kelly Fraction and Bet Size
Search terms
Kelly variance blackjackvariance per true countfractional Kelly variance estimate
2.4 Kelly Fraction and Bet Size¶
Status: Canonical runtime when a Kelly policy is used
Formula
kelly_fraction = edge / variance
adjusted_kelly = kelly_fraction * fraction
raw_units = bankroll_scale * adjusted_kelly
units = clamp(round(raw_units), table_min, table_max)
Primary locations
src/typescript/simulator_lite/src/betting_vm.tscalculateKellyUnits(...)
What it is for
Turns the modeled edge and variance into an actual bet size.
Provenance status
Mixed. The f = edge / variance Kelly structure is a standard external concept; the specific edge/variance inputs feeding it in BJW come from the BJW-authored models in 2.2 Kelly Edge Model and 2.3 Kelly Variance Model.
Citation status
Exact reference recorded for the general Kelly concept: R1. No verified citation recorded for BJW’s exact blackjack notation and parameterization in this section.
Variables
edgevariancefraction: fractional Kelly multiplierbankroll_scale: Kelly bankroll sizing scale
Where the variables come from
edgeis the output of 2.2 Kelly Edge Modelvarianceis the output of 2.3 Kelly Variance Modelfractioncomes fromkelly_params.fractionorkelly_params.fractional_kellybankroll_scalecomes fromkelly_params.bankroll_scale, with BJW defaulting if it is omitted
Interpretation
bankroll_scale here is a Kelly model parameter carried in the policy VM, not the live bankroll balance being tracked by bankroll-stop or bankroll-goal features.
Related formulas
- Kelly edge model: 2.2 Kelly Edge Model
- Kelly variance model: 2.3 Kelly Variance Model
- Kelly edge-table discretization: 2.5 Kelly Edge-Table Discretization
Expected output
An integer bet size in BJW units.
Search terms
Kelly criterionfractional Kellyf = edge / variance
2.5 Kelly Edge-Table Discretization¶
Status: Canonical runtime when a Kelly edge table is used
Formula
count_index =
floor(count) if count >= 0
ceil(count) if count < 0
then clamp to the nearest lower available table key.
Primary locations
src/typescript/simulator_lite/src/betting_vm.tsgetEdgeFromTable(...)
What it is for
Maps a continuous count to a discrete lookup key in an edge table.
Citation status
No verified citation recorded. This is a BJW lookup/discretization rule for an authored Kelly edge table.
Search terms
discretized true count lookupfloor positive ceil negative count
2.6 Progression Bet Formulas¶
Status: Canonical runtime for progression policies
Formula
Martingale fast path:
units = base_units * 2^current_step
General BVM progression path:
units = next_units
where next_units is produced by progression-specific pre-round actions such as:
sequence progression: next_units = sequence[current_step]
Labouchere: next_units = first(sequence) + last(sequence)
percentage progression: next_units = pct(prev_bet)
then clamp to table max/min.
Primary locations
src/typescript/simulator_lite/src/betting_vm.tsgetProgressionUnits(...)- progression transpilation in
src/python/configurator/transpilers/betting_to_bvm.py
What it is for
Implements Martingale, sequence progressions like 1-3-2-6, Labouchere-style systems, and percentage progressions through the same VM.
Provenance status
BJW contract choice. These are implementations of authored betting-policy semantics carried in the BVM, not a single externally sourced blackjack formula.
Citation status
No verified citation recorded. This section documents BJW betting-policy execution semantics rather than a single literature formula.
Important note
The 2^current_step expression is only the Martingale-specific fast path. It is not the generic formula for every BJW progression policy.
Search terms
Martingaledoubling progression1-3-2-6 betting progressionLabouchere
2.7 State-Machine Special Calculation (total_loss * 0.40)¶
Status: Canonical runtime for authored state-machine policies, but repo-authored rather than literature-backed
Formula
units = max(1, floor(total_loss * 0.40))
Primary locations
src/typescript/simulator_lite/src/simulator.tsunitsFromAuthoredBetPolicy(...)
What it is for
Implements a custom “bet 40% of accumulated loss” rule for certain authored policies.
Variables
total_loss: state-machine-tracked cumulative loss
Where the variables come from
total_lossis the authored state-machine loss accumulator maintained in BJW bet-policy state- in the BVM-based path the parallel state variable is
total_loss_units - this rule is only activated when an authored state-machine policy names the matching special calculation
Interpretation
This is repo-authored betting logic, not a generic blackjack theorem or a simulator-wide bankroll formula.
Citation status
No verified citation recorded. This is a repo-authored state-machine rule rather than a verified external formula.
Expected output
An integer bet size that scales with accumulated loss.
Search terms
loss-recovery betting40 percent of total loss betting
3. Blackjack Engine and Settlement Formulas¶
Section provenance note
Most formulas in this section are standard blackjack rule/accounting mechanics or straightforward arithmetic identities over settled outcomes. This document does not yet carry exact book/page citations for each such rule.
Section citation status
No verified citation recorded section-wide. Most formulas here are direct consequences of blackjack rules or direct arithmetic over settled outcomes.
3.1 Hand Total with Ace Adjustment¶
Status: Canonical runtime
Formula
sum = Σ card_values with Ace initially counted as 11
while sum > 21 and aces > 0:
sum -= 10
aces -= 1
soft = (remaining_aces_counted_as_11 > 0)
Primary locations
src/typescript/simulator_lite/src/simulator.tshandTotal(...)
What it is for
Computes hard/soft hand totals for play, dealer rules, and settlement.
Search terms
blackjack hand total acessoft hand calculation
3.2 Dealer Play Rule¶
Status: Canonical runtime
Formula
if total > 17: stand
if total < 17: hit
if total == 17:
hit on soft 17 only when H17 is enabled
Primary locations
src/typescript/simulator_lite/src/simulator.tsdealerPlays(...)
What it is for
Executes dealer drawing rules under H17/S17.
Search terms
dealer hits soft 17S17 H17 rule
3.3 Blackjack Detection¶
Status: Canonical runtime
Formula
is_blackjack = (hand_length == 2) and (hand_total == 21)
Primary locations
src/typescript/simulator_lite/src/simulator.tsisBlackjack(...)
What it is for
Identifies naturals for peek/natural settlement.
3.4 Double Eligibility¶
Status: Canonical runtime
Formula
must have exactly 2 cards
if after split:
DAS must be allowed
if split aces: double_after_split_aces must be allowed
if DOA: allowed
else: only total 10 or 11
Primary locations
src/typescript/simulator_lite/src/simulator.tscanDouble(...)
What it is for
Applies table rules to doubling decisions.
Search terms
double on any twodouble 10 or 11 onlyDAS
3.5 Surrender Eligibility¶
Status: Canonical runtime
Formula
surrender_allowed and (not after_split or surrender_after_split_allowed)
Primary locations
src/typescript/simulator_lite/src/simulator.tscanSurrender(...)
What it is for
Applies late-surrender rules.
3.6 Insurance Decision Threshold¶
Status: Canonical runtime
Formula
Policy-threshold form:
take insurance if bucket >= threshold
with RC- or TC-based authored strings like dealer_upcard:A:TC>=3.
Primary locations
src/typescript/simulator_lite/src/simulator.tsshouldTakeInsurance(...)
What it is for
Applies authored insurance thresholds.
Search terms
insurance indexinsurance true count thresholdinsurance running count threshold
3.7 Insurance Settlement¶
Status: Canonical runtime
Formula
insurance_bet = main_bet / 2
if dealer_has_blackjack:
payout = 2 * insurance_bet
net = +2 * insurance_bet (profit-only tracking)
else:
payout = 0
net = -insurance_bet
summary-level corrected net:
insurance_net_units = 1.5 * payout_units - bet_units
Primary locations
src/typescript/simulator_lite/src/simulator.tssettleInsuranceBet(...)src/typescript/simulator_lite/src/simulator.tssummary finalization
What it is for
Tracks insurance separately from the main hand and then centralizes net reporting.
Variables
payout_units: profit-only 2:1 payout accumulationbet_units: total insurance stakes
Where the variables come from
payout_unitscomes fromcounters.insurance_payout_units, which is incremented insettleInsuranceBet(...)only on winning insurance eventsbet_unitscomes fromcounters.insurance_bet_units, which is incremented on every insurance bet regardless of outcome- both counters are then combined during summary finalization to produce
insurance_net_units
Why the summary uses 1.5 * payout_units - bet_units
At runtime, winning insurance payouts are tracked as profit-only 2 * bet, not returned stake plus profit.
If win_bet_units is the total insurance stake on winning events:
payout_units = 2 * win_bet_units
win_bet_units = payout_units / 2
true_net
= (+2 * win_bet_units) - (loss_bet_units)
= (+2 * win_bet_units) - (bet_units - win_bet_units)
= 3 * win_bet_units - bet_units
= 1.5 * payout_units - bet_units
So the 1.5 coefficient is not a blackjack payoff rule by itself; it is the algebra needed to reconstruct total insurance net from profit-only payout tracking plus total stake.
Expected output
Insurance wins/losses, net units, and derived insurance QA metrics.
Search terms
insurance 2:1 payoutinsurance side bet blackjack
3.8 Insurance Effective Probability and EV¶
Status: Canonical runtime for insurance diagnostics
Formula
effective_p = (payout_units / 2) / bet_units
ev_per_unit = 3 * effective_p - 1
Primary locations
src/typescript/simulator_lite/src/simulator.tsinsurance bucket outputssrc/typescript/simulator_lite/src/simulator.tsdebug.insurance_qa
What it is for
Reconstructs the implied win probability and EV of insurance from observed bucket results.
Variables
effective_p: estimated probability dealer hole card is ten, inferred from payoutsev_per_unit: expected profit per unit of insurance stake
Where the variables come from
effective_pis reconstructed from observed insurance bucket telemetry using the bucket’spayout_unitsandbet_units- those bucket-level inputs come from the same insurance settlement counters described in 3.7 Insurance Settlement
ev_per_unitis then derived from that reconstructedeffective_p
Why 3p - 1
Insurance pays +2 on a win and -1 on a loss:
EV = 2p + (-1)(1 - p) = 3p - 1
Search terms
insurance EV 3p - 1insurance break-even 1/3
3.9 Insurance Break-Even Calibration¶
Status: Canonical runtime for diagnostics
Formula
Simple calibration:
threshold = 1/3 + margin
margin = 0.00
Monotone-safe calibration:
threshold = 1/3 + margin
peff[i] >= peff[i-1] - epsilon
eligible if insured_events >= min_events or bet_units >= min_bet_units
with current monotone-safe defaults:
margin = 0.01epsilon = 0.005min_events = 500min_bet_units = 1000
Primary locations
src/typescript/simulator_lite/src/simulator.tscomputeInsuranceCalibration(...)src/typescript/simulator_lite/src/simulator.tscomputeMonotoneSafeCalibration(...)src/typescript/simulator_lite/src/simulator.tscheckMonotonicity(...)
What it is for
Builds recommended insurance thresholds from observed bucket profitability.
Provenance status
BJW-authored model/heuristic. The 1/3 break-even point is a standard insurance concept, but the margin, monotonicity rule, event thresholds, and monotone-safe construction are BJW diagnostic heuristics.
Citation status
No verified citation recorded for BJW’s exact calibration heuristic.
Search terms
insurance break-even probability one thirdinsurance threshold calibrationmonotonic insurance index
3.10 Natural, Surrender, Win/Loss/Push Settlement¶
Status: Canonical runtime
Formula
player natural result = blackjack_payout * bet
surrender result = -0.5 * base_bet
regular win = +wager
regular loss = -wager
push = 0
Primary locations
src/typescript/simulator_lite/src/simulator.tsnatural handling and hand settlement- shadow-action settlement inside decision telemetry
What it is for
Produces the actual round/hand PnL the rest of BJW summarizes.
Important note
blackjack_payout is read from manifest.payouts.blackjack.
Common values are:
1.5for3:21.2for6:5
BJW does not hardcode only those two values; it uses the numeric payout carried in the manifest.
Search terms
blackjack 3:2 payoutblackjack 6:5 payoutlate surrender half betpush zero outcome
3.11 Initial Pair Probability¶
Status: Canonical runtime QA
Formula
Pr(pair in d decks) = 13 * C(4d, 2) / C(52d, 2)
implemented as:
pairs_per_rank = (4d * (4d - 1)) / 2
total_pairs = (52d * (52d - 1)) / 2
pair_rate = 13 * pairs_per_rank / total_pairs
Primary locations
src/typescript/simulator_lite/src/simulator.tstheoreticalPairRate(...)
What it is for
Checks that shoe randomness is producing plausible initial pair frequency.
Search terms
pair probability blackjack d deckcombinatorics same rank two cards
3.12 Pair/Split/Win-Loss-Push/Volume Rates¶
Status: Canonical runtime
Formula
initial_pair_rate = initial_pairs_total / rounds
rounds_with_split_rate = rounds_with_split / rounds
winRateRound = roundWins / rounds
lossRateRound = roundLosses / rounds
pushRateRound = roundPushes / rounds
winRateHand = handWins / hands
lossRateHand = handLosses / hands
pushRateHand = handPushes / hands
avgHandsPerRound = hands / rounds
Primary locations
src/typescript/simulator_lite/src/simulator.ts
What it is for
Creates result summary rates and QA checks.
4. Canonical Runtime Performance and Risk Formulas¶
4.1 Observed Sample Variance via Welford¶
Status: Canonical runtime
Formula
Online update:
delta = x - mean
count += 1
mean += delta / count
delta2 = x - mean
m2 += delta * delta2
final sample variance:
variance = m2 / (n - 1)
sd = sqrt(max(0, variance))
Primary locations
src/typescript/simulator_lite/src/simulator.tsrecordHandOutcome(...),recordRoundOutcome(...)
What it is for
Tracks observed per-hand and per-round variance directly from simulated outcomes.
Provenance status
Standard external concept. Welford’s online variance update is standard statistics, applied here to blackjack outcomes.
Citation status
Exact reference recorded: R2.
Variables
x: realized hand or round net result in unitsmean,m2,count: Welford accumulators
Where the variables come from
- hand-level
xvalues come from realized hand results recorded throughrecordHandOutcome(...) - round-level
xvalues come from realized round net results recorded throughrecordRoundOutcome(...) - those hand and round net values are produced by settlement logic in Section 3 and passed into the Welford accumulators during play
mean,m2, andcountare the mutable online accumulators maintained for hands and rounds separately
Expected output
Observed sample variance/SD for hand outcomes and round outcomes.
Search terms
Welford algorithmonline sample variance
4.2 EV per Hand, per Round, per Initial Bet, and Average Bet¶
Status: Canonical runtime
Formula
EV_per_hand = sumNetUnits / handsTotal
EV_per_round = sumNetUnits / actualRoundsPlayed
initialBetUnitsTotal = Σ (bet_units * frequency)
EV_per_initial_bet_units = sumNetUnits / initialBetUnitsTotal
EV_per_initial_bet_pct = 100 * sumNetUnits / initialBetUnitsTotal
avgBetUnits = totalBetUnits / totalRoundsPlayed
Primary locations
src/typescript/simulator_lite/src/simulator.ts- extracted again in
scripts/validation/compare_to_reference.py
What it is for
Produces BJW’s core profitability measures.
Provenance status
Standard bookkeeping identities over BJW runtime accumulators, with BJW-specific choices about which accumulators are exposed and named.
Citation status
No verified citation recorded. These are bookkeeping identities over BJW runtime accumulators.
Variables
sumNetUnits: total realized profit/losshandsTotal: total hands playedactualRoundsPlayed: total rounds playedbetUnitsHistogram: initial-bet histogramtotalBetUnits: total wager actually placed across played rounds
Where the variables come from
sumNetUnitsis the top-level net accumulator updated from settled round outcomeshandsTotalcomes from hand-level settlement countingactualRoundsPlayedcomes from accepted rounds in the main loopbetUnitsHistogramis built from initial round bets onlytotalBetUnitsis built from actual round wager exposure and can include doubles/splits on played roundsinitialBetUnitsTotalis reconstructed frombetUnitsHistogram
Important note
avgBetUnits is the average total wager per played round from betting.totalBetUnits / betting.totalRoundsPlayed.
That is not always the same as average initial bet, because totalBetUnits can include additional wager exposure from doubles and splits on rounds that were actually played.
BJW’s canonical runtime risk_primary formulas do not use avgBetUnits directly, but helper scripts, optimizers, and reporting code often use it for normalization and spread comparison.
Search terms
EV per handIBAinitial bet advantagetotal win divided by initial bet
4.3 Primary Risk Basis Selection¶
Status: Canonical runtime
Formula
if counting and count-based betting:
primary basis = per_round
else:
primary basis = per_hand
Primary locations
src/typescript/simulator_lite/src/simulator.tssrc/typescript/simulator_lite/src/index.tssyncObservedRiskContract(...)
What it is for
Decides whether risk_primary uses observed round variance or observed hand variance.
Provenance status
BJW contract choice. This is not an external blackjack theorem; it is the current canonical result-contract rule BJW applies after simulation.
Citation status
No verified citation recorded. This is a BJW result-contract rule.
Important note
syncObservedRiskContract(...) is the step that writes:
summary.observed- top-level per-hand aliases like
summary.sdPerHandUnits - canonical
summary.risk_primary
after worker aggregation and pooled-variance recomputation.
4.4 SCORE¶
Status: Canonical runtime
Formula
SCORE = 1,000,000 * EV^2 / Variance
Primary locations
src/typescript/simulator_lite/src/simulator.tssrc/typescript/simulator_lite/src/index.tssrc/python/wonk_tools/results.pysrc/python/bjw/catalog/results.pyscripts/validation/compare_to_reference.pyscripts/validation/intake_reference.py- display/reporting duplicates in
scripts/sim_ui.py,scripts/gui/widgets/simulation_manager.py
What it is for
Produces the standardized risk-adjusted comparison metric BJW reports.
Provenance status
Standard blackjack/AP concept, but the exact citation is not recorded here. The formula is well known in blackjack literature; BJW’s additional choice is which EV/variance basis feeds it.
Citation status
No verified citation recorded for an exact source in this pass.
Variables
EV: canonical EV on the current risk basisVariance: canonical variance on the current risk basis
Where the variables come from
- for active runtime results, both values come from
summary.risk_primary - that object is populated by
syncObservedRiskContract(...)after pooled aggregation and basis selection - for non-counting runs this usually means per-hand observed EV/variance
- for counted runs on this branch this usually means per-round observed EV/variance
Search terms
SCORE blackjack1,000,000 * EV^2 / varianceBlackjack Attack SCORE
4.5 Desirability Index (DI)¶
Status: Canonical runtime
Formula
DI = 1000 * EV / SD
Primary locations
src/typescript/simulator_lite/src/simulator.tssrc/typescript/simulator_lite/src/index.tssrc/python/wonk_tools/results.pysrc/python/bjw/catalog/results.pyscripts/validation/compare_to_reference.py- display/reporting duplicates in
scripts/sim_ui.py,scripts/gui/widgets/simulation_manager.py
What it is for
Produces BJW’s standard DI metric.
Provenance status
Standard blackjack/AP concept, but the exact citation is not recorded here. BJW’s runtime contract defines which EV/SD basis feeds the DI.
Citation status
No verified citation recorded for an exact source in this pass.
Search terms
Desirability Index blackjackDI = 1000 EV / SDBlackjack Attack DI
4.6 Canonical Runtime N0¶
Status: Canonical runtime
Formula
N0 = (SD / EV)^2
Primary locations
src/typescript/simulator_lite/src/simulator.tssrc/typescript/simulator_lite/src/index.tssrc/python/bjw/catalog/results.py(via1_000_000 / SCORE)scripts/validation/compare_to_reference.py
What it is for
Produces BJW’s canonical risk_primary.n0 and preserves the algebraic identity:
Provenance status
Standard blackjack/AP concept, but the exact citation is not recorded here. BJW’s runtime contract defines the basis and therefore the unit semantics.
Citation status
No verified citation recorded for an exact source in this pass.
DI^2 = SCORE
SCORE * N0 = 1,000,000
only when all three metrics are derived from the same EV and variance basis.
Search terms
N0 blackjackN-zerohands to one standard deviation
Important note
This is not the same formula used in some helper/experiment scripts, which compute a 95%-confidence hands-to-profit quantity using 1.96; see 8.5 Helper/API N0(Confidence) Formula and 11.2 N0 Definition Drift.
4.7 Risk of Ruin (RoR) Approximation¶
Status: Canonical runtime
Formula
RoR ≈ exp(-2 * bankroll * edge / variance)
Primary locations
src/typescript/simulator_lite/src/simulator.ts- duplicate reporting/optimizer copies in
scripts/compare_spreads.py,scripts/optimize_spread.py
What it is for
Approximates the probability of eventual ruin for a positive-edge game.
Provenance status
Standard external approximation, not an exact blackjack-specific theorem. BJW uses it as an approximation layer over simulated EV/variance.
Citation status
No verified citation recorded for the exact approximation source used here.
Variables
bankroll: bankroll in unitsedge: EV on the primary risk basisvariance: variance on the same basis
Where the variables come from
bankrollcomes from bankroll settings or bankroll-analysis inputs expressed in betting unitsedgeis the canonical EV chosen on the same basis assummary.risk_primaryvarianceis the canonical variance on that same basis
Interpretation
The approximation only makes sense if bankroll, edge, and variance all share the same unit basis.
Important note
This is a gambler’s-ruin-style exponential approximation, not an exact blackjack theorem for BJW’s variable-bet counted games.
It is most defensible as a large-bankroll, positive-drift approximation. Reliability degrades when bankroll is small, edge is small, or the process departs materially from an i.i.d. random walk.
Search terms
risk of ruin exponential approximationexp(-2BR/variance)blackjack bankroll approximation
4.8 Bankroll Sizing from Target RoR¶
Status: Canonical runtime
Formula
bankroll = -ln(target_ror) * variance / (2 * edge)
Primary locations
src/typescript/simulator_lite/src/simulator.ts
What it is for
Inverts the RoR approximation to recommend bankroll sizes for target ruin probabilities.
Provenance status
Derived from the same standard approximation described in 4.7 Risk of Ruin (RoR) Approximation, so its limits are the same.
Citation status
No verified citation recorded beyond the approximation note in 4.7 Risk of Ruin (RoR) Approximation.
Search terms
bankroll from risk of ruin-ln(RoR) variance / 2 edge
5. Parallel Aggregation and Pooled Variance Formulas¶
Section provenance note
This section is standard statistics, not blackjack-specific literature.
Section citation status
Exact reference recorded for the combined-variance algorithms discussed here: R3.
5.1 Pooled Mean and Variance for Merged Worker Results¶
Status: Canonical runtime aggregation
Formula
Two-sample pooled mean:
pooled_mean = (n1 * mean1 + n2 * mean2) / (n1 + n2)
Two-sample pooled variance:
pooled_var =
((n1 - 1) * var1
+ (n2 - 1) * var2
+ n1 * n2 / (n1 + n2) * (mean1 - mean2)^2)
/ (n1 + n2 - 1)
Multi-worker pooled variance:
var_pooled = Σ[(n_i - 1) * var_i + n_i * (mean_i - mean_pooled)^2] / (N - 1)
Primary locations
src/typescript/simulator_lite/src/index.ts
What it is for
Combines worker-local variances without losing between-worker mean differences.
Important note
This is a standard statistics combine formula, not a blackjack-specific result.
Search terms
pooled variance formulaparallel variance combinebetween group variance termcombining variance from batchesChan Golub LeVeque variance
6. Per-Bucket and Decision-Telemetry Formulas¶
Section provenance note
These are BJW runtime bookkeeping and sample-moment formulas built from simulator telemetry. They are mostly arithmetic identities over recorded outcomes rather than externally named blackjack formulas.
Section citation status
No verified citation recorded section-wide. These are BJW telemetry and bookkeeping formulas.
6.1 EV-by-Bucket Variance¶
Status: Canonical runtime telemetry
Formula
EV_per_hand = sumNetUnits / hands
variance =
(sumNetUnitsSq - sumNetUnits^2 / hands) / (hands - 1)
SD = sqrt(max(0, variance))
avgBetUnits = totalBetUnits / rounds
Primary locations
src/typescript/simulator_lite/src/simulator.tsevByBucket
What it is for
Computes EV and SD per count bucket from raw aggregates.
Search terms
sample variance from sum of squaresEV by true count
6.2 Exact Decision Variable SD¶
Status: Canonical runtime telemetry
Formula
Same sample-variance identity as above, applied to the exact decision variable map.
Primary locations
src/typescript/simulator_lite/src/simulator.tsexactDecisionVarStats
What it is for
Checks monotonicity and non-bucketed decision-value behavior.
6.3 Decision Telemetry Action EV/SD¶
Status: Canonical runtime telemetry
Formula
avgEV = sumEV / count
variance = (sumEVSq - sumEV^2 / count) / (count - 1)
sdEV = sqrt(max(0, variance))
Primary locations
src/typescript/simulator_lite/src/simulator.tsdecision_telemetry- pooled again in
src/typescript/simulator_lite/src/index.ts
What it is for
Measures counterfactual action EV/dispersion for deviation discovery.
7. Legacy and Diagnostic Variance Formulas¶
7.1 Legacy chapter10 Variance Decomposition¶
Status: Diagnostic/legacy only
Formula
Per-hand and per-round versions both use:
E_b = sum_b / count
E_w = sum_w / count
E_b2 = sum_b2 / count
E_w2 = sum_w2 / count
E_bw = sum_bw / count
Var_b = E_b2 - E_b^2
Var_w = E_w2 - E_w^2
Cov_bw = E_bw - E_b * E_w
variance = E_b2 * Var_w + Var_b * E_w^2 + 2 * Cov_bw * E_b * E_w
sd = sqrt(max(0, variance))
Primary locations
- raw telemetry capture in
src/typescript/simulator_lite/src/simulator.tsrecordBetOutcome(...),recordRoundBetOutcome(...) - recompute in
scripts/validation/run_formula_recompute_audit.py
What it is for
Legacy BJW decomposition of variable-betting variance from bet/outcome accumulators.
Variables
b: bet sizew: normalized per-unit outcome
Where the variables come from
- per-hand
bandware captured byrecordBetOutcome(...) bis the realized wager on that handw = hand_outcome / b- per-round
bandware captured byrecordRoundBetOutcome(...) bis the initial round betw = round_outcome / initial_bet- the raw sums
sum_b,sum_w,sum_b2,sum_w2,sum_bw, andcountare stored in legacy variance telemetry and recomputed byrun_formula_recompute_audit.py
Important note
This is not BJW’s canonical counted-risk formula on this branch.
Its provenance is currently repo-local and unresolved as an external citation. It should not be treated as a verified Schlesinger, Griffin, or Epstein formula unless an exact source is found.
Citation status
No verified citation recorded.
Search terms
variance of product bet outcome covariancevariable betting variance decomposition
7.2 Legacy di_adjusted Reconstruction¶
Status: Diagnostic/legacy only
Formula
E[bet^2] = Σ(bet^2 * frequency) / rounds
base_variance = E[bet^2] * Var_w
var_bet_component = Var_b * E_w^2
covariance_component = 2 * Cov_bw * E_b * E_w
variance = base_variance + var_bet_component + covariance_component
sd = sqrt(variance)
count_correlation_factor = variance / base_variance
Primary locations
scripts/validation/run_formula_recompute_audit.py
What it is for
Audits older result files that still contain di_adjusted.
Citation status
No verified citation recorded.
Provenance status
Legacy unsourced. This block exists to recompute and audit older BJW outputs, not as a currently validated canonical variance formula.
7.3 RMS SD Validation Heuristic¶
Status: Diagnostic/validation only
Formula
E_b = Σ(bet * count) / N
E_b2 = Σ(bet^2 * count) / N
rms_bet = sqrt(E_b2)
non-counting expected SD scaling:
SD_expected = baseline_SD * rms_bet
counting heuristic:
SD_expected = baseline_SD * rms_bet * sqrt(0.71)
Primary locations
src/python/simulator_support/sd_validation.py
What it is for
Sanity-checks whether observed SD is in a plausible range for a bet histogram.
Important note
This is a simulator-side heuristic, not BJW’s canonical runtime variance model.
The repo does not currently carry a verified external citation for the 0.71 factor. Treat it as a legacy BJW validation heuristic, not a sourced blackjack formula.
Citation status
No verified citation recorded.
Search terms
RMS bet scalingsqrt(E[bet^2])variance reduction factor 0.71
8. Reporting, Helper, Optimizer, and Experiment Formulas¶
This section covers formulas outside the simulator that still produce blackjack/AP claims from result files.
8.1 Sharpe-Like Ratio¶
Status: Reporting/helper/optimizer
Formula
Sharpe_like = EV / SD
Primary locations
scripts/compare_spreads.pyscripts/optimize_spread.pyscripts/ml/fitness_evaluator.pyscripts/ml/analyze_results.pyscripts/analysis/results_to_markdown.pyscripts/sim_ui.pyscripts/gui/widgets/simulation_manager.py
What it is for
Used as a generic risk-adjusted comparison metric in optimizers and UI.
Provenance status
Standard generic ratio concept, but not BJW’s canonical blackjack DI unless the 1000 scaling and correct runtime basis are applied.
Citation status
No verified citation recorded for an exact source in this pass.
Important note
This is not BJW’s standard DI unless the script explicitly multiplies by 1000.
Search terms
Sharpe ratioEV over SD
8.2 Reweighting Formulas for Spread Optimization¶
Status: Optimizer/ML only
Formula
EV_new = Σ(freq_i * EV_i * bet_i)
Variance_new = Σ(freq_i * SD_i^2 * bet_i^2)
SD_new = sqrt(Variance_new)
AvgBet = Σ(freq_i * bet_i)
Sharpe = EV_new / SD_new
Primary locations
scripts/optimize_spread.pyscripts/ml/fitness_evaluator.py
What it is for
Approximates the performance of alternative bet ramps from one baseline simulation.
Provenance status
BJW-authored model/heuristic. This is an internal approximation method for optimization, not a verified exact law for recomputing counted-strategy EV/variance under arbitrary new spreads.
Citation status
No verified citation recorded.
Variables
freq_i: bucket frequency fromevByBucketEV_i: per-hand EV in bucketifromevByBucket[*].evPerHandUnitsSD_i: per-hand SD in bucketifromevByBucket[*].sdPerHandUnitsbet_i: proposed bet size in bucketi
Where the variables come from
freq_iis built from baselineevByBuckettelemetry by dividing bucket hands by total baseline handsEV_iandSD_iare read directly from the baseline result’s per-bucket telemetrybet_icomes from the candidate spread allocation being optimized or scoredAvgBetis then reconstructed fromfreq_i * bet_i, not read directly from runtimerisk_primary
Important note
These optimizers currently reweight hand-level bucket telemetry, not canonical counted risk_primary round-basis risk. That makes them a useful approximation tool, but not a direct implementation of the new counted-risk contract.
Search terms
reweighting bet spread optimizationbucket frequency weighted EV
8.3 Helper/API DI Formula¶
Status: Reporting/helper
Formula
DI = 1000 * EV / SD
Primary locations
src/python/wonk_tools/results.pyget_di(...)
What it is for
Convenience API for scripts and reports.
Provenance status
Helper wrapper around the DI concept in 4.5 Desirability Index (DI). The main risk is semantic drift, not different mathematics.
Citation status
No verified citation recorded beyond the base DI concept note in 4.5 Desirability Index (DI).
8.4 Helper/API SCORE Formula¶
Status: Reporting/helper
Formula
SCORE = 1,000,000 * EV^2 / variance
Primary locations
src/python/wonk_tools/results.pyget_score(...)
Provenance status
Helper wrapper around the SCORE concept in 4.4 SCORE. The main risk is basis drift if callers assume the wrong variance source.
Citation status
No verified citation recorded beyond the base SCORE concept note in 4.4 SCORE.
8.5 Helper/API N0(Confidence) Formula¶
Status: Reporting/helper
Formula
N0_confidence = (z * SD / EV)^2
with:
z = 1.96for 95%z = 2.576for 99%
Primary locations
src/python/wonk_tools/results.pyget_n0(...)
What it is for
Returns a “hands needed for chosen confidence of being ahead” quantity.
Provenance status
Helper/reporting convention. This is not BJW’s canonical runtime N0 and should be treated as a confidence-style derivative quantity.
Citation status
No verified citation recorded for an exact source in this pass.
Important note
This is a different definition from runtime risk_primary.n0; see 4.6 Canonical Runtime N0 and 11.2 N0 Definition Drift.
Units depend on the basis of EV and SD:
- with per-hand inputs, the output is in hands
- with per-round inputs, the output is in rounds
On current results, methodology='primary' returns summary.risk_primary.n0, whose unit follows the canonical runtime basis rather than always meaning hands.
Search terms
hands to 95% confidence of profit1.96 SD over EV squared
8.6 Catalog Fallback Formulas¶
Status: Reporting/helper
Formula
DI = 1000 * EV / SD
SCORE = 1,000,000 * EV^2 / variance
N0 = 1,000,000 / SCORE
Primary locations
src/python/bjw/catalog/results.py
What it is for
Lets the results browser backfill DI/SCORE/N0 when result files do not explicitly provide them.
Provenance status
Fallback reporting formulas derived from the canonical metric relationships, used when richer runtime fields are unavailable.
Citation status
No verified citation recorded beyond the base metric sections they derive from.
8.7 Result-Comparison Confidence Heuristics¶
Status: Reporting/UI
Formulas
Simple change percentages:
pct_change = |new - old| / |old| * 100
and heuristic thresholds such as:
< 1%: likely noise< 3%: may be within single-run variance
Primary locations
scripts/sim_ui.pyassess_comparison_confidence(...)
What it is for
Provides operator-facing warnings when optimization improvements are probably too small to trust.
Provenance status
BJW-authored heuristic. The percentage cutoffs are operator-facing warning thresholds, not sourced statistical decision rules.
Citation status
No verified citation recorded.
8.8 Win per Hand / Win per Round / EV% of Average Bet / Per-100-Hand Conversions¶
Status: Reporting/helper
Formulas
win_per_hand = net_units / hands
win_per_round = net_units / rounds
ev_pct_of_avg_bet = 100 * EV_per_hand / avg_bet
EV_per_100_hands = EV_per_hand * 100
SD_per_100_hands = SD_per_hand * sqrt(100) = SD_per_hand * 10
EV_basis_points = EV_fraction * 100 * 100
rate_pct = 100 * rate
Primary locations
scripts/sim_ui.pyscripts/gui/widgets/simulation_manager.pyscripts/analysis/analyze_kelly.pyscripts/experiments/experiment1_rule_variation_matrix.pysrc/python/wonk_tools/results.py
What it is for
Turns simulator outputs into more operator-friendly units.
Provenance status
Standard unit-conversion arithmetic over BJW result fields.
Citation status
No verified citation recorded. These are direct unit conversions.
9. Statistical Confidence and Comparison Formulas¶
Section provenance note
This section is standard statistics and hypothesis-testing math, not blackjack-specific literature.
Section citation status
Exact reference recorded for confidence-interval and mean-comparison background: R4. Other formulas in this section are standard statistics, but no additional exact citation is recorded subsection-by-subsection in this pass.
9.1 Standard Error / 95% CI on EV¶
Status: Statistical comparison
Formula
Single-run EV CI:
SEM = SD / sqrt(n)
CI_95_half_width = 1.96 * SEM
EV delta between two independent runs:
SEM_delta = sqrt((SD_a / sqrt(n_a))^2 + (SD_b / sqrt(n_b))^2)
CI_95_half_width = 1.96 * SEM_delta
BJW also expresses some of these in percent or basis points:
CI_95_EV_pct = 1.96 * SD / sqrt(n) * 100
CI_95_EV_bp = EV_to_bp(1.96 * SD / sqrt(n))
Primary locations
scripts/experiments/experiment1_rule_variation_matrix.pyscripts/experiments/common.pyscripts/experiments/experiment2_score_di_n0_matrix.pyscripts/experiments/experiment3_ko_warmline_penetration.py
What it is for
Quantifies uncertainty around EV or EV deltas.
Search terms
standard error mean95% confidence interval 1.96difference of two means standard error
9.2 Standard Error of EV-by-Bucket Difference¶
Status: Statistical comparison
Formula
variance = (sum_sq - sum^2 / n) / (n - 1)
ours_sd = sqrt(variance)
ours_se = ours_sd / sqrt(n)
se_delta = sqrt(ours_se^2 + ref_se^2)
pass if |delta| <= 2 * se_delta
Primary locations
scripts/validation/compare_to_reference.py
What it is for
Assesses whether BJW EV-by-TC differs materially from the reference tool’s EV-by-TC.
9.3 t-Critical / Mean ± CI for Repeated Runs¶
Status: Statistical comparison
Formula
CI = t_(0.95, df) * std / sqrt(n)
or via SciPy:
stats.t.interval(0.95, n-1, loc=mean, scale=stats.sem(samples))
Primary locations
scripts/validation/compare_to_reference.pymean_ci95(...)scripts/ml/analyze_results.py
What it is for
Builds confidence intervals when multiple independent simulation runs exist.
9.4 Z-Score for Run-to-Run Comparison¶
Status: Statistical comparison
Formula
SE_diff = sqrt(SD1^2 / N1 + SD2^2 / N2)
z = EV_diff / SE_diff
Primary locations
scripts/gui/widgets/comparison_tool.pyscripts/analyze_penetration_effects.pyscripts/validate_exact_decision_var_monotonicity.py
What it is for
Scores how statistically meaningful an observed EV difference is.
Search terms
z score difference of meansSE(diff) = sqrt(sd1^2/n1 + sd2^2/n2)
9.5 Two-Sample t-Test for Sharpe Comparison¶
Status: Statistical comparison
Formula
Implemented through SciPy:
stats.ttest_ind(candidate_sharpes, baseline_sharpes)
Primary locations
scripts/ml/analyze_results.py
What it is for
Tests whether candidate spread Sharpe means differ significantly from baseline Sharpe means.
9.6 Minimum Sample Heuristic for EV Precision¶
Status: Statistical comparison / experiment design
Formula
Used in some experiment scripts as a back-of-the-envelope minimum rounds-per-bucket rule:
min_rounds ≈ (1.96 * SD / desired_precision)^2
Current hard-coded example:
MIN_BUCKET_ROUNDS_FOR_SIG = (1.96 * 1.1 / 0.01)^2
Primary locations
scripts/experiments/experiment3_ko_warmline_penetration.pyscripts/experiments/experiment7_rc_penetration_surface.py
What it is for
Defines a rough minimum bucket sample size before treating a bucket EV as statistically useful.
Search terms
sample size for confidence interval widthrequired n for desired standard error
10. QA Threshold and Sanity-Check Formulas¶
Section provenance note
Unless otherwise stated, thresholds in this section are BJW-authored QA heuristics rather than externally sourced blackjack constants.
Section citation status
No verified citation recorded section-wide unless a subsection says otherwise.
10.1 Initial Pair Baseline Tolerance¶
Status: Runtime QA
Formula
initial_pair_rate = initial_pairs_total / rounds
deviation = |initial_pair_rate - theoretical_pair_rate|
PASS if deviation <= 0.6 percentage points
WARN if deviation <= 1.2 percentage points
FAIL otherwise
Primary locations
src/typescript/simulator_lite/src/simulator.tsperformInstrumentationChecks(...)
What it is for
Checks that pair frequency looks plausible for a random shoe source.
10.2 Rounds-With-Split Bound¶
Status: Runtime QA
Formula
rounds_with_split_rate = rounds_with_split / rounds
expected bound: rounds_with_split_rate <= 0.08
Primary locations
src/typescript/simulator_lite/src/simulator.tsperformInstrumentationChecks(...)
What it is for
Warns when split frequency looks suspiciously high.
10.3 Kelly Cap Warning Threshold¶
Status: Runtime QA
Formula
pct_bets_at_cap = 100 * betsAtCap / totalRoundsPlayed
warning if pct_bets_at_cap > 10
Primary locations
src/typescript/simulator_lite/src/simulator.ts
What it is for
Warns that the Kelly model is frequently slamming into table limits, which can make the spread unrealistic.
11. Known Semantic Drifts You Should Audit Carefully¶
11.1 DI Scaling Drift¶
There are two DI-style formulas in the repo:
- standard DI:
DI = 1000 * EV / SD
- dimensionless EV/SD ratio, sometimes still labeled “DI” in old experiment/report code:
ratio = EV / SD
Files to inspect
- standard DI: runtime, helpers, comparator, UI
- dimensionless ratio:
scripts/experiments/experiment2_score_di_n0_matrix.py,scripts/experiments/experiment3_ko_warmline_penetration.py,scripts/experiments/common.py
Primary definitions
- Canonical runtime DI: 4.5 Desirability Index (DI)
- Helper/API DI: 8.3 Helper/API DI Formula
- Dimensionless ratio used in some optimizers: 8.1 Sharpe-Like Ratio
11.2 N0 Definition Drift¶
There are two N0-style formulas in the repo:
- runtime/canonical:
N0 = (SD / EV)^2
- confidence-style “hands to 95% confidence”:
N0_95 = (1.96 * SD / EV)^2
Files to inspect
- canonical runtime N0: simulator, aggregator, catalog, comparator
- confidence-style N0:
src/python/wonk_tools/results.py,scripts/experiments/common.py,scripts/experiments/experiment2_score_di_n0_matrix.py
Primary definitions
- Canonical runtime N0: 4.6 Canonical Runtime N0
- Confidence-style helper N0: 8.5 Helper/API N0(Confidence) Formula
11.3 Counted-Risk Basis Drift in Older Scripts¶
Some older experiment/report code still assumes counted runs should read summary.chapter10 and/or per-hand counted SD.
Files to inspect
scripts/experiments/experiment2_score_di_n0_matrix.pyscripts/experiments/experiment3_ko_warmline_penetration.pyscripts/experiments/common.pywhenprefer_ch10=Truesrc/python/wonk_tools/results.pyold methodology options
Primary definitions
- Canonical counted-risk basis: 4.3 Primary Risk Basis Selection
- Legacy diagnostic variance: 7.1 Legacy
chapter10Variance Decomposition
11.4 Top-Level Per-Hand Fields vs risk_primary¶
Some UI/reporting scripts still compute DI/SCORE/Sharpe from:
summary.evPerHandUnits
summary.sdPerHandUnits
summary.varPerHandUnits
instead of reading:
summary.risk_primary
That means counted-run displays in those scripts can still show per-hand risk math even though canonical counted risk is now per-round.
Files to inspect
scripts/sim_ui.pyscripts/gui/widgets/simulation_manager.pyscripts/compare_spreads.pyscripts/analysis/results_to_markdown.pyscripts/ml/analyze_results.py
Primary definitions
- Contract-sync step: 4.3 Primary Risk Basis Selection
- Canonical SCORE/DI/N0: 4.4 SCORE, 4.5 Desirability Index (DI), 4.6 Canonical Runtime N0
12. What You Will Not Find in BJW¶
You will not find a closed-form “blackjack edge formula” for the simulator’s main EV result.
BJW’s core engine:
- deals cards
- applies rules and policy lookups
- settles outcomes
- measures EV/variance from observed results
So for the most important outputs, the core “formula” is often:
simulate outcomes, then compute sample moments from the realized data
That is why many of the most important audit targets are:
- count conversion
- betting logic
- settlement logic
- variance basis selection
- post-simulation summaries
not a single house-edge equation.
13. Fast Search Guide¶
If you want to verify BJW formulas against books or external material, these are the terms most likely to get you to the right place:
true count = running count / decks remainingtrue count rounding away from zerofractional Kelly blackjackedge / variance KellySCORE blackjackDesirability Index blackjackN0 blackjackrisk of ruin exp(-2BR/V)insurance EV = 3p - 1insurance break-even 1/3pair probability 13*C(4d,2)/C(52d,2)sample variance from sum of squaresWelford online variancestandard error of difference of means95% CI 1.96
14. Minimum File Set to Read First¶
If you want the shortest possible manual audit path, start here:
src/typescript/simulator_lite/src/simulator.tssrc/typescript/simulator_lite/src/betting_vm.tssrc/typescript/simulator_lite/src/index.tssrc/typescript/simulator_lite/src/utils.tssrc/python/wonk_tools/results.pyscripts/validation/compare_to_reference.pyscripts/validation/run_formula_recompute_audit.pysrc/python/simulator_support/sd_validation.py
Then read the experiment/reporting duplicates only if you want to audit naming drift and non-canonical analysis math.
15. Exact References Recorded¶
R1. Kelly (1956)¶
J. L. Kelly Jr., "A New Interpretation of Information Rate," Bell System Technical Journal, 35(4), 917-926, 1956.
- Official publication page: Nokia Bell Labs
- DOI: 10.1002/j.1538-7305.1956.tb03809.x
Used in this document
- 2.4 Kelly Fraction and Bet Size
R2. Welford (1962)¶
B. P. Welford, "Note on a Method for Calculating Corrected Sums of Squares and Products," Technometrics, 4(3), 419-420, 1962.
Used in this document
- 4.1 Observed Sample Variance via Welford
R3. Chan, Golub, and LeVeque (1983)¶
T. F. Chan, G. H. Golub, and R. J. LeVeque, "Algorithms for Computing the Sample Variance: Analysis and Recommendations," The American Statistician, 37(3), 242-247, 1983.
- DOI: 10.1080/00031305.1983.10483115
- Public PDF mirror used in this pass: PKU mirror
Used in this document
- 5.1 Pooled Mean and Variance for Merged Worker Results
R4. NIST/SEMATECH e-Handbook Confidence and Comparison Pages¶
NIST/SEMATECH e-Handbook of Statistical Methods, especially the confidence-interval and process-comparison pages used in this pass.
- Handbook home: NIST/SEMATECH e-Handbook
- Confidence intervals overview: 7.1.4 What are confidence intervals?
- Confidence-interval approach with unknown standard deviation: 7.2.2.1 Confidence interval approach
- Two-process mean comparison background: 7.3.1 Do two processes have the same mean?
Used in this document
- 9.1 Standard Error / 95% CI on EV
- 9.2 Standard Error of EV-by-Bucket Difference
- 9.3 t-Critical / Mean +- CI for Repeated Runs
- 9.4 Z-Score for Run-to-Run Comparison
- 9.5 Two-Sample t-Test for Sharpe Comparison