Goal Elo

monitoring only -- not used by any card's picks

An attack/defense Elo variant tracking goal-scoring and goal-conceding strength independently of win/loss. Each team's Attack and Defense sit on a log scale where 0 is exactly league average; ratings update after every match from the gap between actual and expected goals. See scripts/goal_elo/goal_elo.py for the model.

24 teams · K=0.025 · league avg 1.297 goals/team/match · home advantage +0.166 log-units (~18%) · seasons 2022, 2023, 2024, 2025 · generated 2026-09-19 10:32 UTC

Attack (0 = league average)Defense ↑Lyon -- attack 0.163 (1582 Elo), defense 0.120 (1560 Elo), 140 matchesAjaccio -- attack -0.174 (1413 Elo), defense -0.103 (1448 Elo), 38 matchesStrasbourg -- attack 0.209 (1604 Elo), defense 0.039 (1519 Elo), 140 matchesMonaco -- attack 0.277 (1638 Elo), defense -0.032 (1484 Elo), 140 matchesMonacoClermont Foot -- attack -0.153 (1423 Elo), defense -0.083 (1459 Elo), 72 matchesParis Saint Germain -- attack 0.428 (1714 Elo), defense 0.376 (1688 Elo), 140 matchesParis Saint GermainToulouse -- attack 0.031 (1515 Elo), defense 0.069 (1534 Elo), 139 matchesNice -- attack -0.101 (1450 Elo), defense -0.007 (1497 Elo), 142 matchesAngers -- attack -0.361 (1320 Elo), defense 0.005 (1503 Elo), 106 matchesNantes -- attack -0.299 (1351 Elo), defense 0.011 (1505 Elo), 139 matchesLille -- attack 0.033 (1517 Elo), defense 0.331 (1665 Elo), 140 matchesLilleAuxerre -- attack -0.124 (1438 Elo), defense 0.145 (1573 Elo), 106 matchesMontpellier -- attack -0.283 (1359 Elo), defense -0.247 (1377 Elo), 106 matchesEstac Troyes -- attack -0.066 (1467 Elo), defense -0.119 (1440 Elo), 38 matchesLens -- attack 0.296 (1648 Elo), defense 0.257 (1628 Elo), 140 matchesLensStade Brestois 29 -- attack -0.046 (1477 Elo), defense -0.080 (1460 Elo), 140 matchesRennes -- attack 0.245 (1622 Elo), defense -0.003 (1498 Elo), 140 matchesLorient -- attack 0.047 (1523 Elo), defense 0.017 (1509 Elo), 106 matchesMarseille -- attack 0.216 (1608 Elo), defense 0.041 (1521 Elo), 140 matchesReims -- attack -0.224 (1388 Elo), defense 0.035 (1518 Elo), 108 matchesLe Havre -- attack -0.221 (1389 Elo), defense 0.066 (1533 Elo), 102 matchesMetz -- attack -0.216 (1392 Elo), defense -0.337 (1331 Elo), 72 matchesSaint Etienne -- attack -0.076 (1462 Elo), defense -0.253 (1373 Elo), 38 matchesParis FC -- attack 0.060 (1530 Elo), defense 0.094 (1547 Elo), 34 matches

Dot size = matches played (a small dot is a partial-season sample -- promoted/relegated sides). Color is combined attack+defense strength, green (strong) to red (weak). Labeled: top 3 by attack, top 3 by defense.

TeamAttackDefenseAtk EloDef EloGF vs avg defenseGA vs avg attackMatches
Paris Saint Germain0.4280.376171416881.990.89140
Lens0.2960.257164816281.741.00140
Monaco0.277-0.032163814841.711.34140
Rennes0.245-0.003162214981.661.30140
Marseille0.2160.041160815211.611.24140
Strasbourg0.2090.039160415191.601.25140
Lyon0.1630.120158215601.531.15140
Paris FC0.0600.094153015471.381.1834
Lorient0.0470.017152315091.361.27106
Lille0.0330.331151716651.340.93140
Toulouse0.0310.069151515341.341.21139
Stade Brestois 29-0.046-0.080147714601.241.40140
Estac Troyes-0.066-0.119146714401.211.4638
Saint Etienne-0.076-0.253146213731.201.6738
Nice-0.101-0.007145014971.171.31142
Auxerre-0.1240.145143815731.151.12106
Clermont Foot-0.153-0.083142314591.111.4172
Ajaccio-0.174-0.103141314481.091.4438
Metz-0.216-0.337139213311.041.8272
Le Havre-0.2210.066138915331.041.21102
Reims-0.2240.035138815181.041.25108
Montpellier-0.283-0.247135913770.981.66106
Nantes-0.2990.011135115050.961.28139
Angers-0.3610.005132015030.901.29106

Atk/Def Elo = 1500 + raw × 500 -- a cosmetic rescale for familiarity, not a real unit conversion. Chess Elo's 400-point gap has a specific meaning (10:1 win odds) that goal-scoring rate has no equivalent of. The Attack/Defense columns are what the model actually computes with.

2026 over 1.5 check

P(total goals ≥ 2) for every completed match since 2026-01-01 across all 38 tracked leagues -- the mu_home + mu_away → Poisson total construction, same as over-15-card's own math, just fed by Goal Elo's ratings instead. Each prediction used only ratings built from strictly earlier matches, compared against a baseline that knows just the league's average scoring rate and home advantage, no team identity at all.

7,770
Matches scored
75.8%
Actual over-1.5 rate
0.182
Model Brier score
-0.5%
Skill vs baseline

Honest read: over 1.5 is a low bar in football (the baseline alone already expects it 76% of the time), so knowing which specific teams are playing barely moves the needle here -- skill sits close to 0% pooled, unlike the real, consistent edge Attack/Defense showed on raw expected goals. The model is well calibrated (see below), it just isn't adding much information a viewer didn't already have from the league's baseline rate.

Reliability

0%0%25%25%50%50%75%75%100%100%Predicted P(over 1.5)Actual over-1.5 rateperfect calibrationpredicted ~50%, actually over 1.5 51% of the time (n=45)predicted ~55%, actually over 1.5 67% of the time (n=177)predicted ~60%, actually over 1.5 65% of the time (n=428)predicted ~65%, actually over 1.5 71% of the time (n=967)predicted ~70%, actually over 1.5 74% of the time (n=1564)predicted ~75%, actually over 1.5 76% of the time (n=1858)predicted ~80%, actually over 1.5 79% of the time (n=1593)predicted ~85%, actually over 1.5 84% of the time (n=835)predicted ~90%, actually over 1.5 87% of the time (n=243)predicted ~95%, actually over 1.5 95% of the time (n=44)

Matches bucketed by predicted P(over 1.5); dot = actual over-1.5 rate in that bucket (size = sample). On the dashed line means perfectly calibrated.

Skill vs no-team-identity baseline

Peru - Primera Division
5.0%
Bolivia - Primera Division
3.8%
South Africa - Premier Soccer League
3.2%
Turkey - Super Lig
2.2%
Portugal - Primeira Liga
2.1%
Ecuador - Liga Pro
1.8%
Russia - Premier League
1.1%
China - Super League
1.1%
USA - MLS
1.0%
Australia - A-League
0.9%
Brazil - Serie A
0.4%
Argentina - Liga Profesional
0.3%
Colombia - Primera A
0.1%
Costa Rica - Primera Division
0.0%
Chile - Primera Division
-0.2%
Norway - Eliteserien
-0.2%
France - Ligue 1
-0.3%
Greece - Super League
-0.5%
Guatemala - Liga Nacional
-0.6%
Spain - La Liga
-0.6%
Italy - Serie A
-1.1%
Netherlands - Eredivisie
-1.3%
El Salvador - Primera Division
-1.3%
Uruguay - Primera Division
-1.4%
Honduras - Liga Nacional
-1.6%
Sweden - Allsvenskan
-1.9%
Denmark - Superliga
-2.1%
Mexico - Liga MX
-2.4%
Paraguay - Division Profesional (Apertura)
-2.4%
Saudi Arabia - Pro League
-2.6%
England - Premier League
-2.7%
India - Indian Super League
-2.9%
Austria - Bundesliga
-2.9%
Scotland - Premiership
-3.0%
Venezuela - Primera Division
-3.3%
Japan - J1 League
-3.5%
Belgium - Jupiler Pro League
-4.1%
Germany - Bundesliga
-4.7%

1 − (model Brier / baseline Brier). 0% = no better than ignoring which teams are playing; a negative bar means Attack/Defense info actually hurt on that league's calls.

Biggest surprises

Lowest probability the model gave to what actually happened.

  • VfL Wolfsburg 0-1 Bayern München (Germany - Bundesliga, 2026-05-09)model said 96% over
  • CF Montreal 0-1 Inter Miami (USA - MLS, 2026-07-25)model said 93% over
  • Club Brugge KV 1-0 Cercle Brugge (Belgium - Jupiler Pro League, 2026-08-23)model said 92% over
  • Barcelona 1-0 Celta Vigo (Spain - La Liga, 2026-04-22)model said 92% over
  • FC Schalke 04 0-0 Bayern München (Germany - Bundesliga, 2026-09-05)model said 92% over
  • Sirius 0-1 Malmo FF (Sweden - Allsvenskan, 2026-08-31)model said 91% over
  • FC Midtjylland 0-1 FC Nordsjaelland (Denmark - Superliga, 2026-03-15)model said 91% over
  • Always Ready 1-0 Oriente Petrolero (Bolivia - Primera Division, 2026-04-22)model said 91% over
  • Newcastle Jets 1-0 Macarthur (Australia - A-League, 2026-02-22)model said 90% over
  • Al-Fateh 0-1 Al-Hilal Saudi FC (Saudi Arabia - Pro League, 2026-03-14)model said 90% over

All predictions — France - Ligue 1 (200)

Switch leagues with the tabs above the ratings table; newest match first.

DateMatchScoreP(over)ActualCall
2026-09-18Monaco v Lens2-182%over
2026-09-13Lille v Estac Troyes2-077%over
2026-09-13Le Mans v Lens2-280%over
2026-09-13Stade Brestois 29 v Paris Saint Germain0-182%under
2026-09-12Strasbourg v Monaco1-186%over
2026-09-12Lorient v Toulouse2-274%over
2026-09-12Auxerre v Nice1-074%under
2026-09-12Le Havre v Angers0-066%under
2026-09-12Paris FC v Lyon0-077%under
2026-09-11Rennes v Marseille1-086%under
2026-09-06Estac Troyes v Strasbourg2-680%over
2026-09-06Angers v Rennes1-278%over
2026-09-06Marseille v Paris FC2-378%over
2026-09-05Lens v Lorient0-181%under
2026-09-05Nice v Le Mans1-176%over
2026-09-05Le Havre v Stade Brestois 291-273%over
2026-09-04Lyon v Auxerre3-178%over
2026-09-04Paris Saint Germain v Monaco1-284%over
2026-09-03Toulouse v Lille0-172%under
2026-08-30Paris FC v Nice3-072%over
2026-08-30Rennes v Le Mans3-283%over
2026-08-30Monaco v Marseille2-084%over
2026-08-29Strasbourg v Lens2-184%over
2026-08-29Lyon v Le Havre1-173%over
2026-08-29Lorient v Estac Troyes1-276%over
2026-08-29Stade Brestois 29 v Toulouse2-277%over
2026-08-29Auxerre v Angers1-370%over
2026-08-28Lille v Paris Saint Germain2-273%over
2026-08-23Angers v Lille0-266%over
2026-08-23Le Havre v Monaco0-178%under
2026-08-23Rennes v Paris Saint Germain2-282%over
2026-08-22Lens v Auxerre5-275%over
2026-08-22Nice v Lorient0-076%under
2026-08-22Toulouse v Lyon0-277%over
2026-08-22Estac Troyes v Paris FC0-078%under
2026-08-22Le Mans v Stade Brestois 292-278%over
2026-08-21Marseille v Strasbourg4-083%over
2026-05-29Nice v Saint Etienne4-177%over
2026-05-26Saint Etienne v Nice0-080%under
2026-05-17Lille v Auxerre0-266%over
2026-05-17Lyon v Lens0-478%over
2026-05-17Marseille v Rennes3-186%over
2026-05-17Nice v Metz0-084%under
2026-05-17Strasbourg v Monaco5-481%over
2026-05-17Lorient v Le Havre0-273%over
2026-05-17Stade Brestois 29 v Angers1-171%over
2026-05-17Paris FC v Paris Saint Germain2-180%over
2026-05-13Stade Brestois 29 v Strasbourg1-279%over
2026-05-13Lens v Paris Saint Germain0-280%over
2026-05-10Angers v Strasbourg1-171%over
2026-05-10Paris Saint Germain v Stade Brestois 291-088%under
2026-05-10Monaco v Lille0-176%under
2026-05-10Rennes v Paris FC2-182%over
2026-05-10Toulouse v Lyon2-177%over
2026-05-10Auxerre v Nice2-171%over
2026-05-10Le Havre v Marseille0-177%under
2026-05-10Metz v Lorient0-483%over
2026-05-08Lens v Nantes1-078%under
2026-05-03Lille v Le Havre1-170%over
2026-05-03Strasbourg v Toulouse1-278%over
2026-05-03Auxerre v Angers3-160%over
2026-05-03Paris FC v Stade Brestois 294-078%over
2026-05-03Lyon v Rennes4-280%over
2026-05-02Nantes v Marseille3-077%over
2026-05-02Paris Saint Germain v Lorient2-286%over
2026-05-02Metz v Monaco1-288%over
2026-05-02Nice v Lens1-182%over
2026-04-26Lorient v Strasbourg2-375%over
2026-04-26Rennes v Nantes2-179%over
2026-04-26Le Havre v Metz4-471%over
2026-04-26Paris FC v Lille0-172%under
2026-04-26Marseille v Nice1-186%over
2026-04-25Lyon v Auxerre3-266%over
2026-04-25Angers v Paris Saint Germain0-376%over
2026-04-25Toulouse v Monaco2-280%over
2026-04-24Stade Brestois 29 v Lens3-379%over
2026-04-22Paris Saint Germain v Nantes3-083%over
2026-04-19Monaco v Auxerre2-273%over
2026-04-19Nantes v Stade Brestois 291-172%over
2026-04-19Strasbourg v Rennes0-381%over
2026-04-19Metz v Paris FC1-377%over
2026-04-19Paris Saint Germain v Lyon1-280%over
2026-04-18Lorient v Marseille2-083%over
2026-04-18Angers v Le Havre1-158%over
2026-04-18Lille v Nice0-081%under
2026-04-17Lens v Toulouse3-276%over
2026-04-12Nice v Le Havre1-173%over
2026-04-12Toulouse v Lille0-469%over
2026-04-12Lyon v Lorient2-076%over
2026-04-11Auxerre v Nantes0-064%under
2026-04-11Rennes v Angers2-174%over
2026-04-10Paris FC v Monaco4-178%over
2026-04-10Marseille v Metz3-188%over
2026-04-05Angers v Lyon0-068%under
2026-04-05Lorient v Paris FC1-176%over
2026-04-05Le Havre v Auxerre1-159%over
2026-04-05Metz v Nantes0-076%under
2026-04-05Monaco v Marseille2-186%over
2026-04-04Strasbourg v Nice3-181%over
2026-04-04Stade Brestois 29 v Rennes3-476%over
2026-04-04Lille v Lens3-072%over
2026-04-03Paris Saint Germain v Toulouse3-179%over
2026-03-22Lyon v Monaco1-279%over
2026-03-22Marseille v Lille1-280%over
2026-03-22Rennes v Metz0-088%under
2026-03-22Paris FC v Le Havre3-263%over
2026-03-22Nantes v Strasbourg2-371%over
2026-03-21Toulouse v Lorient1-075%under
2026-03-21Auxerre v Stade Brestois 293-064%over
2026-03-21Nice v Paris Saint Germain0-484%over
2026-03-20Lens v Angers5-168%over
2026-03-15Strasbourg v Paris FC0-076%under
2026-03-15Le Havre v Lyon0-069%under
2026-03-15Metz v Toulouse3-474%over
2026-03-15Rennes v Lille1-277%over
2026-03-14Lorient v Lens2-177%over
2026-03-14Angers v Nice0-270%over
2026-03-14Monaco v Stade Brestois 292-079%over
2026-03-13Marseille v Auxerre1-080%under
2026-03-08Lens v Metz3-083%over
2026-03-08Lille v Lorient1-176%over
2026-03-08Nice v Rennes0-482%over
2026-03-08Stade Brestois 29 v Le Havre2-068%over
2026-03-08Lyon v Paris FC1-179%over
2026-03-07Nantes v Angers0-163%under
2026-03-07Auxerre v Strasbourg0-071%under
2026-03-07Toulouse v Marseille0-181%under
2026-03-06Paris Saint Germain v Monaco1-384%over
2026-03-01Paris FC v Nice1-080%under
2026-03-01Lille v Nantes1-074%under
2026-03-01Lorient v Auxerre2-271%over
2026-03-01Metz v Stade Brestois 290-180%under
2026-03-01Marseille v Lyon3-284%over
2026-02-28Rennes v Toulouse1-077%under
2026-02-28Monaco v Angers2-073%over
2026-02-28Le Havre v Paris Saint Germain0-177%under
2026-02-27Strasbourg v Lens1-176%over
2026-02-22Auxerre v Rennes0-373%over
2026-02-22Angers v Lille0-166%under
2026-02-22Nantes v Le Havre2-067%over
2026-02-22Nice v Lorient3-378%over
2026-02-22Strasbourg v Lyon3-176%over
2026-02-21Lens v Monaco2-377%over
2026-02-21Toulouse v Paris FC1-175%over
2026-02-21Paris Saint Germain v Metz3-092%over
2026-02-20Stade Brestois 29 v Marseille2-086%over
2026-02-15Le Havre v Toulouse2-165%over
2026-02-15Lorient v Angers2-068%over
2026-02-15Metz v Auxerre1-371%over
2026-02-15Lyon v Nice2-081%over
2026-02-14Marseille v Strasbourg2-285%over
2026-02-14Lille v Stade Brestois 291-177%over
2026-02-14Paris FC v Lens0-571%over
2026-02-13Rennes v Paris Saint Germain3-185%over
2026-02-13Monaco v Nantes3-178%over
2026-02-08Nice v Monaco0-084%under
2026-02-08Angers v Toulouse1-066%under
2026-02-08Auxerre v Paris FC0-070%under
2026-02-08Le Havre v Strasbourg2-169%over
2026-02-08Paris Saint Germain v Marseille5-086%over
2026-02-07Lens v Rennes3-175%over
2026-02-07Stade Brestois 29 v Lorient2-078%over
2026-02-07Nantes v Lyon0-178%under
2026-02-06Metz v Lille0-083%under
2026-02-01Lyon v Lille1-081%under
2026-02-01Angers v Metz1-078%under
2026-02-01Nice v Stade Brestois 292-282%over
2026-02-01Toulouse v Auxerre0-072%under
2026-02-01Strasbourg v Paris Saint Germain1-279%over
2026-01-31Paris FC v Marseille2-285%over
2026-01-31Lorient v Nantes2-176%over
2026-01-31Monaco v Rennes4-082%over
2026-01-30Lens v Le Havre1-068%under
2026-01-25Nantes v Nice1-476%over
2026-01-25Stade Brestois 29 v Toulouse0-277%over
2026-01-25Metz v Lyon2-581%over
2026-01-25Paris FC v Angers0-074%under
2026-01-25Lille v Strasbourg1-476%over
2026-01-24Rennes v Lorient0-281%over
2026-01-24Le Havre v Monaco0-076%under
2026-01-24Marseille v Lens3-178%over
2026-01-23Auxerre v Paris Saint Germain0-180%under
2026-01-18Strasbourg v Metz2-182%over
2026-01-18Nantes v Paris FC1-274%over
2026-01-18Rennes v Le Havre1-178%over
2026-01-18Lyon v Stade Brestois 292-179%over
2026-01-17Lens v Auxerre1-072%under
2026-01-17Toulouse v Nice5-175%over
2026-01-17Angers v Marseille2-575%over
2026-01-16Monaco v Lorient1-382%over
2026-01-16Paris Saint Germain v Lille3-082%over
2026-01-04Marseille v Nantes0-285%over
2026-01-04Lorient v Metz1-182%over
2026-01-04Stade Brestois 29 v Auxerre2-076%over
2026-01-04Le Havre v Angers2-163%over
2026-01-04Paris Saint Germain v Paris FC2-187%over
2026-01-03Monaco v Lyon1-379%over
2026-01-03Nice v Strasbourg1-177%over
2026-01-03Lille v Rennes0-283%over
2026-01-02Toulouse v Lens0-368%over