Troubleshooting - italostatonato/stock-screener-automation GitHub Wiki

Troubleshooting

Revisado em 05/10/2026.

Preparar e executar

Use Git, Python 3.11 ou superior e Chrome para a coleta de FIIs. Instale as dependências de requirements.txt num ambiente virtual. Node.js 24 permite executar os testes JavaScript da carteira híbrida e de rendering.

python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install -r requirements.txt
python main.py
python scripts/healthcheck_data.py
python -m pytest tests/ -v

No Linux/macOS, ative o ambiente com source .venv/bin/activate. Execute os comandos na raiz do projeto. Se houver erro ao importar src, confira o diretório atual, o interpretador ativo e a presença de src/__init__.py; não presuma que o arquivo esteja faltando.

O arquivo paths.local_input_file, quando presente, substitui a coleta de FIIs. Logs ficam em logs/YYYY-MM-DD.log, o Excel em data/output/Top20_Ranking_YYYY-MM-DD.xlsx e o JSON em docs/data/YYYY-MM-DD.json. A data usa America/Sao_Paulo. Reexecutar no mesmo dia substitui o ranking Excel daquela data, removendo ativos que saíram do Top N. Números lidos do Excel preservam suas unidades: percentuais numéricos já são frações; textos como 7,5% são convertidos.

Backup e escopo

Antes de reprocessar ou alterar dados, preserve uma cópia de data/. Preserve também docs/data/ quando a operação for reescrever snapshots do dashboard. Use uma pasta externa ou temporária para não incluir o backup num commit por acidente:

$BackupDir = Join-Path $env:TEMP ("radar-backup-" + [guid]::NewGuid().ToString("N"))
New-Item -ItemType Directory -Path $BackupDir | Out-Null
Copy-Item -LiteralPath "data" -Destination $BackupDir -Recurse
Copy-Item -LiteralPath "docs/data" -Destination (Join-Path $BackupDir "dashboard-data") -Recurse

Uma mudança apenas documental não precisa executar main.py. Esse comando coleta dados, treina modelos e pode entregar Excel. Revise e adicione ao Git somente os arquivos relacionados à mudança; preserve trabalhos locais de outras tarefas.

Healthcheck

python scripts/healthcheck_data.py

O comando atualiza o manifesto do lake, reconstrói o índice do dashboard e grava data/lake/quality_report.json. Portanto, não é somente leitura. O retorno é código 1 para error e código 0 para ok ou warn. Para inspecionar sem escrever, use python scripts/healthcheck_data.py --read-only.

A verificação cobre chaves nulas e duplicadas, esquema e preço de entrada da carteira, cobertura de FII/ACAO nas datas recentes, legibilidade de Parquets, estrutura/data dos JSONs e coerência entre o lake e o índice do dashboard. O pipeline também exige o snapshot da data da execução. Snapshots históricos listados em known_incomplete_snapshots.json podem gerar avisos conhecidos; investigue avisos novos em vez de suprimi-los.

Use --read-only nas auditorias documentais. Se o pytest no Windows falhar por permissão no diretório temporário, escolha uma pasta nova no projeto:

$TestRunDir = ".test-tmp/pytest-" + [guid]::NewGuid().ToString("N")
python -m pytest tests/ -v --basetemp=$TestRunDir -o cache_dir=.test-tmp/pytest-cache

Workflow e publicação

Weekly FII Screener roda toda segunda, 10h de São Paulo (0 13 * * 1), ou por Actions → Weekly FII Screener → Run workflow. Também publica ajustes por push, conforme os caminhos abaixo. O horário das 10h é o início agendado da coleta; a publicação depende da conclusão dos jobs. Arquivos particionados por data não significam que a execução automática seja diária.

  • test: Python 3.11, Node 24, instalação com cache pip e pytest tests/ -v.
  • screener: depende dos testes e só roda no cron ou acionamento manual; prepara Chrome, sincroniza a main, executa pipeline e healthcheck, salva artefatos de saída por 90 dias e commita docs/data/, data/lake/, data/ml/, data/backtest/ e data/delivery/.
  • deploy: usa a main atual e publica docs/ no GitHub Pages quando os testes passam, mesmo se o screener falhar ou for ignorado no push.

Os timeouts são 25 minutos para testes e 60 para coleta. A concorrência é controlada por branch e não cancela a execução já em andamento. A etapa opcional de notificação de falha do screener usa TELEGRAM_BOT_TOKEN e TELEGRAM_CHAT_ID nos Secrets.

Para problemas de push, confira remote, credenciais e permissão de escrita. O workflow já declara contents: write; a publicação usa pages: write e id-token: write no job de deploy. O workflow tests.yml roda a suíte em pushes de código/documentação e pull requests, com permissão de leitura. Esse workflow não inicia coleta nem deploy. Alterações de docs/index.html, docs/assets/ ou de run_screener.yml na main também acionam a publicação pelo run_screener.yml: executam test e deploy, ignorando screener. Isso publica ajustes da interface sem aguardar a próxima segunda-feira nem gerar um novo snapshot.

A revisão documental semanal é separada, segunda-feira às 12h de São Paulo, e é administrada no Codex. Veja Manutenção da documentação.

Site no Sites

O site Radar Semanal tem publicação própria no Sites. O servidor espelha o HTML, os dados e os recursos publicados no GitHub Pages. A aba visível verifica a versão a cada 60 segundos e recarrega quando necessário, aguardando a edição de campos. O workflow deste repositório continua responsável pela coleta semanal; o espelhamento não executa o pipeline.

O HTML original atualizado no Pages chega ao Sites sem nova publicação da réplica. Alterações no Worker, no contador, nas adaptações próprias ou na cópia de contingência continuam exigindo publicação no projeto do Sites. Alterações isoladas em recursos externos ao HTML podem exigir recarga manual: a versão monitorada compara o HTML, o índice e o snapshot mais recente.

Se aparecer o aviso de última cópia disponível, confira a data exibida e a publicação dos dados no GitHub Pages. Se o contador mostrar Indisponível, verifique a API e o banco do projeto no Sites; a falha não representa total zero. O contador é exclusivo do endereço no Sites e persiste no banco D1. Veja Site no Sites e contador de visitantes para diagnóstico e responsabilidades de publicação, verificados em 05/10/2026.

Fonte indisponível ou seleção vazia

Consulte o log e repita a execução quando a fonte estiver disponível. O Fundamentus usa timeout de 30s e duas novas tentativas. O intervalo fundamentus_retry_delay começa em 15s e dobra (15s, 30s), limitado a 120s. O log distingue timeout de conexão, de resposta, erro HTTP e tabela ilegível. Falhas na etapa de coleta preservam logs/ no artefato screener-failure-ID por 30 dias. A coleta de FIIs depende de Chrome e do HTML do Fundsexplorer.

Não existe fallback de quartis. Se a seleção ficar vazia, confira colunas, unidades percentuais e pisos em config.yaml. O pipeline interrompe a geração de um novo snapshot quando a coleta/seleção obrigatória falha. Os dois rankings são validados antes da primeira escrita dos históricos. As escritas posteriores ainda não formam uma transação única entre arquivos.

Falhas no lake, na reconstrução ou na exportação, e qualidade com error, interrompem main.py. Falhas em indicadores, ML sombra ou entrega opcional ficam nos logs. Uma falha ao construir datasets impede treinar dados antigos.

Rebuild e scripts históricos

python scripts/rebuild_from_lake.py

O rebuild não coleta fontes: reconstrói históricos, carteira, datasets e previsões ML em 7d, atualiza manifesto/índice e roda qualidade. Sem snapshots no lake, encerra antes de reconstruir. Ele não recria os payloads completos do dashboard nem os Excels finais.

Os scripts de pesquisa são executados separadamente:

python scripts/build_observed_history.py
python scripts/run_observed_backtest.py
python scripts/build_point_in_time_history.py --start 2021-01-01
python scripts/run_point_in_time_backtest.py

--offline está disponível em build_point_in_time_history.py, run_observed_backtest.py e run_point_in_time_backtest.py; exige caches já preenchidos. Leia Backtests antes de reprocessar. Não copie snapshots sintéticos para o lake observado.

scripts/refresh_ml_7d_primary_from_docs.py encaminha ao rebuild do lake, preservando os JSONs históricos. Não usa Top N como universo ML completo. Os scripts apply_ml_* são comandos de compatibilidade sem escrita.

Dashboard com data antiga

Confira se a coleta realmente concluiu e se o JSON esperado existe. Reconstrua apenas o índice com a função oficial:

python -c "from src.data_lake import rebuild_dashboard_index; print(rebuild_dashboard_index('docs/data'))"

Esse comando altera docs/data/index.json. Para um conflito de Git nesse arquivo, confira os snapshots existentes antes de reconstruir e marcar a resolução. Use git status para verificar o estado de um rebase; não apague diretórios internos de .git como rotina de troubleshooting.

Para servir o dashboard localmente:

python -m http.server 8000 --directory docs

Abra localhost:8000.

Entrega local do Excel

src/delivery.py copia o Excel para paths.onedrive_output_dir, resolvido pela variável SCREENER_EXCEL_OUTPUT_DIR:

$env:SCREENER_EXCEL_OUTPUT_DIR = "C:/Users/<voce>/OneDrive/Recomendacoes"
python main.py

Sem variável, a cópia é pulada e o Excel permanece em data/output/. O destino recebe Top20_Ranking_YYYY-MM-DD.xlsx e Top20_Ranking_Atual.xlsx. O log data/delivery/delivery_log.jsonl registra status, SHA256, tamanho e nomes de arquivo.

O runner Linux não acessa uma pasta Windows local; no Actions, consulte os artefatos. Para testar uma entrega já configurada:

python scripts/test_delivery.py --file data/output/Top20_Ranking_YYYY-MM-DD.xlsx

Substitua a data por um arquivo existente. Esse comando efetua a cópia e registra entrega. Microsoft Graph permanece uma etapa futura.

⚠️ **GitHub.com Fallback** ⚠️