SPORTS BETTING MATH
ARTIGO DE PESQUISA

Modelo Dixon-Coles Explicado: Correção de Baixos Placares e Decaimento Temporal no Futebol

Guia matemático completo sobre a correção bivariada de Dixon-Coles, matriz de ajuste tau para baixos placares, estimação de parâmetros com decaimento temporal e ineficiências em apostas de futebol.

22 min de leitura Avançado Última atualização 2026-09-20
Ilustração do tema: Modelo Dixon-Coles Explicado: Correção de Baixos Placares e Decaimento Temporal no Futebol
Ilustração conceitual. As premissas numéricas e os exemplos são explicados no texto.

Lab de Modelagem Estocástica SBM

Assinatura editorial: modelos de partidas e banca

Esta assinatura agrupa artigos sobre Poisson, Kelly e simulação. É um rótulo editorial, não prova de um laboratório com equipe ou qualificações verificadas.

Modelagem Bivariada de Partidas pela Distribuição de Poisson Otimização de Crescimento Geométrico pelo Critério de Kelly Simulações de Monte Carlo para Risco de Ruína

1. Introdução: A Falha Estrutural do Modelo Poisson Independente

Na modelagem quantitativa de futebol de associação, o modelo de Poisson independente — introduzido pioneiramente na análise esportiva por M. J. Maher em 1982 — representa a referência clássica para estimar a expectativa de gols e as distribuições de placares exatos. A premissa central de Maher afirma que os gols marcados pela equipe mandante (X) e pela equipe visitante (Y) ao longo dos 90 minutos de tempo regulamentar seguem processos estocásticos pontuais de Poisson mutuamente independentes, parametrizados pelas expectativas marginais de gols λ e μ:

P(X=x,Y=y)=P(X=x)⋅P(Y=y)=λxe−λx!⋅μye−μy!

A independência é uma hipótese que deve ser avaliada num conjunto de dados definido. O estado da partida e a interação tática podem criar dependência, mas uma correção também pode ajustar ruído. A comparação precisa de distinguir mudanças na dependência de mudanças nas intensidades. Uma diferença entre modelos não estabelece erro de cotação nem o sinal do valor esperado numa casa.

Com intensidades ilustrativas λ=1.45 e μ=1.10, Poisson independente dá P(0,0)≈7.808167% e P(1,1)≈12.454026%. São valores calculados do modelo. Avaliar subestimação ou superestimação exige frequências observadas e probabilidades da mesma amostra, com datas, competições e incerteza indicadas. A comparação de entradas fixas abaixo isola o efeito da correção dos placares baixos.

Em seu célebre artigo de 1997 publicado no Journal of the Royal Statistical Society, os estatísticos britânicos Mark J. Dixon e Stuart G. Coles apresentaram a solução canônica para este problema: "Modelling Association Football Scores and Inefficiencies in the Football Betting Market". O modelo Dixon-Coles introduziu um fator de dependência de placares baixos τx,y(λ,μ,ρ) que pondera explicitamente os estados de baixa pontuação, preservando integralmente a distribuição marginal de Poisson, associado a um mecanismo de decaimento temporal exponencial para refletir a evolução das forças relativas das equipes ao longo do tempo.

Este artigo deduz a correção de quatro células, preserva as marginais Poisson, define a verossimilhança ponderada no tempo e apresenta um exemplo Python com restrições. A comparação numérica usa entradas fixas explícitas. O ajuste e as probabilidades podem ser reproduzidos separadamente de alegações sobre cotações atuais ou rentabilidade.

2. O Fator de Correção Bivariada de Dixon-Coles

Rho é um parâmetro de dependência dos placares baixos, não a correlação de Pearson entre as contagens de gols. Seu domínio depende das duas intensidades. A implementação de verossimilhança exige todos os fatores tau estritamente positivos. Com lambda=10, mu=2 e rho=-0.35, tau(0,1)=-2.5; todo o conjunto de parâmetros deve ser rejeitado, mesmo ao avaliar um placar alto. Truncar a célula em zero e reescalar definiria outra distribuição.

−min⁡(1/λ,1/μ)<ρ<min⁡(1,1/(λμ))

Para corrigir a falha da independência estocástica sem perder a eficiência de cálculo das distribuições de Poisson, Dixon e Coles formularam a seguinte função de probabilidade conjunta ajustada:

P(X=x,Y=y|λ,μ,ρ)=τx,y(λ,μ,ρ)⋅λxe−λx!⋅μye−μy!

O fator de ajuste τx,y(λ,μ,ρ) é uma função escalar discreta definida pontualmente sobre os resultados de baixa pontuação {0,1}×{0,1}, parametrizada pelo parâmetro de dependência ρ:

τx,y(λ,μ,ρ)={1−λμρpara x=0,y=01+λρpara x=0,y=11+μρpara x=1,y=01−ρpara x=1,y=11para x≥2 ou y≥2

Demonstração Matemática da Conservação da Probabilidade Total

Para que o modelo seja estatisticamente válido, a introdução de τx,y deve respeitar dois axiomas fundamentais: não negatividade (P(X=x,Y=y)≥0) e conservação da probabilidade total (∑x=0∞∑y=0∞P(X=x,Y=y)=1).

Podemos demonstrar a conservação total decompondo o somatório em relação à base clássica de Poisson mais a perturbação sobre os quatro estados modificados:

∑x=0∞∑y=0∞P(X=x,Y=y)=∑x=0∞λxe−λx!∑y=0∞μye−μy!+Δ=1⋅1+Δ

Onde o termo de perturbação Δ é avaliado diretamente sobre os estados (0,0),(0,1),(1,0),(1,1):

Δ=(τ0,0−1)P0(λ)P0(μ)+(τ0,1−1)P0(λ)P1(μ)+(τ1,0−1)P1(λ)P0(μ)+(τ1,1−1)P1(λ)P1(μ)

Substituindo as probabilidades de Poisson não ajustadas P0(λ)=e−λ, P1(λ)=λe−λ, P0(μ)=e−μ e P1(μ)=μe−μ, e evidenciando o termo comum e−λ−μ:

Δ=e−λ−μ[(−λμρ)⋅(1)+(λρ)⋅(μ)+(μρ)⋅(λ)+(−ρ)⋅(λμ)]=e−λ−μρ[−λμ+λμ+λμ−λμ]=e−λ−μρ⋅(0)=𝟎

A soma das perturbações é identicamente nula. Logo, a probabilidade total de 100% permanece perfeitamente conservada em qualquer parametrização válida.

Interpretação Física do Parâmetro de Correlação ρ

O ajuste abaixo escolhe uma região de rho não positivo como ilustração, junto com as restrições de positividade dependentes das intensidades. É uma escolha do modelo, não um sinal universal inferido dos dados de futebol. A família também pode admitir rho positivo: com lambda=1.65, mu=1.15 e rho=0.10, os quatro fatores são 0.81025, 1.165, 1.115 e 0.9, todos positivos.

−0.35≤ρ≤0,τx,y>0

No domínio válido, rho negativo tem os seguintes efeitos algébricos em relação à independência com as mesmas intensidades:

  • No estado (0,0): τ0,0=1−λμρ. Como ρ<0, o produto −λμρ>0, fazendo com que τ0,0>1. A probabilidade de um empate sem gols é aumentada em relação ao Poisson ingênuo.
  • No estado (1,1): τ1,1=1−ρ. Como ρ<0, 1−ρ=1+|ρ|>1. A probabilidade do placar 1 a 1 é explicitamente amplificada.
  • Nos estados (0,1) e (1,0): τ0,1=1+λρ<1 e τ1,0=1+μρ<1. As probabilidades de vitórias magras de 1 a 0 são reduzidas, compensando com exatidão o ganho dos empates.

3. Parametrização das Equipes: Ataque, Defesa e Mando de Campo

No modelo de Dixon e Coles, as expectativas de gols λi,j (equipe mandante i contra visitante j) e μi,j (equipe visitante j contra mandante i) são estruturadas de forma log-linear através das forças latentes de cada clube:

λi,j=αi⋅βj⋅γ,μi,j=αj⋅βi

Onde:

  • αi>0: O índice ofensivo (força de ataque) da equipe i. Um time com αi=1,30 gera 30% mais chances de gol do que a média da competição.
  • βj>0: A fragilidade defensiva (vulnerabilidade a sofrer gols) da equipe j. Um time com βj=0,80 concede 20% menos gols do que a média da liga.
  • γ>0: O fator global de vantagem do mando de campo da liga. Em ligas europeias consolidadas, γ varia entre 1,20 e 1,35.

A Restrição de Identificabilidade de Parâmetros

Um erro conceitual comum em modelos de classificação esportiva é a indeterminação de escala. Multiplicar todos os parâmetros de ataque αk por uma constante c>0 e dividir todas as defesas βk por c gera valores idênticos para λi,j=(cαi)(βj/c)γ=αiβjγ.

Para eliminar graus de liberdade espúrios e fixar o estimador de Máxima Verossimilhança, Dixon e Coles estabeleceram uma restrição de normalização sobre todos os N clubes do campeonato:

1N∑k=1Nαk=1,00

Isso padroniza a força média de ataque da liga em exatamente 1,00, servindo de âncora matemática para todas as métricas relativas.

Fixar o ataque médio em um remove a simetria de escala entre ataque e defesa. Isso não demonstra um ótimo global único da verossimilhança, informação suficiente nos confrontos ou precisão preditiva. Os índices são relativos ao modelo e à amostra ajustados; só a normalização não torna comparáveis diretamente os índices de competições diferentes.

4. Decaimento Temporal Exponencial: A Função de Memória ξ

Modelos ingênuos tratam partidas disputadas há dois anos com o mesmo peso de partidas realizadas no último domingo. No futebol real, transferências de atletas, trocas de comissão técnica e oscilações físicas alteram substancialmente o rendimento das equipes.

Para incorporar a dinâmica temporal sem perder a robustez amostral, Dixon e Coles introduziram uma função de decaimento temporal exponencial wk(ξ) para cada partida histórica k realizada na data tk, relativa à data de previsão t:

wk(ξ)=exp⁡(−ξ⋅(t−tk))

Onde (t−tk) representa o tempo decorrido em dias e ξ>0 é o hiperparâmetro de decaimento contínuo.

A unidade temporal deve corresponder ao coeficiente. Este exemplo usa dias decorridos e uma taxa ilustrativa ξ=0.0065 por dia, com meia-vida aproximada de 106.638 dias. Se as idades forem medidas em semanas, a taxa equivalente é 7ξ=0.0455 por semana; manter o mesmo número mudaria os pesos. Essa aritmética não identifica um ótimo empírico. Escolha a taxa em dados cronológicos separados de validação e informe a métrica de avaliação.

t1/2=ln⁡2ξ,w(t)=e−ξt

5. Formulação de Máxima Verossimilhança (MLE)

Dado um histórico de M jogos disputados, onde cada partida k envolve o mandante hk, visitante ak, placar (xk,yk) e data tk, a função de log-verossimilhança ponderada a ser maximizada é:

ln⁡L(Θ)=∑k=1Mwk(ξ)⋅ln⁡[τxk,yk(λk,μk,ρ)⋅λkxke−λkxk!⋅μkyke−μkyk!]

Ao expandir o logaritmo em seus termos aditivos, obtemos:

ln⁡L(Θ)=∑k=1Mwk(ξ)[ln⁡τxk,yk(λk,μk,ρ)+xkln⁡λk−λk+ykln⁡μk−μk−ln⁡(xk!)−ln⁡(yk!)]

Como os termos fatoriais −ln⁡(xk!)−ln⁡(yk!) dependem apenas dos dados observados e não dos parâmetros Θ, eles são ignorados durante a otimização computacional. Minimizamos, portanto, a log-verossimilhança negativa ponderada:

minΘ⁡𝒩ℒℒ(Θ)=−∑k=1Mwk(ξ)[ln⁡τxk,yk(λk,μk,ρ)+xkln⁡λk−λk+ykln⁡μk−μk]

O exemplo usa SLSQP para lidar com a igualdade da escala de ataque e as desigualdades não lineares de tau. Verifica o sucesso do otimizador e as margens de viabilidade antes de armazenar os parâmetros. Uma terminação numérica bem-sucedida não certifica ótimo global nem desempenho em partidas futuras.

6. Comparação Numérica com Intensidades Fixas

Este cálculo usa parâmetros fixos λ=1.65, μ=1.15 e ρ=−0.12. As probabilidades são somadas até 45 gols. As odds são os inversos das probabilidades de cada modelo. O exemplo é reproduzível sem cotações observadas de fechamento. Uma diferença entre dois modelos não estabelece vantagem sobre o mercado.

ResultadoProbabilidade independenteOdd no modelo independenteProbabilidade Dixon-ColesOdd no modelo Dixon-ColesVariação, pontos percentuais
0–06.081006%16.44467.465651%13.3947+1.384645
1–111.538709%8.666512.923355%7.7379+1.384645
1–010.033660%9.96658.649015%11.5620-1.384645
0–16.993157%14.29975.608512%17.8300-1.384645
Vitória mandante49.026329%2.039747.641684%2.0990-1.384645
Empate24.395242%4.099227.164533%3.6813+2.769290
Vitória visitante26.578428%3.762425.193783%3.9692-1.384645
Menos de 2.546.945368%2.130146.945368%2.1301+0.000000

Under 2.5 contém as quatro células corrigidas, cujas alterações se cancelam. Sua probabilidade é 46.945368% nos dois modelos, com odd aproximada de 2.1301. Over 2.5 também não muda. A dependência pode alterar um total que contenha só parte dessas células, como Under 1.5, além dos empates e de ambas marcam. Reestimar as intensidades pode mudar Under 2.5 através delas. É um efeito diferente de aplicar rho mantendo as intensidades fixas.

A=−ρλμe−(λ+μ),ΔP00=ΔP11=A,ΔP01=ΔP10=−A ΔP(Under 2.5)=A−A−A+A=0

7. Implementação Completa em Python: Classe DixonColesModel

Abaixo encontra-se o script completo em Python contendo a implementação da classe com otimização numérica via scipy.optimize.minimize:

O exemplo restringe os quatro fatores de placares baixos para cada par ordenado de equipes conhecidas, fixa o ataque médio em um e verifica sucesso e viabilidade do otimizador. Probabilidades inválidas são rejeitadas, não truncadas. A grade padrão usa quantis Poisson para manter a massa omitida abaixo de cerca de 2e-12, informa essa massa e conserva as probabilidades sem renormalização. Xi é uma taxa diária ilustrativa; sua escolha exige validação separada.

import numpy as np
from scipy.optimize import minimize
from scipy.stats import poisson


class DixonColesModel:
    def __init__(self, xi=0.0065):
        # Illustrative daily decay rate, not a validated universal optimum.
        if not np.isfinite(xi) or xi < 0:
            raise ValueError("xi must be a finite nonnegative daily rate")
        self.xi = xi
        self.teams = []
        self.team_indices = {}
        self.params = None
        self.gamma = 1.25
        self.rho = -0.11

    @staticmethod
    def tau(x, y, lambda_, mu, rho):
        # Check the whole joint model, including unobserved low-score cells.
        if not np.all(np.isfinite([lambda_, mu, rho])) or min(lambda_, mu) <= 0:
            raise ValueError("Intensities must be finite and positive")
        factors = [1 - lambda_ * mu * rho, 1 + lambda_ * rho,
                   1 + mu * rho, 1 - rho]
        if min(factors) <= 0:
            raise ValueError("rho is outside the strictly positive tau domain")
        return {(0, 0): factors[0], (0, 1): factors[1],
                (1, 0): factors[2], (1, 1): factors[3]}.get((x, y), 1.0)

    def bivariate_prob(self, x, y, lambda_, mu, rho):
        if not np.all(np.isfinite([x, y])) or min(x, y) < 0 or int(x) != x or int(y) != y:
            raise ValueError("Goals must be nonnegative integers")
        factor = self.tau(x, y, lambda_, mu, rho)
        return factor * poisson.pmf(x, lambda_) * poisson.pmf(y, mu)

    def _unpack_params(self, params, n_teams):
        return (params[:n_teams], params[n_teams:2*n_teams],
                params[2*n_teams], params[2*n_teams + 1])

    def fit(self, matches):
        self.params = None
        if not matches:
            raise ValueError("At least one match is required")
        for m in matches:
            goals = [m['home_goals'], m['away_goals']]
            age = m.get('days_ago', 0.0)
            if (m['home'] == m['away'] or not np.all(np.isfinite(goals + [age]))
                    or min(goals) < 0 or any(int(v) != v for v in goals) or age < 0):
                raise ValueError("Invalid teams, goals or match age")
        self.teams = sorted({m['home'] for m in matches} | {m['away'] for m in matches})
        self.team_indices = {team: i for i, team in enumerate(self.teams)}
        n_teams = len(self.teams)
        init = np.concatenate([np.ones(n_teams), np.ones(n_teams), [1.25, -0.10]])

        def tau_constraints(params):
            alpha, beta, gamma, rho = self._unpack_params(params, n_teams)
            values = []
            # Every ordered pairing of known teams must define a valid model.
            for h in range(n_teams):
                for a in range(n_teams):
                    if h == a:
                        continue
                    lam, mu = alpha[h] * beta[a] * gamma, alpha[a] * beta[h]
                    values.extend([1 - lam * mu * rho, 1 + lam * rho,
                                   1 + mu * rho, 1 - rho])
            return np.asarray(values) - 1e-8

        def loss_fn(params):
            alpha, beta, gamma, rho = self._unpack_params(params, n_teams)
            nll = 0.0
            for m in matches:
                h, a = self.team_indices[m['home']], self.team_indices[m['away']]
                lam, mu = alpha[h] * beta[a] * gamma, alpha[a] * beta[h]
                try:
                    factor = self.tau(m['home_goals'], m['away_goals'], lam, mu, rho)
                except ValueError:
                    return 1e12  # Reject an infeasible optimizer trial, never clip a probability.
                weight = np.exp(-self.xi * m.get('days_ago', 0.0))
                log_prob = (np.log(factor) + poisson.logpmf(m['home_goals'], lam)
                            + poisson.logpmf(m['away_goals'], mu))
                nll -= weight * log_prob
            return float(nll)

        constraints = [
            {'type': 'ineq', 'fun': tau_constraints},
            {'type': 'eq', 'fun': lambda p: np.mean(p[:n_teams]) - 1.0},
        ]
        bounds = [(0.05, 3.5)] * (2*n_teams) + [(1.0, 1.8), (-0.35, 0.0)]
        res = minimize(loss_fn, init, method='SLSQP', bounds=bounds,
                       constraints=constraints, options={'maxiter': 1000, 'ftol': 1e-9})
        if (not res.success or not np.all(np.isfinite(res.x)) or not np.isfinite(res.fun)
                or np.min(tau_constraints(res.x)) < -1e-9
                or abs(np.mean(res.x[:n_teams]) - 1) > 1e-8):
            raise RuntimeError(f"No valid converged fit: {res.message}")
        self.params = res.x
        _, _, self.gamma, self.rho = self._unpack_params(res.x, n_teams)
        return res

    def predict_score_matrix(self, home_team, away_team, max_goals=None):
        if self.params is None:
            raise ValueError("Fit the model first")
        alpha, beta, gamma, rho = self._unpack_params(self.params, len(self.teams))
        h, a = self.team_indices[home_team], self.team_indices[away_team]
        lam, mu = alpha[h] * beta[a] * gamma, alpha[a] * beta[h]
        self.tau(0, 0, lam, mu, rho)
        if max_goals is None:
            max_goals = int(max(poisson.ppf(1 - 1e-12, lam), poisson.ppf(1 - 1e-12, mu)))
        if not isinstance(max_goals, (int, np.integer)) or max_goals < 1:
            raise ValueError("max_goals must be an integer of at least one")
        goals = np.arange(max_goals + 1)
        matrix = np.outer(poisson.pmf(goals, lam), poisson.pmf(goals, mu))
        for x, y in [(0, 0), (0, 1), (1, 0), (1, 1)]:
            matrix[x, y] *= self.tau(x, y, lam, mu, rho)
        # Keep the original probability mass; disclose the omitted grid tail.
        self.omitted_mass = float(max(0.0, 1 - matrix.sum()))
        return matrix, lam, mu

    def predict_1x2(self, home_team, away_team):
        matrix, lam, mu = self.predict_score_matrix(home_team, away_team)
        home, draw, away = np.tril(matrix, -1).sum(), np.trace(matrix), np.triu(matrix, 1).sum()
        return {'home_win': float(home), 'draw': float(draw), 'away_win': float(away),
                'fair_odds_home': float(1/home), 'fair_odds_draw': float(1/draw),
                'fair_odds_away': float(1/away), 'lambda': float(lam), 'mu': float(mu),
                'omitted_probability_mass': self.omitted_mass}

8. Extensões Contemporâneas e Conclusão

Embora a formulação de Dixon e Coles tenha sido publicada em 1997, ela continua sendo a espinha dorsal de precificação de casas profissionais mundiais. Variações modernas introduzem cópulas contínuas arquimedianas (Frank e Gumbel) ou modelos bivariados de Poisson com choque comum (Karlis e Ntzoufras). Todavia, para precificação pré-jogo de 1X2, Dupla Hipótese, Placar Exato e Linhas de Totais, o ajuste do fator τ permanece incomparável em clareza analítica, precisão empírica e velocidade de execução estocástica.

Perguntas Frequentes

PESQUISA RELACIONADA

Estudos com Referência Cruzada

Compare o mesmo mercado

Links de parceiros

1win Sports: confira evento, odds e regras de liquidação

O que está no preço → Visitar 1win Sports 18+ · Termos no site

Stake Sportsbook: compare o mesmo evento, mercado e regras

O que está no preço → Visitar Stake 18+ · Termos no site

Confira a cotação atual, o mercado exato, as regras e a disponibilidade no seu país. O resultado da calculadora depende das premissas e não confirma uma oportunidade ao vivo.