Documentação técnica do modelo
O Sassamaru nasceu de uma pergunta simples: é possível construir um modelo de previsão de futebol robusto que rode inteiramente no navegador, sem servidor, sem API externa, usando apenas dados históricos públicos?
A resposta é sim — com ressalvas. Modelos probabilísticos de futebol têm longa tradição acadêmica, começando com Maher (1982) e Dixon & Coles (1997). O Sassamaru reimplementa essa tradição em JavaScript client-side, priorizando transparência, reprodutibilidade e facilidade de uso.
O escopo é deliberadamente limitado: previsão de resultados 1X2 (mandante vence / empate / visitante vence) com probabilidades calibradas e odds derivadas. Não há previsão de escanteios, cartões, marcadores individuais ou mercados asiáticos.
Dataset customizado campeonatobrasileirolimpo.csv com 9 200+ partidas do Campeonato Brasileiro Série A entre 2003 e 2026 (rodadas 1–8 da edição atual). As colunas usadas são: rodada (rodata), mandante, visitante e placar.
Dataset público de Mart Jürisoo disponível no Kaggle (international football results), com 49 000+ partidas entre seleções desde 1872. Colunas: date, home_team, away_team, home_score, away_score, neutral. O campo neutral é booleano e indica se o jogo foi disputado em campo neutro.
Para o modelo de seleções, o decay é date-based (dias desde cada partida), não round-based. O treinamento usa dados a partir de 1990 por padrão, já que o futebol pré-Copa do Mundo moderna tem distribuições estatísticas bastante distintas das atuais.
O pipeline de previsão segue cinco etapas principais:
Partidas mais antigas são menos informativas do que partidas recentes. Para capturar isso, cada jogo histórico recebe um peso calculado com uma função de half-life exponencial:
Três pesos independentes são calculados, com half-lives diferentes, para os três componentes que os usam:
| Componente | Half-life (Brasileirão) | Half-life (Seleções) | Peso mínimo |
|---|---|---|---|
| Elo | 76 rodadas (~2 temporadas) | 730 dias (~2 anos) | 0.10 |
| Poisson (λ) | 152 rodadas (~4 temporadas) | 1 460 dias (~4 anos) | 0.25 |
| Forma recente | 19 rodadas (~½ temporada) | 120 dias (~4 meses) | 0.35 |
A intuição por trás dos diferentes half-lives: a força de ataque e defesa (Poisson) muda devagar — um time bom geralmente permanece bom por anos. A força relativa (Elo) muda um pouco mais rápido. A forma é por definição transitória — o que importa são os últimos meses, não os últimos anos.
O modelo central assume que o número de gols marcados por cada time em uma partida segue distribuições de Poisson independentes com parâmetros λH (gols esperados do mandante) e λA (gols esperados do visitante).
As quatro forças por time (ataque em casa, defesa em casa, ataque fora, defesa fora) são calculadas como razões em relação à média da liga, usando médias ponderadas pelos pesos temporais de Poisson:
Essa estrutura é a base do modelo de Dixon & Coles (1997) e equivale a uma regressão log-linear de Poisson com efeitos fixos por time e por lado (casa/fora).
O sistema Elo, desenvolvido originalmente para xadrez por Arpad Elo, foi adaptado para futebol pela FIFA e por pesquisadores como Hvattum & Arntzen (2010). A ideia central é que cada time tem um rating que sobe quando vence e cai quando perde, proporcionalmente à surpresa do resultado.
O fator K é dinâmico: vitórias por maior placar geram atualização mais forte. O peso temporal w_elo reduz o impacto de jogos antigos no rating atual.
No início de cada temporada do Brasileirão, os ratings sofrem um reset parcial em direção ao valor inicial (1500), controlado pelo parâmetro SEASON_RESET_ALPHA = 0.20. Isso captura o fato de que, com mudanças de elenco, um time forte tende a regredir um pouco à média.
O Elo entra no modelo como um ajuste multiplicativo em λ, usando o parâmetro γ (gamma):
A forma recente captura a tendência de curto prazo de um time — um time que está em crise tende a continuar sofrendo gols, independentemente da sua força histórica.
Para cada time, os últimos FORM_N jogos são usados para calcular médias ponderadas de gols marcados (GF) e sofridos (GA), com o peso temporal de forma (half-life curto):
Esses valores são convertidos em fatores relativos à média da liga e aplicados a λ:
Dixon & Coles (1997) identificaram que o modelo de Poisson puro superestima a probabilidade de placares altos e subestima os placares baixos, particularmente 0-0, 1-0, 0-1 e 1-1. A correção introduz um parâmetro ρ (rho) que ajusta essas quatro células da matriz de placares:
O valor de ρ é estimado por máxima verossimilhança (MLE) via busca em grade de -0.50 a +0.50 em passos de 0.01, maximizando a log-verossimilhança do conjunto de treinamento. O valor empírico encontrado para o Brasileirão é aproximadamente ρ ≈ −0.01 — significativamente menos negativo do que o −0.10 assumido inicialmente, o que demonstra a importância de estimar o parâmetro em vez de fixá-lo por hipótese.
No Brasileirão, times com mais rodadas de descanso desde o último jogo jogam melhor. O modelo aplica um ajuste em λ baseado no gap (em rodadas) desde a última partida disputada:
Aproximadamente 30% das partidas internacionais são disputadas em campo neutro (Copas do Mundo, torneios continentais, amistosos em terceiro país). Nesses casos, a vantagem de jogar em casa não existe, então λ é calculado usando a média entre league_home_avg e league_away_avg para ambos os lados:
Ao construir o modelo, jogos em campo neutro são tratados como "jogos fora" para ambos os times nos cálculos de força de ataque e defesa, evitando inflar o parâmetro de vantagem de casa com dados de jogos que não têm tal vantagem.
Com λH e λA determinados, a probabilidade de cada placar possível (gH, gA) é calculada como produto das probabilidades de Poisson, corrigida por Dixon-Coles:
As probabilidades marginais de resultado (1X2) são obtidas pela soma das células da matriz:
As odds são derivadas dessas probabilidades adicionando um overround (margem da casa), que representa o lucro esperado do bookmaker. Com overround de 6%:
λ^k / k! pode causar underflow em ponto flutuante. O modelo calcula Poisson em log-space: exp(k × log(λ) − λ − logfact(k)), com log-fatoriais pré-computados em cache.
O modelo inclui um backtest walk-forward: para cada uma das últimas BACKTEST_SEASONS temporadas do Brasileirão, o modelo é treinado em todas as temporadas anteriores e avaliado nos jogos da temporada corrente. As métricas calculadas são:
Percentual de jogos em que o palpite do modelo (resultado mais provável) coincidiu com o resultado real. Sassamarumark de referência: ~46% (proporção de vitórias do mandante). O modelo historicamente atinge ~52–55% no Brasileirão.
O modelo é considerado calibrado se, entre todos os jogos para os quais atribuiu probabilidade ~30%, aproximadamente 30% desses jogos ocorreram. A calibração é visualizada em um gráfico de confiabilidade com 10 bins de 10% cada.
Para os apps de simulação de temporada (Brasileirão e Copa do Mundo), o modelo é usado para gerar distribuições de resultados possíveis via Monte Carlo: o torneio inteiro é simulado N vezes (tipicamente 5 000), e as frequências de cada evento (campeão, classificado, rebaixado, etc.) são estimadas empiricamente.
Em cada simulação, para cada partida:
Para jogos eliminatórios (Copa do Mundo), o empate não existe como resultado final. Se a distribuição Poisson + DC gera empate, o vencedor é determinado por um sorteio ponderado pela razão P(H) / (P(H) + P(A)), emulando pênaltis.
Para evitar travar o navegador, o loop Monte Carlo cede o controle ao event loop do JavaScript a cada 50–100 iterações via await new Promise(r => setTimeout(r, 0)). Isso permite atualizar a barra de progresso e manter a interface responsiva durante o cálculo.
Com N = 5 000 simulações, o erro padrão de uma probabilidade de 50% é √(0.5 × 0.5 / 5000) ≈ 0.7%. Para probabilidades extremas (ex.: rebaixamento do favorito, ~2%), o erro padrão é ≈ 0.2%, suficiente para diferenciar candidatos ao rebaixamento com confiança razoável.
| Característica | Sassamaru Rodada | Sassamaru Brasileirão | Sassamaru Seleções | Sassamaru Copa |
|---|---|---|---|---|
| Dataset | Brasileirão 2003–26 | Brasileirão 2003–26 | Internacional 1872–26 | Internacional 1872–26 |
| Unidade de tempo | Rodadas | Rodadas | Dias | Dias |
| Campo neutro | Não | Não | Sim (flag CSV) | Sim (grupo/fase) |
| Fator descanso | Sim | Não (MC) | Não | Não |
| Detecção de temporadas | Auto (clusters) | Auto (clusters) | N/A | N/A |
| Modo de saída | Por partida | Classificação Monte Carlo | Por partida | Torneio Monte Carlo |
Nenhum modelo é completo. As limitações mais relevantes do Sassamaru são:
O modelo não sabe que Neymar está lesionado, que um técnico foi demitido ontem, que o jogo é disputado em altitude de 3 600m, que chove forte ou que um time está concentrado em outra competição. Toda essa informação contextual é real e relevante — o modelo ignora completamente.
O modelo de Poisson bivariado tende a subestimar a probabilidade de empate em comparação com o mercado real. A correção Dixon-Coles mitiga isso parcialmente (via aumento de P(0-0) e P(1-1)), mas o problema persiste para placares maiores (2-2, 3-3).
Times recém-promovidos ou seleções com histórico limitado no dataset têm estimativas de força pouco confiáveis. O modelo usa fallback para médias da liga, o que pode super ou subestimar esses times.
O futebol muda: estilos de jogo, volume de transferências, intensidade física. O modelo trata toda a história (desde 2003 / 1990) como amostras do mesmo processo, ponderando pelo decay. Isso é uma aproximação — o futebol de 2026 não é estatisticamente idêntico ao de 2003, mesmo com decay.
O modelo assume que os gols do mandante e do visitante são independentes. Na prática, o estado do jogo influencia o comportamento: um time que abre 3-0 não joga da mesma forma que em 0-0. Essa correlação dinâmica não é capturada.
O chaveamento da Copa do Mundo 2026 para a fase eliminatória é complexo — o chaveamento real depende de quais grupos os 8 melhores terceiros colocados vieram. O simulador usa uma simplificação de pareamento sequencial, o que pode gerar matches que não seriam possíveis no torneio real.
O modelo atual é funcional e produz previsões razoáveis, mas há espaço significativo para melhoria. Os itens abaixo estão ordenados por impacto esperado na qualidade das previsões.
modelos/model.js: todos os parâmetros (α ataque, β defesa, γ home advantage, μ base, ρ) estimados conjuntamente via gradiente analítico da log-verossimilhança com 400 iterações Adam e penalidades de identificabilidade.
modelos/model.js: fator individual estimado para times com ≥10 jogos ponderados em casa (map homeAdv), limitado ao intervalo [0.85, 1.15]. Times sem dados suficientes usam o fator médio da liga.
apps/index.html: botão de exportação que gera CSV com todas as previsões da rodada.
simulacoes/bench-copa2026.html: layout estilo ESPN com chaveamento visual completo da fase eliminatória.
tests/selecoes-model.test.js: 110+ testes cobrindo helpers matemáticos, pesos temporais, buildModel e predict. Executar via npm run test:selecoes.