world_cup: FIFA soccer betting scenario boilerplate#242
Open
cyruszhang wants to merge 2 commits into
Open
Conversation
New `world_cup` scenario mirrors NBA's wiring for FIFA competitions
(men's WC, women's WC, club WC, qualifiers). A single trial builder
takes a `league` param so one module serves all FIFA codes.
- data/world_cup/: ESPN soccer API wrapper, state tracker w/ soccer
status names + halves/ET/shootout periods, store that polls summary
+ plays and emits curated Pydantic stat models
(SoccerTeamMatchStats / SoccerPlayerMatchStats covering possession,
shots, passes, tackles, fouls, cards)
- world_cup/: trial builder (`register_trial_builder("world_cup")`),
agent, formatters (1H/2H/ET1/ET2/PEN labels), datastream subclass
- cross-cutting: AnyDataEvent union, DEFAULT_IMPORTS, sport_type Literal
- trial_params/world-cup-moneyline.yaml: default league fifa.world,
polymarket stream stubbed out pending game-level WC markets
- tests: 59 new tests against real ESPN fixtures captured via proxy
for CONMEBOL qualifier event 684665 (Ecuador 1-0 Argentina)
Workspace fix: drop the orphaned `packages/dojozero-agent-runner`
(no pyproject.toml on this branch) from `[tool.uv.workspace] members`
so uv and pre-commit hooks work.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wires the world_cup scenario into the dashboard scheduler so trials are
discovered, launched, and monitored automatically off ESPN's soccer
scoreboard. Daily tier targets 2025 Club WC fixtures for backtest
validation; prod tier targets the 2026 men's WC w/ the full NBA-style
persona × LLM matrix.
- WorldCupGameFetcher: per-league fetcher (sport=soccer, league=fifa.*)
with a soccer-specific scoreboard parser that maps ESPN status.type.name
(id 28 / 45 / etc.) onto the canonical 1=scheduled / 2=in_progress /
3=finished scheme used elsewhere in the scheduler.
- Hardens _parse_odds_data against None entries (ESPN's soccer scoreboard
emits null providers).
- _scheduler.py: register_source validation accepts "world_cup";
_sync_source and fetch_games_for_batch dispatch on sport_type and
instantiate WorldCupGameFetcher with the per-source FIFA league;
_get_game_status_info reads `world_cup_league` from scheduled metadata.
- _expand_compact_trial_source: tier YAML may set `league:` which gets
injected into the expanded scenario_config so daily can target
fifa.cwc while prod uses fifa.world.
- _SOCCER_STATUS_NAME_MAP: replace fictional STATUS_AFTER_EXTRA_TIME with
the real ESPN name STATUS_FINAL_AET (verified live: CWC 2025 QF Al Hilal
4-3 Man City, event 735949).
- trial_sources/{base,daily,prod}/world_cup.yaml: base ships data_streams
+ agent_template + schedule defaults (pre_start_hours 2.0, sync 1h);
daily runs 1 game/day with pundit on fifa.cwc; prod runs unlimited
games on fifa.world w/ all six personas.
- Backtest replays: end-to-end fixtures + tests for Chelsea 3-0 PSG final
(event 735958, 191 plays, FT) and Al Hilal 4-3 Man City QF (event 735949,
264 plays, AET — exercises STATUS_FINAL_AET).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a new
world_cupscenario that mirrors NBA's wiring, parameterised by FIFA league code so a single module serves the men's WC, women's WC, club WC, and all six qualifying confederations.WorldCupExternalAPI(league=…)), state tracker with soccer status names (STATUS_FIRST_HALF/STATUS_HALFTIME/STATUS_FULL_TIME/STATUS_FINAL_PEN/…) and halves/ET/shootout period semantics, store that pollssummary+playsand emits curated Pydantic stat models (SoccerTeamMatchStats,SoccerPlayerMatchStats: possession, shots, passes, tackles, fouls, cards). End-of-match detected via ESPNtype.typeslugs (end-regular-time,end-extra-time,end-shootout, …) so locale changes can't break it.register_trial_builder("world_cup", …)) withleagueparam validated against 9 known FIFA codes; thin agent + datastream subclass; formatters with soccer period labels (1H/2H/ET1/ET2/PEN).AnyDataEventunion members,DEFAULT_IMPORTS,sport_type: Literal[..., "world_cup"],world_cup_leaguemetadata field.league: fifa.world. Polymarket stream commented out with a note: the 2026 WC tournament-winner market is event-level only (no game-level markets up yet); the factory remains registered so it can be flipped on later.Workspace fix bundled
packages/dojozero-agent-runner/has source files but nopyproject.tomlon this branch (belongs to a parallel agent-refactor workstream). Thepackages/*glob caused everyuvinvocation — including pre-commit hooks — to fail. Listed members explicitly to unblock builds without touching the other workstream. One-line revert when that branch re-lands itspyproject.toml.Out of scope (flagged with TODO comments)
store_typesdoes not yet include polymarket. Switch on when game-level WC markets go live.Test plan
uv run pytest packages/dojozero/tests/test_data_world_cup.py packages/dojozero/tests/test_world_cup_formatters.py packages/dojozero/tests/test_world_cup_trial.py— 59/59 passuv run pytest packages/dojozero/tests/(no integration) — 1034 pass, no regressionsuv run pyrighton all touched files — 0 errorsuv run ruff check+ruff-format— clean (pre-commit hooks pass)uv run dojo0 run --params trial_params/world-cup-moneyline.yamlwith a realespn_game_id(deferred — needs a scheduled WC match or a CONMEBOL qualifier in season)🤖 Generated with Claude Code