The World Cup Bot Setup Guide (Everything Since Issue 3)
Shadow phases, risk gates, cross-venue paper, and a pre-kickoff checklist — no picks.
Mexico kicks off against South Africa today. If you starred World Cup Bot after Issue 3 but never cloned it, this is the week that matters.
On June 3 I open-sourced the repo and wrote about why shadow mode exists.
The bot has moved since launch — again, literally today. LP logic is on v8 as of this morning’s tournament-launch hardening push. Risk gates ship on by default. Cross-venue is still paper-first. Match-shock is an optional in-play lane you should not flip on casually. I am not publishing picks. I am publishing the setup path I would run on a fresh machine right now.
This issue is a snapshot, not a static manual. Through the World Cup I will keep pushing to main — logic bumps, RUNBOOK edits, conviction hygiene, ops fixes. Pull the repo and skim docs/RUNBOOK.md daily before you plan. The version pin at the top of RUNBOOK is the live truth; Substack does not auto-update when I ship a fix at 2am. Star or watch the repo on GitHub if you want commit notifications. I will post here when something material changes, but do not wait on me — check RUNBOOK.
Not financial advice. Default is shadow mode (DRY_RUN=true). Live order POST requires non-US egress per Polymarket geoblock. Fork with your own keys.
Issue 3 was the trailer
Issue 3 explained architecture: conviction YAML, calendar guard, versioned JSONL ledger, cross-venue alerts. It did not walk you through a full first week as an operator.
That gap matters because LP on advance markets is carry risk. You may rest quotes for weeks. Group results move fair value. A bid that was fine last Tuesday can be toxic six hours before kickoff if nothing pulls it. Shadow mode exists so you learn to trust the cancel window before POST exists.
If you have not read Issue 3, start there for the why. This issue is the how. Full command tables live in docs/RUNBOOK.md on GitHub — I mirror the blocks you actually need so you do not tab between Substack and the repo all day.
Issue 3: https://outlierweekly.substack.com/p/i-open-sourced-the-world-cup-lp-bot
Version pin — read this before you plan
Every material release should have an honest version snapshot. Ledger rows carry logic_version. If your PnL scope looks wrong, you are probably mixing eras.
WORLD CUP BOT — RUNBOOK SNAPSHOT
Effective: 2026-06-11
Repo: github.com/cemini23/world-cup-bot @ main
Public launch: 2026-06-03 — Outlier Weekly Issue 3
Package: world-cup-bot 0.1.0
Conviction config: config/conviction.yaml version 5
LP logic: wc_advance_lp_v8 (deployed 2026-06-11)
Risk gates: wc_risk_gates_v1 (on by default)
Cross-venue paper: wc_cross_venue_paper_v1
Cross-venue auto-exec: wc_cross_venue_exec_v1 (off by default)
Match-shock: wc_match_shock_v1 (off by default)Issue 3 cited wc_advance_lp_v4 at launch. Main has since run through v5 → v6 → v7 → v8 in one week. v8 (today): streak sizing from position_exit rows, live geoblock is a hard FAIL on US egress (do not brush past preflight), CLI loads .env automatically. When you change quoter, fill handler, or calendar logic mid-tournament, bump config/strategy_logic_versions.yaml and use pnl --scope all --by-version for honest post-mortems.
If your ledger still tags wc_advance_lp_v6 or older, you are not on current main. git pull and re-run preflight before the next plan --record.
Split-ledger trap: use one LEDGER_PATH / WC_LEDGER_PATH for every plan --record session. Split files make shadow-status under-count dry-run days. SHADOW.md calls this out because I have done it.
Phase 0 — Install and discovery
git clone https://github.com/cemini23/world-cup-bot.git && cd world-cup-bot
cp .env.example .env
pip install -e ".[dev]"
pip install -e ".[live]"
world-cup-bot preflight
world-cup-bot shadow-status --min-phase 0
world-cup-bot risk-status
world-cup-bot scan --conviction --liquidity
world-cup-bot calendar --cancel-window
world-cup-bot ui # optional → http://localhost:8765Pass: Gamma returns markets. Preflight has no FAIL except geoblock WARN when shadowing from the US. That WARN is expected. Reading markets and shadow mode work from the US. Live POST does not.
The shipped conviction.yaml is an example tier list (version 5). Replace it with your own research. Do not treat example tiers as picks.
Phase 1 — Dry-run quote loop (≥3 separate days)
This is the phase most people skip too fast.
world-cup-bot plan --liquidity-gate
world-cup-bot plan --record --liquidity-gate
world-cup-bot pnl --scope current
world-cup-bot shadow-status --min-phase 1plan --record appends quote intents to JSONL and tags logic_version: wc_advance_lp_v8 on current main. Every plan also writes negative_filter_summary with skip counts — yaml_skip, human_review, liquidity_gate, mid_band. If you see heavy skips, fix conviction tiers and depth bands before you tune quote speed. Faster bad quotes are still bad quotes.
Night three of my Phase 1 I opened the UI Ready tab because I was tired of grepping JSONL. A team I expected was missing. I assumed the UI was broken. calendar --cancel-window had that team inside the pre-kickoff window. The quoter was right to stay quiet. Shadow mode is where you learn to trust the guard over your gut.
Phase 2 — Fill watch (venue reads; still dry on POST)
Requires L2 API creds in .env.
world-cup-bot watch --verbose --record
world-cup-bot rewards sync --record
world-cup-bot pnl --scope current
world-cup-bot ledger backfill-pnl --verify
world-cup-bot fill --team <TEAM> # dry-run single fill / exit path inspectwatch --record reconciles WebSocket against REST, applies kill-switch on bad fills, and logs to the same ledger. rewards sync --record pulls CLOB liquidity incentives — reward farming is not alpha, but PnL that ignores rewards lies to you.
Shadow fill counts without pnl_usd show $0 realized. That is a measurement gap, not proof of zero edge.
Phase 3 and 4 — egress and live pilot
Order POST is geo-blocked from the US. Run preflight on a non-US host with DRY_RUN=true first. Geoblock PASS and clob_auth PASS are the gates. On v8, attempting the live path from the US surfaces a hard FAIL in preflight — not a WARN you can ignore. Shadow and read-only work from the US; live POST is non-US only.
Live pilot — only after Phases 0–3, non-US only, small size:
export DRY_RUN=false
export WC_LIVE_PLAN_ACK=1
export WC_BANKROLL_FROM_WALLET=1
world-cup-bot preflight
world-cup-bot risk-status
world-cup-bot cancel --cancel-window
world-cup-bot plan --record --liquidity-gate
world-cup-bot watch --recordBefore you trust live PnL: export Polymarket trades and run world-cup-bot venue-reconcile compare polymarket-export.csv (≥20 rows) to catch bot journal vs venue CSV drift.
Do not enable plan --advisor on timers for an initial pilot. Manual discipline fails when the match schedule gets dense. That is why the cancel window is code.
Risk gates (on by default)
Since Issue 3, streak sizing and portfolio PnL gates ship in config/risk_gates.yaml. They complement the absolute daily cap in operating.yaml.
world-cup-bot risk-statusIn shadow, portfolio gates defer — no wallet required. Live, bankroll defaults to free USDC plus resting BUY collateral (WC_BANKROLL_FROM_WALLET=1 in .env.example).
This is the kind of thing you want running before the tournament schedule compresses. Not because it guarantees edge — because it stops one bad afternoon from becoming an unbounded afternoon.
Cross-venue — scan and paper first
Module 6 compares Polymarket vs Kalshi gaps for cohort pairs in config. Default path is scan + paper only.
world-cup-bot cross-venue-scan --once --record
world-cup-bot cross-venue-pnl --refresh
world-cup-bot cross-venue-exec attempt --force --dry-runLive auto-exec additionally requires WC_CROSS_VENUE_AUTO_EXEC=1, WC_CROSS_VENUE_EXEC_ACK=1, preflight PASS, Kalshi + Polymarket creds, and DRY_RUN=false on non-US egress.
Cross-venue alerts are not execution. Gaps close. Fees and leg risk eat naive arb. For the retail lens on when PM and Kalshi disagree with traditional books, see the Gambling & Betting Wiki — books vs PM divergence pairs with alert-only scanning here.
Match-shock — optional, separate lane
In-play match-market shock recovery (wc_match_shock_v1) is orthogonal to advance LP. Master switch: config/shock_match.yaml → enabled: false. It does not gate SHADOW Phases 1–4 for advance quoting.
world-cup-bot match-shock-discover --out data/local/match_markets.json
WC_SHOCK_ENABLED=1 world-cup-bot match-shock-record --discovery data/local/match_markets.json
world-cup-bot tournament-ops checkSpec: docs/MATCH_SHOCK_V1.md. Live ladder POST requires paper soak plus WC_MATCH_SHOCK_LIVE=1 and WC_MATCH_SHOCK_LIVE_ACK=1.
Do not enable match-shock live POST on the same wallet as advance LP without explicit operator sign-off. Two strategies, one wallet, one schedule — that is how you discover coupling you did not model.
Pre-kickoff checklist (opening match day)
Advance LP and cross-venue paper can run before the opening match. Module 8 needs a separate flip if you want in-play tape.
world-cup-bot tournament-ops check
world-cup-bot shadow-status --min-phase 1
world-cup-bot calendar --cancel-windowIf you do one thing today: run tournament-ops check and read the output. It is the fastest honest picture of whether your fork is tournament-ready or still misconfigured.
Tournament-week detail: docs/TOURNAMENT_KICKOFF.md in the repo.
On match days with kickoffs affecting your quoted teams: confirm calendar --cancel-window pulled resting quotes. Do not add new advance-LP size on match day without running the LP safety reminder script (scripts/run_wc_lp_safety_reminder.sh).
Retail hygiene overlay (shadow)
Recent shadow overlays add retail-fee awareness without changing your live sizing until you sign off. Sports taker fees around ~0.75% at 50¢ mean you should model 1–2% round-trip before widening caps. Prefer limit posts — maker-first LP. Config lives in k108_retail_hygiene.yaml. Semantic routing for cross-venue pairs is in wc_semantic_rules.yaml — do not pair markets that resolve on different rules text.
Re-run LP safety DR before conviction YAML edits: bash scripts/run_wc_lp_safety_reminder.sh
Where this repo sits in the stack
World Cup Bot is execution code. It is not the whole stack I use to think about markets.
Layer
Link
This issue + RUNBOOK
you are here
Repo + SHADOW.md
https://github.com/cemini23/world-cup-bot
Landing
https://cemini23.github.io/world-cup-bot/
Gambling wiki
https://github.com/cemini23/Gambling-wiki
Issue 3
Issue 4
Agent toolkit
vet · wikilint · phase0 · https://github.com/cemini23/agent-toolkit-demo
The toolkit repos audit YAML and docs before conviction changes land in production. They do not trade.
What this still fails when
Adverse selection is real. Shadow mode proves wiring, not edge. A cancel window reduces kickoff pick-off. It does not eliminate informed flow on slow news days.
Reward sync is not alpha. Cross-venue paper ledger is not executed arb. Tournament variance can dominate a small pilot. $POLY eligibility is unknown.
Still fails when news flow front-runs your resting bid. LP is a discipline sport.
What to do next
Every tournament day:
git pull→ read RUNBOOK version pin →preflight→tournament-ops checkStar or fork https://github.com/cemini23/world-cup-bot (watch for commits)
Run Phase 0–1 shadow before live POST — three separate dry-run days, one ledger
Read
docs/RUNBOOK.mdwhen you need the full command table — it will change this weekBrowse Gambling-wiki for contract-type context before you size YAML caps
Subscribe to Outlier Weekly — I will post when tournament-week repo changes are worth a full note
Reply here or on X with the shadow step you skipped and regretted later.
Thanks for reading.
Outlier Weekly · Not financial advice ·


