Profile match officials and wire their tendencies so the bot prices the ~205 cards/fouls/penalty questions on who is officiating, not just the teams. Dry-run by default.
All 52 FIFA-2026 head referees are already profiled in ../referees/
(stats.json = source of truth, profile.md generated). This runbook covers assigning a
referee to a fixture and refreshing/adding a profile.
FIFA names each match crew ~24-48h before kickoff.
- Find the fixture slug:
python -c "from bot.data.odds import fixture_slug; print(fixture_slug('KOR','CZE'))"→south-korea-vs-czechia. - Add it to
../referees/assignments.json:{"assignments": {"south-korea-vs-czechia": "<referee-slug>"}} - Add the fixture to that referee's
stats.jsonassignmentsarray, regenerate the profile (step C), and link it fromgames/NNN-*/game.md§7. - Score:
python -m bot run --offline --today— the assigned ref now tilts the cards/fouls/ penalty markets (visible inpredictions/<date>.jsonlas therefereefield).
For each referee, gather per-match (both teams) tendencies with cited sources (statshub, valuestats, footymetrics, worldreferee, transfermarkt):
- yellow cards/match, red cards/match, penalties/match, fouls/match, 2nd-half card share
- crew (2 assistant referees + VAR + 4th official), style, strengths, weaknesses, market strategy
Set
confidence(high/medium/low) by sample size & source quality. Honest nulls where unverified — never guess. Thin samples → low confidence → the ensemble shrinks the tilt.
- Edit
referees/<slug>/stats.json(schema:schema/referee_stats.schema.json). python scripts/validate_referee_stats.py# must be cleanpython scripts/gen_referee_profile_md.py# regenerates profile.md (never hand-edit it)
The bot scales each team's card/foul λ by referee_rate / competition_avg (clamped 0.65-1.5) and
sources penalty/red rates from the referee. A strict ref lifts total card/foul and penalty
markets; "more cards than opponent" comparisons barely move (both teams rise together).
comp_avg.yellow_per_matchMUST be the referee's real domestic-league average — not the flat 3.8 default. The tilt isref_yellow / comp_yellow; a global 3.8 denominator re-encodes domestic card inflation (CONMEBOL / La Liga / Liga I refs price 1.15-1.41× by league culture, not strictness) and hurts the backtest (proven: flat-3.8 on all 36 settled refs dropped RBP 868.5→811.5, cards +77→+20). Runpython scripts/enrich_referee_comp_avg.py(documented per-league map, research/RESEARCH_referee_data.md §2) so the tilt measures genuine strict-for-their-league. WorldReferee international samples are the best WC-context prior (≈0.75× domestic for card-heavy leagues).
- Dry-run — never
--submitwithout explicit go-ahead. - Cite every number; low confidence for thin samples (Brier punishes confident-wrong).
stats.jsonis the source of truth;profile.mdis generated.- The head referee is modeled; ARs/VAR are documented for completeness, not given fabricated rates.