B Besalt Labs Bracket Simulator

How It Works

The bracket is a tree. The sim is a pile of weighted coin flips.

Here's a bit more on what's under the hood.

Site snapshot -
Locked real games -
Games left in bracket -
Current favorite -

Step 1

Start with one clean bracket tree

We model the men's tournament as a linked tree of 67 games, including the First Four. In this build, that bracket tree is hand-encoded from the official 2026 NCAA bracket page and stored as structured data inside the app.

The important part is that every game points to the next game... so a winner in one place feeds the right slot later.

Step 2

Lock the games that already happened

Real results come from the ESPN public scoreboard endpoint. When a tournament game is final, we map that matchup onto the bracket tree and hard-lock the winner.

That is what the "locked real games" number means on the home page. It is not a count of simulated outcomes. It is the count of games that are already on the board in real life, so the simulator never flips them back.

The "games left in bracket" number is just the other side of that. It starts at 67 before the tournament begins and drops as the real bracket gets filled in. Check back after a few games to see how it updates, and let me know at dan@besaltlabs.ai if anything breaks .

Step 3

Turn Elo and official NCAA style stats into game odds

Team strength starts with the Warren Nolan Elo feed, then adds a style layer from seven official NCAA stat pages: scoring margin, three-point percentage, three-point percentage defense, turnover margin, offensive rebounds per game, free throw percentage, and assist to turnover ratio.

powerRating = Elo + 20 x avg(z(SCR MAR), z(3FG%), z(3FG% defense, inverted), z(turnover margin), z(offensive rebounds), z(FT%), z(AST/TO))

Those NCAA stats get converted to z-scores, averaged equally, and translated into a modest Elo-style bump. The defensive stat gets inverted so lower opponent three-point percentage helps instead of hurts. It is still a simple model. It is just a better simple model than pure Elo.

formSigma = 12 + 4 x stdev(all seven official NCAA style z-scores)
P(team A beats team B) = 1 / (1 + 10 ^ ((effectivePowerB - effectivePowerA) / 400))

Then we add a tournament-form band. Teams with more uneven stat profiles swing wider from run to run. Still transparent. Just a little less chalky.

Step 4

Run the tree a lot

A single tournament run means walking the tree from the First Four through the title game, resolving each live matchup with that weighted coin flip. Then we do it again. And again. And again.

Round odds

How often each team survives to the next checkpoint.

Recommended bracket

A top-down pick path that stays internally valid instead of choosing each game in isolation.

Highlight facts

Biggest upset lane, best Cinderella, chaos region, and the loudest market disagreement.

Loading a live matchup...

This uses the same rating gap as the simulator. Click it a few times and the favorite still loses sometimes. That is the whole point.

The easy mistake is picking every unresolved game independently and ending up with a bracket that argues with itself. We do not do that. The recommended bracket is built from conditional winner counts inside each matchup, so the whole path stays coherent.

There is also a product question hiding in here. The most likely bracket is not always the highest-EV bracket for a pool. If the scoring rules reward being right when everyone else is wrong, the best bracket usually gets a little stranger.

Step 5

Is 1,000 runs enough?

1,000 runs is enough to watch the bracket move. It is fast, directional, and more than enough for an interactive pass.

1,000 runs x games left in bracket = weighted coin flips

The simulation button is mostly rating lookups, random draws, and counter updates. JavaScript handles that easily because the arithmetic is small and the bracket tree is fixed.

For the page snapshot, more runs are better. So the site uses a larger cached batch than the button. The interaction stays quick. The page snapshot stays steadier.

Step 6

Where markets fit

Markets are compare-only in this version. The live comparison cards on the page pull round qualification lines from Kalshi event markets and line them up next to the model.

That gives us the fun part: where the model is richer than the market (higher probability), where the market is cooler than the model (lower probability), and where both sides quietly agree. We also keep the Polymarket market docs in the source set for future reference. This page is not currently displaying live Polymarket prices.

Step 7

Where the EV version goes next

A pool optimizer has a different job than a straight winner model. It cares about your scoring system, how many entries are in the pool, and which obvious picks everybody else is likely to make.

That is where this goes next: safest bracket, balanced bracket, and highest-EV bracket. The chaos bracket is already live. Same tree. Same simulation engine. Different target.

Data

Live inputs and references