profile

Wilson Freitas

Never Mind the SQL Queries, Here’s the rb3 API


Olá, Reader!

Bem-vindo(a) de volta à nossa jornada de exploração quantitativa!

Na Edição #1 reforçamos a ideia central: tudo começa com dados.

Hoje vamos um passo além: depois de ter consciência da importância dos dados, como estruturá-los para ganhar velocidade, escala e confiabilidade?

A resposta passa por dois pilares que o rb3 abraça profundamente: (1) um data lake local organizado e (2) formatos e estruturas modernas, como os datasets do Apache Arrow.

Antes de falar de Arrow ou de camadas de processamento, precisamos pisar firme no primeiro degrau: entender o ecossistema de aquisição do rb3.

Diferente de um pacote que já entrega um “banco fechado”, o rb3 é um construtor de acervos.

Você instala e está, literalmente, com prateleiras vazias — vai preenchendo conforme escolhe o que baixar.

Esse modelo deliberado dá autonomia (você só mantém o que importa) e transparência (sabe a origem e o momento de cada arquivo baixado), mas exige uma etapa inicial de orientação.

A primeira dúvida inevitável:

“Por onde eu começo? Baixo tudo? Pego só um arquivo famoso como COTAHIST?”

A armadilha aqui é tentar baixar volumes grandes sem ter clareza da estrutura.

O caminho mais inteligente é aprender a lingua franca do pacote: os templates.

O que são templates?

São descrições formais (nome, escopo, argumentos obrigatórios, schema) das fontes de dados tratadas pelo rb3.

Cada template corresponde a uma “fonte temática” da B3: cotações históricas, preços de ajuste de futuros, composição de índices, carteiras teóricas, taxas referenciais etc.

Eles respondem perguntas básicas antes de qualquer download:

  • Quais campos vou receber? (schema)
  • Quais parâmetros preciso informar? (ex.: refdate)
  • O dado varia por dia, por vigência, por índice? (granularidade)
  • Faz sentido baixar em lote ou de forma incremental?

Por que investir alguns minutos neles primeiro?

  1. Evita desperdício (não baixa arquivos que não precisa).
  2. Cria um mapa mental da cobertura funcional do pacote.
  3. Acelera a montagem de pipelines reprodutíveis (você já sabe quais argumentos parametrizar).
  4. Facilita futuras automações (cron, Make, scripts) porque você entende a unidade mínima de atualização.

Sequência sugerida para quem acabou de instalar:

  1. Listar todos os templates: visão panorâmica do “território”.
  2. Escolher 1 ou 2 de interesse imediato (ex.: preços de ajuste ou composição de índices).
  3. Inspecionar cada um com a função template_retrieve() (logo abaixo mostrarei como).
  4. Apenas depois disso, iniciar pequenos downloads controlados (alguns dias ou um mês) para validar entendimento.

Para enxergar esse “cardápio” de possibilidades, use:

list_templates() — ele retorna a tabela com todos os templates disponíveis e uma breve descrição estratégica de cada um.

Após identificar os templates disponíveis, a etapa seguinte é examinar a estrutura específica de um deles.

Consideremos o template b3-futures-settlement-prices, que contém os preços de ajuste dos contratos futuros, informação fundamental para cálculos de margem e valorização de posições.

Para obter a especificação formal deste template, utilizamos a função template_retrieve(), que fornece três componentes essenciais: a descrição formal, os argumentos necessários para download (parâmetros de entrada) e o schema de dados resultante (estrutura de saída).

A execução deste comando revela:

A saída estruturada acima apresenta três componentes essenciais: identificação do template, parâmetros necessários e schema de dados.

Note que o único argumento obrigatório é refdate (data de referência) – um detalhe crucial para construir chamadas válidas.

O schema, por sua vez, revela que receberemos sete campos tipados, incluindo informações de identificação do contrato (commodity e maturity_code) e valores de preços e variações.

Uma prática recomendada antes de investir em downloads extensivos é realizar um teste com escopo reduzido.

Selecione um período curto – uma única data ou uma semana – para validar o comportamento do template e confirmar que a estrutura dos dados atende às suas necessidades analíticas.

Esta etapa de validação economiza recursos e possibilita ajustes antes de criar grandes conjuntos de dados.

Com o entendimento do template estabelecido, podemos avançar para a aquisição efetiva dos dados através da função fetch_marketdata().

Para fins didáticos, demonstraremos com um mês completo.

A sintaxe segue um padrão consistente: o primeiro argumento identifica o template alvo, seguido dos parâmetros específicos requeridos pelo mesmo – neste caso, fornecemos uma sequência de datas através do argumento refdate:

Como observamos na saída acima, a função fetch_marketdata() executa um fluxo estruturado em duas fases principais: aquisição e processamento.

Inicialmente, ocorre o download dos arquivos solicitados para o período especificado – no exemplo, o mês de setembro de 2025 completo.

Após a aquisição bem-sucedida, inicia-se a fase de processamento com a construção de duas camadas estratégicas no data lake local:

1- Camada Input (primeira transformação):

  • Processa os dados brutos baixados, convertendo-os em estruturas tabulares tipadas
  • Mantém fidelidade ao formato original da fonte de dados
  • Armazena em formato Parquet seguindo uma estratégia de particionamento por data de referência (1 arquivo por dia)
  • Preserva o schema exato descrito pelo template

2- Camada Staging (otimização para consulta):

  • Consolida múltiplos arquivos em unidades maiores para acesso eficiente
  • Reorganiza as partições para otimizar o desempenho em consultas analíticas
  • Pode implementar transformações enriquecedoras como derivação de colunas
  • Resolve o problema de fragmentação – um template com dados diários por vários anos poderia acumular milhares de pequenos arquivos (ex.: 10 anos × ~250 dias úteis = 2.500 arquivos na camada input)

A arquitetura em duas camadas é um padrão estabelecido em engenharia de dados, balanceando fidelidade ao dado original com otimização para análise.

Na prática, a camada staging deve ser sua interface padrão para consultas, a menos que exista necessidade específica de acesso aos dados na forma mais granular.

Com o data lake estruturado, precisamos de um mecanismo eficiente para acessar esses dados sem nos preocuparmos com a complexidade subjacente das partições e formatos Parquet.

Aqui entra a função template_dataset() – a interface unificada que abstrai os detalhes de armazenamento e expõe os dados como objetos Arrow, permitindo consultas lazy com sintaxe dplyr.

Esta função estabelece a ponte entre o data lake físico e as operações analíticas, possibilitando que trabalhemos com datasets potencialmente grandes sem carregá-los integralmente na memória.

O primeiro argumento é o nome do template, assim como nas demais funções com prefixo template_, e o segundo argumento é a camada de dados (layer) a ser acessada.

O segundo argumento é opcional, de forma que se não for fornecido, a camada input é utilizada.

Essa função retorna um objeto FileSystemDataset do Arrow, esse objeto representa um dataset formado por arquivos parquet.

Observe que o dataset resulta em 22 arquivos – exatamente o número de dias úteis no mês

solicitado. Cada arquivo Parquet corresponde a uma data de referência válida, excluindo naturalmente os fins de semana.

A estrutura de campos espelha fielmente o schema documentado pelo template_retrieve(), mantendo a consistência entre metadados e dados.

Um detalhe crucial: diferente de um dataframe convencional, o FileSystemDataset do Arrow opera por referência, não carregando o conteúdo em memória até que seja expressamente requisitado – é como ter um cardápio digital completo de um restaurante sofisticado, onde você visualiza todos os pratos disponíveis com suas descrições detalhadas, mas só a cozinha prepara (e sua mesa recebe) exatamente o que você decide pedir.

Para acessar a camada staging, utilizamos a mesma função template_dataset(), porém especificando o valor “staging” no parâmetro layer.

Isso permite alternar entre camadas de dados sem modificar a interface de consulta, aproveitando as otimizações implementadas na camada staging:

A camada staging traz 2 diferenças com relação a camada input:

  1. O dataset dessa camada é composto por apenas 1 arquivo. Isso é feito para otimizar as consultas tornando-as mais rápidas.
  2. O dataset possui 8 colunas, a coluna symbol foi criada, pois representa o ticker do contrato futuro. Essa coluna é resultado da concatenação das colunas commodity e maturity_code.

Esse é o tipo de alteração ou enriquecimento que pode ser realizado na criação da camada staging.

Uma das características mais poderosas dos objetos FileSystemDataset do Arrow é sua integração com a gramática de manipulação do dplyr.

Esta combinação permite executar operações analíticas diretamente sobre dados armazenados em disco, sem a necessidade de carregá-los completamente na memória.

O processamento ocorre de forma “preguiçosa” (lazy), em que as operações são compiladas em uma árvore de execução otimizada e aplicadas apenas quando os resultados são efetivamente solicitados. Isso possibilita trabalhar com volumes de dados significativamente maiores do que a memória disponível, mantendo a sintaxe familiar do dplyr para filtragem (filter), seleção (select), transformação (mutate), agrupamento (group_by) e agregação (summarise).

Nossa primeira consulta revela a dimensão do conjunto: 15.594 registros no total.

Observe o padrão de operação que será recorrente em todas as consultas Arrow: primeiro definimos as operações desejadas (aqui, uma simples contagem) e finalizamos com collect() – o comando que materializa em memória apenas o resultado final, não o dataset inteiro.

Sem esse comando, o dplyr mantém as operações em estado de “intenção”, sem executá-las efetivamente.

Agora que conhecemos o volume, vamos explorar a diversidade de ativos neste universo.

A operação distinct() nos permite identificar quais commodities compõem o dataset:

Com 107 commodities diferentes, temos um panorama completo do mercado futuro brasileiro.

Vamos agora descobrir a quantidade de contratos negociados por dia por cada commodity.

Para isso vamos utilizar group_by() para agrupar os dados e summarize() fazer a contagem por dia e por commodity.

Para avançar em nossa análise, vamos examinar um instrumento específico.

Encadeando múltiplas operações dplyr, podemos extrair a série histórica completa de preços do contrato dólar futuro (WDO) com vencimento em outubro/2025, ordenada cronologicamente:

Resumindo nossa jornada

Nesta newsletter, percorremos o ciclo completo de uma arquitetura moderna de dados financeiros:

  1. Conhecer antes de adquirir: Exploramos o conceito de templates como interface formal para metadados, permitindo decisões informadas antes de qualquer download.
  2. Aquisição estruturada: Utilizamos a função fetch_marketdata() para obter dados da B3 com parametrização clara e reprodutível.
  3. Organização em camadas: Implementamos uma arquitetura de data lake em duas camadas (input e staging) que equilibra fidelidade aos dados originais com otimização para consultas.
  4. Acesso eficiente: Através do template_dataset() e objetos Arrow, conseguimos interagir com dados armazenados em disco usando a sintaxe familiar do dplyr, sem carregar tudo em memória.
  5. Análise escalonável: Demonstramos como realizar consultas progressivamente mais complexas que podem ser aplicadas tanto a pequenos conjuntos quanto a volumes de dados que excedem a capacidade da RAM.

O pacote rb3 não é apenas uma ferramenta para baixar dados financeiros – é uma infraestrutura completa que implementa práticas modernas de engenharia de dados adaptadas ao contexto do mercado brasileiro.

Ao dominar este fluxo, você conquista autonomia para construir seu próprio acervo de dados conforme suas necessidades analíticas específicas.

Na próxima edição exploraremos tópicos ainda mais avançados, incluindo técnicas de visualização e modelagem estatística aplicadas aos dados estruturados que preparamos.

Um abraço,
Wilson Freitas

Wilson Freitas

Escrevo semanalmente para lhe ajudar a utilizar linguagem de programação na análise de dados financeiros, estratégias de investimento quantitativas e as melhores práticas para manipulação e visualização de dados. Para que você possa ter conhecimento e ferramentas quantitativas e reproduzir análises quantitativas de forma independente.

Share this page