EN

Dados B3Guias › Python

Guia · Python

Screener de ações da B3 em Python, sem olhar o futuro

O erro mais comum de quem testa uma ideia de investimento com dados de balanço é usar um número que ainda não existia na data do teste. O balanço de 2018 só chega à CVM em 2019 — em média, 100 dias depois do fim do exercício. Este guia filtra ações pelo que estava público em cada data, e guarda o resultado de um jeito que outra pessoa consegue conferir.

Instalar

pip install dadosb3

O filtro percorre o universo inteiro, então exige chave — a grátis serve (200 consultas por dia, sem cartão). Deixe-a na variável de ambiente DADOS_B3_API_KEY ou passe no construtor.

Duas perguntas diferentes: ano e as_of

from dadosb3 import DadosB3

api = DadosB3()   # lê DADOS_B3_API_KEY

# "quem teve ROIC acima de 15% NO exercício de 2018"
por_exercicio = api.screener(roic_min=0.15, ano=2018)

# "o que eu poderia ter escolhido em 30/06/2019"
por_data = api.screener(roic_min=0.15, dl_ebitda_max=2, as_of="2019-06-30")
for e in por_data["empresas"]:
    print(e["ticker"], e["ano"], e["disponivel_em"], e["indicadores"]["roic"])

A primeira responde uma pergunta que ninguém podia responder em 2018. A segunda usa, para cada companhia, o exercício mais recente cujo balanço já tinha chegado à CVM na data — e cada linha traz disponivel_em, para você conferir. Os indicadores são frações: ROIC de 15% é 0.15. Nome de filtro inválido é recusado com erro, nunca ignorado; o cardápio completo está em /screener.

Guardar a resposta: o recibo

Na semana seguinte, quando a base for atualizada, a mesma pergunta pode devolver outra lista. Para citar a de hoje, peça um recibo:

r = api.screener(roic_min=0.15, as_of="2019-06-30", recibo=1)
print(r["recibo"]["url"])      # endereço permanente
print(r["recibo"]["sha256"])   # impressão digital do resultado

O recibo guarda a pergunta, a versão do dado e o resultado, e abre sem chave — quem recebe o link confere. A mesma pergunta na mesma versão devolve o mesmo recibo. Para conferir a impressão digital:

import hashlib, json, urllib.request
rec = json.load(urllib.request.urlopen(r["recibo"]["json"]))
corpo = json.dumps(rec["resultado"], sort_keys=True, separators=(",", ":"),
                   ensure_ascii=False).encode()
assert hashlib.sha256(corpo).hexdigest() == rec["sha256"]

O limite que isto não resolve

A data de corte tira o futuro dos números, não do universo: a base tem as companhias ativas hoje. Uma consulta a 2019 escolhe só entre quem sobreviveu até agora — o viés de sobrevivência. A resposta diz isso no campo limite_conhecido, e o tamanho do buraco está medido, companhia por companhia, em /saiu-da-bolsa. Por isso não publicamos backtest de carteira: com só 11% das que saíram reconstruíveis, o resultado enganaria.

Fontes: CVM (dados abertos, ODbL) e B3 (COTAHIST). Não afiliado à B3 nem à CVM. Não é recomendação de investimento.

Os números desta página são ao vivo. Versão do dado 2026-09-14-etfs · página gerada em 2026-09-23 00:30 UTC. Se isto não bater com o /saude, você está lendo uma cópia em cache.