Spaces:
Running
Running
| # Revisão profunda de precisão — v2.1-precision | |
| > Documento histórico da revisão v2.1. Para as mudanças atuais, consulte | |
| > `RELEASE_NOTES_v2.2.md`. | |
| Esta revisão focou em erros silenciosos que podem produzir uma confiança artificialmente alta. | |
| ## 1. Correções críticas | |
| ### 1.1 Tempo regulamentar em mata-mata | |
| O código antigo usava `score.fullTime`. Em partidas com prorrogação, isso pode representar 120 minutos e classificar como vitória algo que foi empate no mercado 1X2 de 90 minutos. | |
| A versão nova usa: | |
| 1. `score.regularTime`, quando existe; | |
| 2. `score.fullTime` como fallback. | |
| ### 1.2 Histórico não é mais global | |
| O código anterior criava um catálogo global de equipes e tentava fazer fuzzy matching entre todas as ligas. Isso permitia casar nomes semelhantes de competições diferentes. | |
| Agora cada evento do The Odds API possui um mapeamento explícito para o código do football-data.org: | |
| - EPL → PL | |
| - EFL Championship → ELC | |
| - Bundesliga → BL1 | |
| - Serie A Itália → SA | |
| - La Liga → PD | |
| - Ligue 1 → FL1 | |
| - Brasileirão → BSA | |
| - Eredivisie → DED | |
| - Primeira Liga → PPL | |
| - Champions League → CL | |
| O matching ocorre somente dentro da competição correta. | |
| ### 1.3 Matching de times mais rígido | |
| O motor usa: | |
| - ID da equipe no football-data.org quando disponível; | |
| - nome oficial; | |
| - shortName; | |
| - TLA; | |
| - aliases; | |
| - score mínimo; | |
| - diferença mínima entre o melhor e o segundo candidato. | |
| Se o nome for ambíguo, o evento é rejeitado. | |
| ### 1.4 Odds agregadas corretamente | |
| A versão anterior fazia a mediana das odds e só depois removia a margem. Isso mistura preços de bookmakers diferentes e pode criar uma probabilidade sintética incoerente. | |
| Agora: | |
| 1. cada bookmaker precisa ter Casa/Empate/Fora completos; | |
| 2. a margem é removida **dentro de cada bookmaker**; | |
| 3. probabilidades de-vigadas são agregadas robustamente; | |
| 4. odds de referência continuam sendo medianas; | |
| 5. bookmakers com timestamp muito velho são descartados; | |
| 6. dispersão entre casas é calculada e entra no Risk Gate. | |
| ### 1.5 Mercado como prior | |
| Mercados líquidos contêm informação que um modelo gratuito sem escalações/xG não possui. | |
| A nova versão não ignora isso. O modelo interno (Dixon-Coles + Elo + forma) é combinado com o consenso de mercado. Quanto menor a qualidade dos dados, mais forte o shrinkage para o mercado. | |
| Isso reduz overconfidence. | |
| ## 2. Modelo de gols | |
| O Poisson foi refeito. | |
| O código antigo fazia médias lineares simples de gols marcados e sofridos. A versão nova: | |
| - separa casa/fora; | |
| - usa half-life de recência; | |
| - calcula tamanho efetivo da amostra; | |
| - aplica shrinkage para a média da liga; | |
| - combina ataque e defesa geometricamente para evitar explosões; | |
| - ajusta placares 0-0, 1-0, 0-1 e 1-1 com Dixon-Coles; | |
| - estima o `rho` da competição a partir da taxa recente de empates, quando existe amostra suficiente. | |
| ## 3. Elo e forma | |
| Elo continua sendo um modelo lento/estrutural. | |
| Forma é separada e recebe peso menor. Jogos antigos perdem peso progressivamente. Assim uma sequência curta não domina o sistema. | |
| ## 3.1 Tuning walk-forward dos pesos | |
| Os pesos Poisson/Elo/Forma não ficam mais totalmente fixos. Para cada competição, o motor reencena uma janela histórica em ordem temporal: | |
| 1. escolhe uma partida histórica de avaliação; | |
| 2. treina/calcula usando **somente partidas anteriores**; | |
| 3. guarda as três probabilidades dos modelos; | |
| 4. repete para dezenas de partidas; | |
| 5. procura uma grade grossa de pesos que minimize Brier Score; | |
| 6. encolhe os pesos aprendidos de volta para um prior conservador. | |
| A grade é propositalmente grossa e o peso aprendido nunca é aceito se piorar o Brier do prior. Isso evita otimização excessiva em amostra pequena. | |
| ### 3.2 Brier Skill fora da amostra | |
| A v2.1 acrescenta uma segunda verificação. Em cada partida de validação, o motor cria também uma **climatologia temporal** usando apenas os resultados conhecidos antes daquela partida. O ensemble recebe um Brier Skill Score contra essa referência. | |
| Esse skill não serve para inflar a probabilidade. Ele funciona como **regulador de confiança**: | |
| - skill forte + amostra suficiente → o modelo interno pode ter mais influência; | |
| - skill fraco ou ainda desconhecido → a probabilidade é puxada mais para o consenso de mercado; | |
| - componentes Poisson/Elo que não sustentam o favorito podem bloquear uma seleção mesmo que o posterior agregado pareça alto. | |
| Assim, concordância interna deixa de ser confundida com habilidade preditiva real. | |
| ## 4. Probabilidade conservadora | |
| O código antigo chamava uma penalização heurística de “limite conservador”, mas a fórmula parecia um intervalo estatístico sem ter distribuição amostral válida. | |
| Agora é explicitamente **reliability shrinkage**: | |
| - qualidade dos dados; | |
| - concordância dos modelos; | |
| - profundidade/estabilidade do mercado; | |
| - confiança do matching de nomes; | |
| - habilidade walk-forward do ensemble na competição. | |
| A probabilidade é puxada em direção a 50% conforme a confiabilidade cai. | |
| Isso é mais honesto e mais robusto. | |
| ## 5. Calibração forward | |
| Depois que a mesma versão acumula amostra suficiente de palpites liquidados, o sistema aplica uma correção fraca baseada no desempenho real próximo daquela faixa de probabilidade. | |
| Proteções: | |
| - só usa resultados já encerrados; | |
| - só usa a mesma `model_version`; | |
| - exige amostra efetiva mínima; | |
| - correção máxima de ±5 pontos percentuais; | |
| - prior forte centrado na previsão atual. | |
| Não há “autoaprendizado” agressivo em meia dúzia de apostas. | |
| ## 6. Histórico e métricas | |
| O histórico agora: | |
| - registra uma única recomendação por evento; | |
| - não cria duas apostas opostas se a seleção mudar em outro scan; | |
| - liquida por competição + horário + ambos os nomes; | |
| - mede win rate; | |
| - ROI; | |
| - Brier Score; | |
| - Log Loss; | |
| - ECE de calibração; | |
| - gap previsão x resultado; | |
| - drawdown máximo em unidades. | |
| ## 7. Bilhetes | |
| Multiplicar probabilidades assume independência. Em jogos diferentes a aproximação é útil, mas não perfeita. | |
| A v2 adiciona um **stress conservador** para múltiplas pernas da mesma competição, principalmente quando ocorrem em horários próximos. O painel mostra: | |
| - odd total; | |
| - se o alvo foi atingido; | |
| - probabilidade conjunta; | |
| - probabilidade conjunta sob stress; | |
| - EV estimado; | |
| - fator de dependência. | |
| ## 8. APIs e cota | |
| ### football-data.org | |
| A versão v2 busca por competição/temporada e mantém cache local. Quando a temporada atual ainda possui poucos jogos, busca a temporada anterior. Há um rate guard com folga abaixo do limite gratuito. | |
| ### The Odds API | |
| Antes de gastar quota em `/odds`, consulta a lista `/sports` para descobrir ligas ativas. Essa chamada é gratuita segundo a documentação oficial. | |
| ## 9. Limitações que permanecem | |
| Para manter o projeto gratuito: | |
| - não há xG premium universal; | |
| - escalações/lesões não são garantidas em todas as ligas; | |
| - a Betano não é raspada automaticamente; | |
| - a odd Betano deve ser digitada no painel; | |
| - calibração forte precisa de meses de forward tracking; | |
| - uma freebet odd 10 continua sendo de risco alto, independentemente do nome “SAFE”. | |
| O sistema prefere dizer **“nenhuma seleção aprovada”** a fabricar confiança. | |
| ## 10. Validação executada | |
| Na revisão final: | |
| - `python -m compileall -q app tests` → OK | |
| - `pytest -q` → **24 passed** | |
| - FastAPI `/api/health` → HTTP 200 | |
| - FastAPI `/api/state` → HTTP 200 | |
| - painel `/` → HTTP 200 | |
| - `GET /api/cron/daily` → HTTP 405 e `POST` sem segredo → HTTP 401 | |
| - JavaScript do painel validado com `node --check` | |
| - validação walk-forward inclui baseline temporal e nunca recebe partidas futuras | |
| - simulação sintética de favorito forte → probabilidade final ficou entre modelo interno e mercado, como projetado | |
| - stress sintético adicional → **250 previsões em 10 competições**, todas normalizadas e sem exceções; tuning concluído em ~1,4 s no ambiente de revisão | |
| As integrações reais não foram chamadas com as chaves do usuário nesta revisão. O primeiro scan no Space continua sendo a validação de integração final. A tentativa de instalar um ambiente virtual novo também não pôde ser concluída porque o container de revisão não tinha acesso DNS externo; os testes foram executados com as bibliotecas já instaladas no ambiente. | |