Pular para conteúdo

FRE Companhias Abertas — leitura

Leitura (← CVM) do Formulário de Referência das companhias abertas (fre_cia_aberta_AAAA.zip), publicado no portal de dados abertos da CVM.

Veja também: Referência da API · Uso · o IPE, o VLMO, o FCA e o CGVN.


⚠️ O maior dataset do portal — entregue em 4 fatias

O FRE tem 36 membros e ~131 mil linhas (o FCA, o segundo maior, tem 10 membros). Foi implementado em 4 PRs temáticos, cada um revisável e releasável sozinho:

fatia tema membros estado
1 índice + estrutura de capital 8
2 administração / pessoas (todos os membros com CPF) 7
3 diversidade (contagens agregadas) 11
4 remuneração + valores mobiliários + transações 10 esta

Com esta fatia o dataset está completo: 36 de 36 membros.


Os 8 membros da fatia 1 — índice + capital

reader membro cols linhas (2025) colunas de data
FreCiaAbertaReader índice 9 4.931 DT_REFER, DT_RECEB
FreCiaAbertaCapitalSocialReader capital_social 13 2.402 Data_Referencia, Data_Autorizacao_Aprovacao
FreCiaAbertaCapitalSocialClasseAcaoReader capital_social_classe_acao 8 292 Data_Referencia
FreCiaAbertaCapitalSocialTituloConversivelReader capital_social_titulo_conversivel 8 26 Data_Referencia
FreCiaAbertaDistribuicaoCapitalReader distribuicao_capital 15 700 Data_Referencia, Data_Ultima_Assembleia
FreCiaAbertaDistribuicaoCapitalClasseAcaoReader distribuicao_capital_classe_acao 9 170 Data_Referencia
FreCiaAbertaResponsavelReader responsavel 7 1.413 Data_Referencia
FreCiaAbertaMercadoEstrangeiroReader mercado_estrangeiro 17 11 Data_Referencia, Data_Emissao, Data_Inicio_Listagem

Os 7 membros da fatia 2 — administração / pessoas

reader membro cols linhas (2025) colunas de data
FreCiaAbertaAuditorReader auditor 18 1.097 Data_Referencia, Data_Inicio_Contratacao, Data_Fim_Contratacao, Data_Inicio_Prestacao_Servico
FreCiaAbertaAdministradorMembroConselhoFiscalReader administrador_membro_conselho_fiscal 21 8.988 Data_Referencia, Data_Eleicao, Data_Posse, Data_Inicio_Primeiro_Mandato, Data_Nascimento
FreCiaAbertaMembroComiteReader membro_comite 21 4.538 as mesmas 5 do anterior
FreCiaAbertaRelacaoFamiliarReader relacao_familiar 17 1.698 Data_Referencia
FreCiaAbertaRelacaoSubordinacaoReader relacao_subordinacao 17 9.102 Data_Referencia, Data_Inicio_Exercicio_Social, Data_Fim_Exercicio_Social
FreCiaAbertaPosicaoAcionariaReader posicao_acionaria 29 31.508 Data_Referencia, Data_Composicao_Capital_Social, Data_Ultima_Alteracao
FreCiaAbertaPosicaoAcionariaClasseAcaoReader posicao_acionaria_classe_acao 9 2.092 Data_Referencia

Os 11 membros da fatia 3 — diversidade

Todos com uma coluna de data (Data_Referencia, 100% ISO) e uma de CNPJ (CNPJ_Companhia).

reader membro cols linhas (2025) agrupa por
FreCiaAbertaAdministradorPcdReader administrador_PCD 10 3.495 Orgao_Administracao
FreCiaAbertaAdministradorDeclaracaoGeneroReader administrador_declaracao_genero 12 3.470 Orgao_Administracao
FreCiaAbertaAdministradorDeclaracaoRacaReader administrador_declaracao_raca 14 3.470 Orgao_Administracao
FreCiaAbertaEmpregadoPcdReader empregado_PCD 10 1.082 Codigo_Posicao + Posicao
FreCiaAbertaEmpregadoLocalDeclaracaoGeneroReader empregado_local_declaracao_genero 11 3.118 Local
FreCiaAbertaEmpregadoLocalDeclaracaoRacaReader empregado_local_declaracao_raca 13 3.117 Local
FreCiaAbertaEmpregadoLocalFaixaEtariaReader empregado_local_faixa_etaria 9 3.117 Local
FreCiaAbertaEmpregadoPosicaoDeclaracaoGeneroReader empregado_posicao_declaracao_genero 11 1.038 Posicao
FreCiaAbertaEmpregadoPosicaoDeclaracaoRacaReader empregado_posicao_declaracao_raca 13 1.038 Posicao
FreCiaAbertaEmpregadoPosicaoFaixaEtariaReader empregado_posicao_faixa_etaria 9 1.040 Posicao
FreCiaAbertaEmpregadoPosicaoLocalReader empregado_posicao_local 12 1.036 Posicao × região

Os 10 membros da fatia 4 — remuneração, valores mobiliários e transações

reader membro cols linhas (2025) colunas de data
FreCiaAbertaAcaoEntregueReader acao_entregue 14 1.304 Data_Referencia + as 2 do exercício social
FreCiaAbertaRemuneracaoAcaoReader remuneracao_acao 14 1.565 idem
FreCiaAbertaRemuneracaoMaximaMinimaMediaReader remuneracao_maxima_minima_media 14 3.307 idem
FreCiaAbertaRemuneracaoTotalOrgaoReader remuneracao_total_orgao 27 6.320 idem
FreCiaAbertaRemuneracaoVariavelReader remuneracao_variavel 18 3.851 idem
FreCiaAbertaOutroValorMobiliarioReader outro_valor_mobiliario 24 2.735 Data_Referencia, Data_Emissao, Data_Vencimento
FreCiaAbertaTitularValorMobiliarioReader titular_valor_mobiliario 9 163 Data_Referencia
FreCiaAbertaTituloExteriorReader titulo_exterior 21 122 Data_Referencia, Data_Emissao, Data_Vencimento
FreCiaAbertaParticipacaoSociedadeReader participacao_sociedade 21 6.511 Data_Referencia, Data_Valor_Mercado, Data_Valor_Contabil
FreCiaAbertaTransacaoParteRelacionadaReader transacao_parte_relacionada 22 11.238 Data_Referencia, Data_Transacao

⚠️ participacao_sociedade é o único membro da fatia com DUAS colunas de CNPJCNPJ_Companhia (quem entrega) e CNPJ (a investida). 792 dos 6.511 valores de CNPJ em 2025 são o placeholder literal 00000000000000, que é o que a CVM publica para subsidiária no exterior sem CNPJ brasileiro (AMERICANAS LUX, St. Marys Cement Inc.): nenhum malformado, nenhum branco. Voltam como publicados, e a coluna segue declarada porque o contrato exige ao menos um válido — a aresta (um arquivo só de placeholders levanta) é pinada por teste.

⚠️ transacao_parte_relacionada.Documento_Parte_Relacionada fica FORA de tuple_cnpj_cols apesar de chegar 100% vazia em 2025. A irmã Tipo_Pessoa tem domínio PF/PJ na META: a coluna guarda CPF ou CNPJ conforme a linha, como o Documento_Pessoa_Relacionada da fatia 2. Declará-la passaria em todo ano vazio e quebraria no primeiro com dado.

⚠️ Coluna vazia é propriedade do ANO, não do schema. Doze colunas de participacao_sociedade e três de outro_valor_mobiliario chegam 100% vazias em 2025 — entre elas Data_Valor_Mercado e Data_Valor_Contabil, que a META tipa date e portanto seguem colunas de data (tudo NaT). A asserção é sobre o dtype, nunca sobre isna().all(): branco vira NA sob str também.

⚠️ Duracao_Transacao é texto livre, não data, embora 879 das 11.238 linhas pareçam DD/MM/YYYY — a META a tipa varchar e a maioria dos valores é prosa ("indeterminado").

Particionado por ano — o date_ref seleciona o ano, e todos os readers do FRE baixam o mesmo arquivo (um path_raw escrito por um serve os outros).


⚠️ O índice não segue a convenção dos próprios satélites

índice os 35 satélites
CNPJ CNPJ_CIA CNPJ_Companhia
data de referência DT_REFER Data_Referencia
denominação DENOM_CIA Nome_Empresarial

O FCA faz igual; o CGVN não — o índice dele é CamelCase. Não há regra entre datasets do DOC, só medição por dataset. A divergência é pinada por teste nas duas direções, com o CGVN como contra-exemplo explícito.

⚠️ Ao longo dos 36 membros o FRE usa seis nomes de coluna de CNPJ — CNPJ, CNPJ_Auditor, CNPJ_CIA, CNPJ_Companhia, CNPJ_Emissor, CNPJ_Emissor_Pessoa_Relacionada. Cada contrato declara o seu; nada é herdado.


⚠️ Coluna de CNPJ é a que guarda CNPJ — o nome não é o teste

Quase todo membro declara só o CNPJ_Companhia, mas três declaram mais, e quatro colunas que parecem identificador ficam de fora. Cada caso foi decidido contando os valores reais de 2025:

membro declara fica de fora por quê
auditor CNPJ_Companhia, CNPJ_Auditor CPF_Auditor CPF é dado pessoal
relacao_familiar CNPJ_Companhia, CNPJ_Emissor, CNPJ_Emissor_Pessoa_Relacionada 2 colunas de CPF idem
relacao_subordinacao CNPJ_Companhia Documento_Pessoa_Relacionada guarda CNPJ e CPF (8.462 × 34)
posicao_acionaria CNPJ_Companhia as 3 CPF_CNPJ_* mistas por definição
participacao_sociedade CNPJ_Companhia, CNPJ o CNPJ da investida, 5.719 válidos + 792 placeholders
transacao_parte_relacionada CNPJ_Companhia Documento_Parte_Relacionada CPF ou CNPJ (Tipo_Pessoa é PF/PJ), mesmo 100% vazia em 2025

Documento_Pessoa_Relacionada é o caso que uma regra pelo nome erra: não diz nem CPF nem CNPJ, e guarda os dois (tipados pela coluna irmã Tipo_Pessoa_Relacionada, PJ/PF). Uma coluna mista declarada passaria no ano em que os valores fossem todos CNPJ e quebraria no primeiro CPF.

⚠️ O estilo de máscara não é uniforme nem dentro de um membro: em auditor, CNPJ_Companhia vem pontuado (00.000.000/0001-91) e CNPJ_Auditor, na mesma linha, vem em dígitos crus (49928567000111). Os dois são declarados — o validador normaliza a pontuação — e voltam como publicados.


Tipagem

Todas as colunas de data chegam 100% ISO; branco vira NaT. Quatro chegam inteiramente vazias em 2025 — auditor.Data_Fim_Contratacao (contrato em aberto não tem fim), posicao_acionaria.Data_Composicao_Capital_Social e as duas de participacao_sociedade (Data_Valor_Mercado, Data_Valor_Contabil) — e seguem sendo data por contrato: um ano vazio não rebaixa a coluna para texto.

Todo o restante é texto exato da fonte, incluindo Valor_Capital (monetário), Quantidade_* e Numero_* (contagens), Percentual_* e — na fatia 4, a mais monetária do dataset — Salario, Bonus_*, Montante_*, Preco_* e Saldo_*.

Nunca um float binário: um float64 perde a escala publicada de forma irreversível e silenciosa, e bin/check_dtypes.py barra o atalho. Converta para Decimal a jusante se precisar de aritmética.


⚠️ Dado pessoal (LGPD) — a fatia 2 concentra todo o CPF do FRE

Seis dos sete membros desta fatia carregam CPF, e vários carregam nome, profissão e data de nascimento de pessoa física. Tudo volta como publicado, sem mascarar e sem reformatar, mas:

  • nenhuma coluna de CPF entra em tuple_cnpj_cols — CPF não é identificador de empresa;
  • as fixtures de teste são só cabeçalho, sem uma linha de dado, para que nenhum CPF real entre no repositório.

posicao_acionaria_classe_acao é o único membro da fatia sem dado pessoal — identifica o acionista só pelo ID_Acionista.

⚠️ posicao_acionaria grafa CPF_CNPJ_Representante_legal com legal minúsculo, ao contrário das duas colunas irmãs. A grafia é preservada verbatim: "corrigir" faria a coluna não ser encontrada no arquivo real.

⚠️ Os membros de diversidade (*_declaracao_raca, *_declaracao_genero, *_PCD, *_faixa_etaria, fatia 3) não são dado pessoal sensível — são contagens agregadas por companhia (Quantidade_Preto, Quantidade_Feminino). O nome do membro sugere o contrário; medir as colunas desmentiu. Nenhum deles tem CPF, nome de pessoa, ou qualquer identificador além do CNPJ da companhia — pinado por teste sobre as colunas, não sobre o nome.


⚠️ Cinco pares de mesma largura na fatia 3 — o risco de copiar o irmão

Os membros de diversidade diferem entre si por uma coluna de agrupamento e pelos baldes que carregam. Cinco pares têm exatamente a mesma contagem de colunas e listas diferentes:

cols par
9 empregado_local_faixa_etaria × empregado_posicao_faixa_etaria
10 administrador_PCD × empregado_PCD
11 empregado_local_declaracao_genero × empregado_posicao_declaracao_genero
12 administrador_declaracao_genero × empregado_posicao_local
13 empregado_local_declaracao_raca × empregado_posicao_declaracao_raca

Um contract copiado do irmão bate na largura e só falha contra o header pinado — por isso cada um é gerado do seu próprio header, e os 5 pares são pinados por teste. ⚠️ administrador_PCD e empregado_PCD têm 10 colunas cada e compartilham 8 — divergem em exatamente 2 cada: o primeiro agrupa por Orgao_Administracao e tem Nao_Aplicavel; o segundo agrupa por Codigo_Posicao + Posicao e não tem.

⚠️ Em administrador_PCD as colunas Quantidade_* chegam parcialmente vazias (~1/5 das linhas em 2025). Vazio não é zero — é declaração ausente, e volta vazio.

⚠️ Mais quatro pares de mesma largura na fatia 4 — e três deles com prefixo idêntico

cols par o que compartilham
14 acao_entregue × remuneracao_acao as 10 primeiras colunas
14 acao_entregue × remuneracao_maxima_minima_media as 8 primeiras
14 remuneracao_acao × remuneracao_maxima_minima_media as 8 primeiras
21 titulo_exterior × participacao_sociedade quase nada — só a largura

O trio de 14 colunas é a colisão mais apertada do dataset: compartilha largura, prefixo e todo teste de entrada gerada — só o header pinado discorda. Nove pares no total entre as fatias 3 e 4.


Uso

from datetime import date
from pathlib import Path

from filings_cvm.ingestion.cia_aberta import (
    FreCiaAbertaCapitalSocialReader,
    FreCiaAbertaPosicaoAcionariaReader,
    FreCiaAbertaReader,
    FreCiaAbertaRemuneracaoTotalOrgaoReader,
)

# O índice dos formulários entregues no ano:
df_indice = FreCiaAbertaReader(date_ref=date(2025, 6, 15)).read()

# O capital social, guardando o .zip cru (serve às outras fatias também):
df_capital = FreCiaAbertaCapitalSocialReader(
    date_ref=date(2025, 6, 15),
    path_raw=Path("/data/bronze/cvm/fre"),
).read()

# A base acionária — o maior membro da fatia 2 (31.508 linhas em 2025):
df_acionistas = FreCiaAbertaPosicaoAcionariaReader(date_ref=date(2025, 6, 15)).read()

# A remuneração por órgão — o membro mais largo da fatia 4 (27 colunas):
df_remuneracao = FreCiaAbertaRemuneracaoTotalOrgaoReader(date_ref=date(2025, 6, 15)).read()

# Aritmética a jusante — Decimal, nunca float:
from decimal import Decimal

total = sum(Decimal(v) for v in df_capital["Valor_Capital"] if v)

O frame devolvido carrega, além das colunas da fonte, as seis colunas de proveniência.


META

A especificação da CVM sai em MetaFreCiaAbertaReader (o 42º Meta reader) — veja META.

⚠️ A URL é a forma padrão meta_fre_cia_aberta.zip; as outras 3 candidatas dão 404 — inclusive fre_cia_aberta.zip sem prefixo, que é justamente a forma correta do FCA.

⚠️ O arquivo traz 50 membros para 36 membros de dados, e a nomenclatura interna é mista: a maioria tem o prefixo meta_fre_cia_aberta*, mas ao menos um (fre_cia_aberta_empregado_local_faixa_etaria.txt) não tem. As seções a mais e o prefixo inconsistente voltam como publicados — o parser rotula cada seção pelo nome do membro que encontra, sem normalizar.