kalmari.app / Strategies
Strategy

Arena — methodology

2026-07-25 — chapters became strategies. The single "Arena" strategy was split by migration arena-strategy-split-v1: the closed World Cup chapter is now strategy WC2026 (status discontinued — record on /explore only), the live baseball chapter is strategy MLB (status shadow, feed-visible). DeriveStrategy maps audit_version=wc2026 → WC2026 and audit_version=arena (the tag MLB runs still post under) → MLB. This doc describes the shared method; "Arena" below refers to the method.

Source: audit · Current version: 1 · Legacy tags: audit_version=arena (live MLB chapter, run_id ending -arena) and audit_version=wc2026 (retired World Cup chapter, run_id ending -wc2026) — see Chapters below. Early rows (Jul 7–9) carry pick_kind=forced; from 2026-07-10 picks post as real experimental picks (pick_kind="") — shown in the Telegram feed with full thesis, but off the public scoreboard and never auto-copied (non-scored audit_version).

Gauntlet's question, answered with Keel's tooling. Gauntlet showed that the palmtree ensemble, forced to forecast every World Cup game, mostly echoed the market back (<1¢ average claimed edge — prediction-market snapshots and odds-saturated search anchored every forecaster). Arena replaces the ensemble with the deep-research audit: one Claude session per game day that researches each match like Keel researches a mispricing candidate — lineups, injuries, form, tactical matchup, primary sources — and is forced to hold exactly one leg per game, even when its best available edge is negative.

The comparison this sets up:

Gauntlet Arena Keel
Coverage forced, every leg forced, one pick/game chosen (scan & reject)
Analysis 6-LLM ensemble, minutes deep research, Keel-grade deep research
Question raw ensemble calibration does research create edge when selection is removed? production baseline

Chapters

Arena's method is sport-agnostic; only the series and prompt change. Each chapter gets its own audit_version so the records never blend:

Chapter Series Job Tag Period Record
World Cup KXWCGAME kalshi-wc-arena (paused) wc2026 Jul 7 – Jul 19 2026, daily 10 picks, 5W-5L
MLB KXMLBGAME kalshi-mlb-arena arena from Jul 25 2026, Sat only live, ~15/wk

The WC rows were audit_version=arena until the arena-wc2026-retag-v1 migration (2026-07-24) moved them to wc2026, so the MLB run starts clean. DeriveStrategy maps both tags to strategy Arena — the strategy identity, exposure flags and feed badge are unchanged; only the audit_version bucket split. Neither tag is in scoredVersions, so both stay off /performance and off auto-copy.

Cadence: weekly, and why the cut is by day

Arena covers every game on the dates it runs — that is the whole design. The MLB chapter runs one full Saturday slate a week (~15 picks) rather than all ~13.4 games every day (~94/wk).

Cutting by day preserves forced coverage exactly; the only choice is the date, which is uncorrelated with where mispricing sits. Cutting by game — capping to N games/day — would reintroduce the selection step Arena exists to eliminate, collapsing it into a worse Keel and voiding the comparison against Gauntlet and Keel. If the sample ever needs widening, add a second day (Sunday, also a 15-game slate); never sub-sample a day.

Saturday specifically: a full 15-game slate (Mon/Thu are getaway days at 7–12), the week's best retail liquidity, no collision with the Keel fleet (Mon–Thu), and picks resolving early Sunday (see Resolution below). Cost is ~$12.30/run at ~$0.82/game.

How it works

  1. kalshi-mlb-arena Cloud Run job, Saturdays pre-game (6am PT), running the standard mispricing workflow with AUDIT_VERSION=arena and CATEGORY=MLB (prompts/mlb-forced-audit.md, Opus 5 — half Fable 5's token price, which is what makes ~13 games/day affordable). The workflow picks the prompt from CATEGORY and fails loudly on an unmapped one.
  2. The prompt scopes to today's games (date and first pitch parsed from the event ticker — occurrence_datetime is expected expiration, ~3h after the start, and sports close_time sits days past the game) and mandates a probability-first discipline: estimate the leg probabilities from evidence before reading the order book, then compare and choose the best edge. If every leg is negative, hold the least-bad one and say so — that datum is the point.
  3. Picks post with full thesis/rationale, every leg probability in the rationale, cluster = game event, pick_kind="" (feed-visible with the experimental tag; off scoreboard and auto-copy), audit_version=arena.

What differs on MLB

What to measure

Future / decision points

Resolution

Not blocked on close_time — this is a common misreading of the schema, so it is worth stating precisely.

Kalshi does stamp MLB close_time at first pitch +72h (verified: all 15 markets, zero variance), and UnresolvedSignalsForResolution is gated on it. But that is not the path that resolves sports picks. The drift-snapshot job (signals_jobs.go) polls every live signal whose last snapshot is older than snapshotStaleAfter (18h) on an hourly loop, and resolves immediately when SettlementOutcome sees a determined result — regardless of close_time. result is authoritative even when Kalshi reports status inconsistently.

Measured on the World Cup chapter: picks resolved 260–329h before their close_time. Steady-state lag once the feature had bedded in was ~18–24h after the match (Jul 10 game → resolved Jul 11 07:57; Jul 11 → Jul 12 07:57).

For MLB that means a Saturday slate — entry snapshot at 06:00, next poll ~18h later, all games long settled by then — resolves early Sunday, comfortably before the following Saturday's run.

The only remaining latency is the 18h snapshot cadence, not close_time. Worth revisiting only if a faster feedback loop is ever needed; at a weekly cadence it is slack, not a constraint.

Version history

See this strategy's live track record

Every pick this strategy has ever published — resolved results, P&L, and calibration vs the market — is public and auditable.

Open in the Strategy Explorer →