Como Funciona - italostatonato/stock-screener-automation GitHub Wiki
Como Funciona
Revisado em 05/10/2026. O Radar Semanal executa uma coleta semanal de FIIs e ações, gera rankings e derivados e publica um dashboard estático. A coleta tem início agendado para segunda-feira às 10h de Brasília e também pode ser acionada manualmente; a revisão documental das 12h é uma tarefa separada.
Ingestão e seleção
main.py carrega config.yaml por src/config.py e usa a data civil de
America/Sao_Paulo para nomear logs e snapshots. Um arquivo em
paths.local_input_file substitui a coleta de FIIs quando existe; do contrário,
src/scraper.py usa Selenium/Chrome no Fundsexplorer. A fonte padrão de ações
é a tabela HTTP do Fundamentus.
src/cleaner.py normaliza os FIIs. O adaptador de ações já entrega as colunas
numéricas compatíveis. src/scorer.py calcula sete percentis com pesos iguais
no universo completo. src/filters.py aplica pisos de elegibilidade, ordena
pelo score, desempata pelo ticker e limita o Top N. A seleção de ações também
remove classes duplicadas de uma mesma empresa. Veja Metodologia.
Um Top FII vazio interrompe a execução antes das escritas de histórico. Coleta, score e Top Ações não vazio também são obrigatórios. Uma falha de ações ocorre antes de escrever os históricos de qualquer classe. As escritas posteriores ainda não são uma transação única entre todos os arquivos.
Persistência
src/storage.py: Excels históricos emdata/old/e Excel final emdata/output/, ignorados pelo Git.src/ml_storage.py: históricos dos universos comData_Execucao.src/backtest.py: carteira histórica com preço de entrada e backtest legado.src/data_lake.py: snapshots por data, manifestos, reconstrução e qualidade.src/delivery.py: cópia opcional do Excel e log emdata/delivery/.
data/lake/snapshots/YYYY-MM-DD/
fii_universe.parquet
acoes_universe.parquet
top_fiis.parquet
top_acoes.parquet
carteira.parquet
manifest.json
data/lake/manifest.json
data/lake/quality_report.json
data/lake/known_incomplete_snapshots.json
O lake é a fonte oficial do histórico observado. Os caminhos são particionados por data, não por ID da execução: rodar novamente no mesmo dia atualiza a partição daquela data. Snapshots históricos reconhecidos como incompletos são preservados e identificados no arquivo de exceções.
Depois de salvar o lake, main.py chama rebuild_legacy_tables_from_lake()
para reconstruir os históricos de data/ml/ e a carteira de data/backtest/.
Derivados analíticos
src/dataset_builder.py cria features e targets de 7, 30, 60 e 90 dias.
src/ml_models.py treina e calcula previsões em modo sombra.
src/ml_confidence.py resume maturidade e desempenho validado.
Treino e previsão ainda acontecem juntos, em 7d no pipeline e no rebuild.
Previsões são identificadas por horizonte e o treino exige targets realizados
até a data prevista. Leia Pipeline ML.
O histórico retroativo é separado da execução semanal:
src/observed_history.py: consolida carteiras realmente publicadas.src/point_in_time.py: reconstrói sinais mensais de FIIs com dados CVM/B3.src/backtest_engine.py: aplica calendário, preços ajustados, custos, turnover e auditoria de cobertura.data/point_in_time/: snapshots sintéticos e resultados isolados do lake.
Esses scripts não são chamados pelo workflow semanal. Suas premissas diferem das curvas de preço do dashboard. Veja Backtests.
Exportação e interface
src/market_data.py coleta indicadores e nomes de ativos.
src/benchmark.py prepara séries de mercado e macroeconomia.
src/formatter.py formata o Excel.
src/exporter.py gera docs/data/YYYY-MM-DD.json por substituição atômica e
reconstrói o índice de datas. Valores numéricos não finitos não são aceitos no
JSON. Os derivados respeitam paths.data_dir; o histórico de maturidade usa
o diretório de saída do dashboard. O Excel conserva células numéricas.
Metadados externos são escapados ao inserir texto em HTML e tooltips usam
textContent. Os testes de rendering cobrem markup, aspas e entidades.
docs/index.html concentra HTML, CSS e JavaScript da aplicação. O navegador
consome os snapshots e calcula a alocação, as quantidades inteiras e as curvas
da carteira híbrida com os pesos selecionados. A máscara IMask é distribuída
localmente em docs/assets/vendor/. Não há backend de ordens ou autenticação
própria no dashboard. O link de apresentação abre um recurso externo de leitura.
Coleta → Normalização → Score → Elegibilidade/Top N
→ Históricos e lake → Reconstrução → Datasets/ML
→ Excel e JSON → Qualidade → Entrega local opcional
Lake/JSON/Excel observados → Histórico observado → Motor de backtest
CVM/B3 → Histórico point-in-time isolado → Motor de backtest
JSON → Dashboard → Simulação de alocação no navegador
O JSON é uma saída de apresentação. A recuperação histórica pode usá-lo como fonte secundária quando o lake não cobre uma data; esse é um caminho explícito de recuperação, não a fonte primária da coleta.
Orquestração e limites
O workflow run_screener.yml roda às
segundas, 10h de São Paulo, ou por acionamento manual; nesses eventos, test
precede screener. Pushes na main que alterem docs/index.html,
docs/assets/** ou .github/workflows/run_screener.yml também acionam o
workflow, mas ignoram screener: executam testes e publicação, sem coleta.
O job deploy consulta a main atual e roda quando os testes passam, mesmo
se screener falhar ou for ignorado. A etapa independente de healthcheck bloqueia o commit
automático em caso de error. O próprio main.py interrompe em falhas de lake,
reconstrução, exportação ou qualidade. Indicadores, ML e entrega opcional
podem falhar com registro em log. tests.yml valida pushes e pull requests
sem executar coleta ou publicação.
Os principais limites são dependência de fontes públicas, crescimento de binários no Git, cobertura de preços históricos e maturidade estatística. Particionamento adicional, separação de treino/previsão e entrega remota via Microsoft Graph permanecem evoluções futuras.