I've been playing FIFA's official fantasy game for the 2026 World Cup, and like any engineer, I immediately wanted to over-engineer my team selection.
## The Setup
FIFA Fantasy for the 2026 World Cup works like most fantasy football games — you pick 15 players within a budget, score points based on real match events (goals, assists, clean sheets, etc.), and get a limited number of free transfers between rounds. There are also one-time boosters: a Wild Card for unlimited transfers, a Maximum Captain to double your top scorer's points, and others.
The twist that makes World Cup fantasy interesting is **elimination**. In a club season, every team plays every week. In a World Cup, half the field goes home after the group stage. Bad team selection doesn't just cost you points this round — it costs you players for the rest of the tournament.
## What I Built
With help from GitHub Copilot, I put together a local CLI toolkit that pulls live data, models tournament progression, and recommends transfers.
The pipeline looks like this:
1. **Fetch FIFA data** — player prices, stats, fixtures, and squad info from FIFA's public JSON endpoints
2. **Fetch market odds** — implied win probabilities from Polymarket's prediction markets for each national team
3. **Enrich my roster** — fuzzy-match my squad by name to FIFA player IDs to get accurate prices and stats
4. **Run the optimizer** — Monte Carlo simulation of group stage outcomes and knockout advancement, scoring each possible transfer plan by expected future points minus hit costs
The whole thing runs in one command:
```bash
./scripts/run_round.sh --free-transfers 2 --max-paid-transfers 2 --rounds-ahead 4 --sims 2000
```
## The Model
### Team strength
Each national team gets a composite rating from three signals:
- **Price prior** — average price of the top 11 players on the squad (expensive players tend to be better)
- **Results metrics** — points per game and goal difference from completed group matches
- **Market prior** — normalized Polymarket implied win probability
The blended rating feeds a logistic model for head-to-head match outcomes.
### Group stage simulation
I simulate remaining group matches using Poisson-sampled scorelines, then rank teams by points/GD/GF to determine which 32 advance. Because the 2026 World Cup uses a 48-team format, the best 8 third-placed teams also qualify — so I track that too.
### Knockout simulation
From the Round of 32 onward, I run bracket simulations where each matchup uses the same logistic win-probability model. After 2,000 simulations, each team has an estimated probability of reaching R32, R16, QF, SF, the Final, and winning.
### Player value
A player's value to my team is a blend of:
- Recent form (weighted avg points, last-round points)
- Their team's probability of advancing to each future round
- Position-specific fixture multipliers (defenders benefit more from clean sheet odds)
### Transfer optimization
For each possible combination of 1–4 transfers, I score the resulting squad and subtract any hit cost (−3 points per transfer beyond the free allocation). The optimizer returns the best plan for each hit-level so I can decide how aggressive to be.
## Round 3 Results
After three group stage rounds, my scores have been:
| Round | Points |
|---|---:|
| Round 1 | 57 |
| Round 2 | 74 |
| Round 3 | 81 |
Round 3 was the best yet. Key moves:
- **Out:** Kenan Yildiz (Turkey, 6.7% qualification probability) and Antonio Rüdiger (Germany DEF, poor form, avg 1.0 pts)
- **In:** Felix Nmecha (Germany MID) and Alexander Freeman (USA DEF, £4.0, last round 16 points)
- **Booster:** Maximum Captain — Bellingham delivered 28 points this round
The model correctly identified Yildiz as the main elimination risk (Turkey had ~7% R32 probability) and flagged Rüdiger as the weakest performer by expected value among safe-nation picks.
## What Prediction Markets Added
The most interesting part of the model is blending FIFA player prices with Polymarket odds. Player prices capture historical squad quality but lag on current form and bracket position. Prediction markets are forward-looking — they incorporate recent results, injuries, and bracket luck in real time.
Top market-implied win probabilities going into the knockouts:
| Team | Win probability |
|---|---:|
| France | 18.9% |
| Argentina | 14.6% |
| Spain | 13.8% |
| England | 10.8% |
| Portugal | 7.5% |
This informed my squad composition — I have heavy coverage in France (Mbappé, Kanté), Spain (Llorente, Porro, Oyarzabal), and England (Bellingham, Saka, Guéhi).
## Round of 32 — Full Squad Rebuild
### The System Wildcard
Something I didn't fully appreciate going in: FIFA Fantasy grants an **automatic unlimited transfer window** for the group stage → knockout transition. Every player is free to move. This is separate from your personal Wild Card booster — it's a system-level reset that lets everyone rebuild from scratch before the knockouts begin.
That changes the strategy significantly. Instead of optimizing transfers at the margin (who's the best 1–2 swaps?), I got to redesign the entire squad around R32 fixtures.
The budget also increased. FIFA adds a $5M "knockout boost" when the knockouts begin, bringing the total from $100M to $105M. Combined with the unlimited free window, this felt like a second draft.
### How I Rebuilt
The rebuild had three filters, applied in order:
1. **Team survival** — only pick players from nations in the Round of 32 (obvious, but the data confirms it: any player whose nation was eliminated goes to $0 expected value)
2. **Fixture quality** — use the rank difference between the team and their R32 opponent as a proxy for how comfortable the match should be. I pulled group stage standings to generate live rankings for all 32 remaining nations.
3. **Player form** — within good fixtures, pick the highest avg-points players
I also ran the Polymarket odds through the model to estimate each team's win probability for their R32 match, which fed an expected-points calculation: `avg_pts + win_prob × qual_booster_bonus`.
### The Squad
**Formation: 4-3-3**
| Pos | Player | Team | Opponent | Rank Diff | Win% |
|---|---|---|---|---:|---:|
| GK | Unai Simón | ESP | TBD | ? | TBD |
| DEF | Mateo Chávez | MEX | Ecuador | +22 | 74% |
| DEF | Marcos Llorente | ESP | TBD | ? | TBD |
| DEF | Facundo Medina | ARG | Cabo Verde | +21 | 86% |
| DEF | Lisandro Martínez | ARG | Cabo Verde | +21 | 86% |
| MID | Ousmane Dembélé | FRA | Sweden | +21 | 80% |
| MID | Vinícius Júnior | BRA | Japan | +13 | 70% |
| MID | Jude Bellingham (VC) | ENG | Congo DR | +14 | 81% |
| FWD | Lionel Messi | ARG | Cabo Verde | +21 | 86% |
| FWD | Kylian Mbappé (C) | FRA | Sweden | +21 | 80% |
| FWD | Erling Haaland | NOR | Côte d'Ivoire | ±1 | 59% |
The squad is heavily weighted toward France (Mbappé, Dembélé), Argentina (Messi, Medina, Martínez), and Spain (Simón, Llorente) — the three highest-probability tournament winners per Polymarket. The ARG clean sheet upside is particularly high: Cabo Verde ranked #32 in the tournament by group stage results, giving Argentina a +21 rank advantage.
**The Haaland question.** Norway vs Côte d'Ivoire was the one iffy fixture — both teams ranked essentially equal (#14 vs #13) and Norway's win probability was only 59%. I ran the alternatives:
| Player | Avg | Win% | Exp pts |
|---|---:|---:|---:|
| Haaland | 15.0 | 59% | 16.2 |
| Mbappé | 12.0 | 80% | 13.6 |
| Undav | 9.7 | 74% | 11.2 |
| Kane | 7.7 | 81% | 9.3 |
The Qualification Booster only adds ~2 pts per qualifying player, so the fixture edge for Kane or Cunha is worth at most ~0.5 pts in expected qualification bonus. Haaland's form advantage is 3–7 pts. Even if Norway lose, Haaland will almost certainly outscore any alternative in the single match that matters. He stays.
### Booster Choice: Qualification Booster
With 11 starters all on high-probability qualifying nations (France 80%, England 81%, Argentina 86%, Brazil 70%, Mexico 74%, Spain TBD but top-5 world ranking), the Qualification Booster is the right play for R32. It pays +2 pts per qualifying starting player — with 10 of 11 starters on 70%+ nations, expected value is around +18 to +20 bonus points.
The personal Wild Card is saved for R16, where the bracket may force a rebuild after upsets. Clean Sheet Shield and 12th Man are earmarked for the quarter-final and semi-final respectively, when the field narrows and fixture quality is extreme.
**Captain: Mbappé.** France vs Sweden has a +21 rank advantage and 80% win probability. Mbappé's avg (12.0) is lower than Messi's (16.5) but France is the tournament favourite and Sweden are weak — high ceiling for a captain pick. Bellingham is VC given England's dominant fixture vs Congo DR.
### What's Next
The Round of 32 results will tell me which nations survive. With the personal Wild Card held for R16, I can do a full rebuild again if the bracket breaks unfavourably. The model will re-run with updated Polymarket odds and fresh fixtures after the R32 games complete.
Code is all local — if you want to run something similar, the main ingredients are:
- [FIFA's public fantasy API](https://play.fifa.com/json/fantasy/players.json)
- [Polymarket's Gamma API](https://gamma-api.polymarket.com/markets)
- A bit of Monte Carlo and a fuzzy name matcher