What this app optimizes for
Bettor does not predict winners. It line-shops across a fixed set of sportsbooks and ranks outcomes where (1) the price looks “sharp” in a simple sense and (2) you get a better number at one book than the average of the books that post that line.
Where the numbers come from
Live odds and schedules come from The Odds API. Soccer uses moneyline (h2h) markets in bulk; NBA, NFL, and MLB use player prop markets (and MLB home-run markets) per game, within API limits.
Which books count
Only these books are included: DraftKings, FanDuel, and Fanatics. Lines from other books are ignored.
When a line becomes a candidate
For each outcome (a team on the moneyline, or a specific player prop side), the app
requires at least two of those books to post a price. If only one book
has it, that outcome is skipped so you can actually compare prices. The next section
explains exactly how best_decimal_odds is chosen from the books that do
qualify.
How best_decimal_odds is calculated
The Odds API returns each line as a numeric price on each outcome. Bettor
requests decimal odds, so that field is treated as a
decimal odds quote (e.g. 2.10 means you win 2.10× your stake
including stake return — higher is a “better” price for the bettor on that side).
The backend walks the event payload book by book, but only for the allowed bookmakers listed above. For each bet type:
-
Moneyline (h2h): it groups prices by outcome name — typically each
team and sometimes a draw — using only the
h2hmarket. - Player props: it groups by a key that combines the market (e.g. points), the player / description, the bet side (over/under or yes/no), and the line point when the sportsbook posts one, so the same prop at different numbers stays separate.
For every posting that survives grouping, the raw price is parsed as a
float. Entries are dropped if the value is missing, not a number, or
≤ 1.0 (invalid as decimal odds for a bet).
For one logical bet (one row in the UI), let the surviving decimal quotes from different
books be d1, d2, … dn with at least two books
(n ≥ 2). Then:
best_decimal_odds_raw = max(d1, d2, …, dn)
In words: best_decimal_odds is the largest decimal odds among the allowed books that posted that exact outcome — i.e. the longest price you can get without leaving those three books. The field best_book is whichever book offered that maximum (if two books tie on the same number, the implementation picks one deterministically).
The value shown in the API/JSON is best_decimal_odds rounded to
three decimal places. Implied probability and rank score use the same
underlying best price before that display rounding.
Separately, average_decimal_odds (used for “Edge %”) is the arithmetic mean of those same per-book decimals, not the best price — so edge measures how far above the mean your best book sits.
Implied probability
“Implied %” is the naive conversion from your best decimal price:
implied = 1 / best_decimal_odds
This is not a de-vigged or market-wide fair probability — it is just the break-even rate implied by the single best price you can bet.
Edge % (line shopping)
“Edge %” measures how much better the best price is than the average of your books on that exact outcome:
edge_pct = (best_decimal − average_decimal) / average_decimal × 100
Rank score (how lines are ordered)
Each candidate line gets a rank score that blends favoring a higher implied probability (tighter favorites / shorter prices in that naive sense) and a higher edge % (more disagreement between books on your side):
rank_score = 0.55 × (implied × 100) + 0.45 × edge_pct
Within each game, lines are sorted by rank_score descending. The app keeps
the top three per game by default.
Minimum implied filter (and fallback)
First, only lines with implied probability (from the best decimal) above a league-specific floor are kept: ≥ 52% for most sports, ≥ 30% for MLB. If that would show nothing useful for the day, the app relaxes once and recomputes — non-MLB lines use ≥ 50%, MLB lines ≥ 28%. You’ll see a banner when that fallback runs.
Disclaimer
This is a tool to compare posted prices, not betting advice. Odds change; past results don’t guarantee future outcomes. Gamble only what you can afford to lose.