OData¶
Diversas APIs disponíveis no portal de dados abertos do Banco Central implementam o protocolo OData, são centenas de APIs.
O python-bcb tem algumas classes que implementam APIs OData:
bcb.odata.api.Expectativas: Expectativas de mercado para os indicadores macroeconômicos da Pesquisa Focusbcb.odata.api.PTAX: Dólar comercialbcb.odata.api.TaxaJuros: Taxas de juros de operações de crédito por instituição financeirabcb.odata.api.IFDATA: Dados selecionados de instituições financeirasbcb.odata.api.MercadoImobiliario: Informações do Mercado Imobiliáriobcb.odata.api.SPI: Estatísticas do SPI (Sistema de Pagamentos Instantâneos)Veja todas as APIs implementadas em APIs OData.
Para uma explicação prática das consultas ao IFData, veja IFData.
Estas APIs foram implementadas em classes por serem as mais populares, entretanto,
qualquer API OData pode ser acessada através da classe bcb.odata.api.ODataAPI que abstrai o acesso
a API a partir da URL da API que está disponível no portal de dados abertos
do Banco Central.
Veja mais detalhes em Classe ODataAPI.
Timeout por chamada¶
As APIs OData também aceitam timeout para serviços lentos ou consultas com
muitos registros. O timeout informado no construtor é usado na descoberta do
serviço, no carregamento dos metadados e como padrão das queries criadas a
partir dessa API. Métodos de execução podem receber outro valor para sobrescrever
o padrão apenas naquela chamada.
from bcb import Expectativas
em = Expectativas(timeout=120)
ep = em.get_endpoint("ExpectativasMercadoAnuais")
df = ep.get(timeout=60)
raw = ep.query().limit(1000).text(timeout=60)
data = ep.query().limit(1000).collect(timeout=60)
O mesmo parâmetro está disponível nas versões assíncronas async_get,
async_text e async_collect.
Segue um exemplo de como acessar a API do PIX.
In [1]: from bcb import SPI
In [2]: pix = SPI()
É necessário importar e criar um objeto da classe que implementa a API, neste caso a classe SPI.
Tendo o objeto, executar o método describe para visualizar os endpoints disponíveis na API e suas propriedades. Para obter apenas a listagem curta dos nomes, use describe(full=False).
In [3]: pix.describe()
EntitySets:
EntitySet (Endpoint): PixLiquidadosAtual
EntityType: br.gov.bcb.olinda.servico.SPI.PixLiquidadosAtual
Properties: Data<datetime>, Quantidade<int>, CanalPrimario<int>, CanalSecundario<int>, Total<float>, Media<float>
EntitySet (Endpoint): PixRemuneracaoContaPI
EntityType: br.gov.bcb.olinda.servico.SPI.PixRemuneracaoContaPI
Properties: DataBase<datetime>, BaseRemuneracaoIF<float>, ValorRemuneradoIF<float>, BaseRemuneracaoTotal<float>, ValorRemuneradoTotal<float>, SelicAnual<float>
EntitySet (Endpoint): PixInterrupcaoSPI
EntityType: br.gov.bcb.olinda.servico.SPI.PixInterrupcaoSPI
Properties: DataHoraInicioInt<str>, DataHoraTerminoInt<str>, Interrupcao<str>
EntitySet (Endpoint): PixLiquidadosIntradia
EntityType: br.gov.bcb.olinda.servico.SPI.PixLiquidadosIntradia
Properties: Horario<str>, QuantidadeMedia<int>, TotalMedio<float>
EntitySet (Endpoint): PixDisponibilidadeSPI
EntityType: br.gov.bcb.olinda.servico.SPI.PixDisponibilidadeSPI
Properties: DataBase<datetime>, Indice<float>, MinimoNormativo<float>
Como vemos, a API do PIX tem 4 endpoints (EntitySets).
Para restringir a saída a um endpoint, execute o método describe passando como argumento
o nome do endpoint.
In [4]: pix.describe("PixLiquidadosAtual")
EntitySet (Endpoint): PixLiquidadosAtual
EntityType: br.gov.bcb.olinda.servico.SPI.PixLiquidadosAtual
Properties: Data<datetime>, Quantidade<int>, CanalPrimario<int>, CanalSecundario<int>, Total<float>, Media<float>
Vemos que o endpoint PixLiquidadosAtual retorna 4 propriedades:
Data<datetime>: data das operaçõesQuantidade<int>: quantidade de operações realizadas na dataTotal<float>: financeiro das operações realizdas na dataMedia<float>: média das operações realizadas na data
As propriedades são atributos de objetos da classe bcb.odata.api.Endpoint, retornados pelo método
get_endpoint.
In [5]: ep = pix.get_endpoint("PixLiquidadosAtual")
In [6]: ep.Data
Out[6]: <Property Data<datetime>>
In [7]: ep.Media
Out[7]: <Property Media<float>>
Para acessar os dados deste endpoint é necessário executar uma query nesse objeto.
In [8]: ep.query().limit(5).collect()
Out[8]:
Data Quantidade CanalPrimario CanalSecundario Total Media
0 2025-05-15 203155891 202530064 625827 1.051084e+08 517.38
1 2024-04-19 163588000 163124269 463731 7.911428e+07 483.62
2 2024-05-24 156097661 155912971 184690 6.866069e+07 439.86
3 2024-02-10 140720681 140509596 211085 2.550603e+07 181.25
4 2025-11-18 200922887 200484305 438582 9.788716e+07 487.19
Ao realizar a query no endpoint limitamos a consulta a retornar 10 elementos, apenas para visualizar os dados
da consulta.
A consulta retorna um DataFrame pandas onde as colunas são as propriedades do endpoint.
Veremos abaixo, com mais detalhes, como realizar consultas nas APIs e quais os tipos de endpoints disponíveis
(EntitySets e FunctionImports).
Como Realizar Consultas em APIs OData¶
As consultas são realizadas através do método query da classe bcb.odata.api.Endpoint.
Este método retorna um objeto bcb.odata.framework.ODataQuery que abstrai a consulta e permite executar
algumas firulas como: filtros e ordenação.
A classe bcb.odata.framework.ODataQuery tem os seguintes métodos:
bcb.odata.framework.ODataQuery.filter(): define filtros na consulta, com uma clausulawhereno SQL.bcb.odata.framework.ODataQuery.select(): seleciona as propriedades retornadas pela consulta.bcb.odata.framework.ODataQuery.orderby(): ordena a consulta pelas propriedades.bcb.odata.framework.ODataQuery.limit(): limita os resultados anregistros.bcb.odata.framework.ODataQuery.parameters(): endpoints do tipoFunctionImportspossuem parâmetros que são definidos por este método.bcb.odata.framework.ODataQuery.collect(): o framework tem uma abordagem lazy, dessa forma, este método realiza a consulta trazendo os dados e retornando um DataFrame.bcb.odata.framework.ODataQuery.text(): este método retorna o texto (formato json) retornado pela API.bcb.odata.framework.ODataQuery.show(): imprime a estrutura da consulta.
Os métodos filter, select, orderby, limit e parameters retornam o objeto
bcb.odata.framework.ODataQuery, e isso permite a realização de chamadas aninhadas que compõem a consulta.
Por exemplo, na consulta do PIX, as datas não estão ordenadas, temos dias de 2021, 2022 e 2023 nos 10 registros
retornados.
Vamos ordernar pela propriedade Data de forma decrescente.
In [9]: ep.query().orderby(ep.Data.desc()).limit(5).collect()
Out[9]:
Data Quantidade CanalPrimario CanalSecundario Total Media
0 2026-06-14 175592940 175171310 421630 2.242838e+07 127.73
1 2026-06-13 235796306 235292263 504043 3.499939e+07 148.43
2 2026-06-12 254528967 253751905 777062 1.209410e+08 475.16
3 2026-06-11 239210494 238471195 739299 1.149050e+08 480.35
4 2026-06-10 258814871 257440361 1374510 1.546446e+08 597.51
Veja que a consulta retorna as datas mais recentes primeiro.
Gosto de estruturar as consultas como uma query SQL. Sigamos com um exemplo:
select Data, Media
from PIX
where Data >= "2023-01-01"
order by Media desc
limit 10
Quero obter os 10 dias em 2023 que apresentam as maiores médias transacionadas no PIX.
Para executar essa query utilizo o método select passando as propriedades Data e Media,
encadeio o método filter filtrando a propriedade Data maiores que 2023-01-01, e note
que aqui utilizo um objeto date; objetos datetime também são aceitos. Na descrição do endpoint PixLiquidadosAtual,
a propriedade Data aparece como datetime porque representa um campo OData Edm.Date.
Sigo com o método orderby passando a propriedade média e indicando que a ordenação é decrescente e concluo com
o método limit para obter os 10 primeiros registros.
Na última linha executo o método collect que executa a consulta e retorna um DataFrame com os resultados.
In [10]: from datetime import date
In [11]: (ep.query()
....: .select(ep.Data, ep.Media)
....: .filter(ep.Data >= date(2023, 1, 1))
....: .orderby(ep.Media.desc())
....: .limit(5)
....: .collect())
....:
Out[11]:
Data Media
0 2025-06-30 745.06
1 2026-02-18 712.83
2 2025-12-15 707.89
3 2026-03-30 701.97
4 2026-05-04 689.97
Visualizando a Consulta¶
Algumas consultas podem ficar bastante complicadas, dependendo da quantidade de elementos que compõem a consulta.
Para ajudar na construção e na depuração da query, criamos o método show imprime a query na tela,
mas não a executa.
In [12]: (ep.query()
....: .select(ep.Data, ep.Media)
....: .filter(ep.Data >= date(2023, 1, 1))
....: .orderby(ep.Media.desc())
....: .limit(5)
....: .show())
....:
URL:
https://olinda.bcb.gov.br/olinda/servico/SPI/versao/v1/odata/PixLiquidadosAtual
Query Parameters:
$format = json
$filter = Data ge 2023-01-01
$orderby = Media desc
$select = Data,Media
$top = 5
Return: Data<datetime>, Quantidade<int>, CanalPrimario<int>, CanalSecundario<int>, Total<float>, Media<float>
Filtrando Dados¶
Os filtros são criados com o método filter e aplicados às propriedades do endpoint, por isso é necessário
conhecê-lo, o que deve ser feito com o método describe.
In [13]: from bcb import Expectativas
In [14]: em = Expectativas()
In [15]: em.describe('ExpectativasMercadoTop5Anuais')
EntitySet (Endpoint): ExpectativasMercadoTop5Anuais
EntityType: br.gov.bcb.olinda.servico.Expectativas.ExpectativasMercadoTop5Anual
Properties: Indicador<str>, Data<str>, DataReferencia<str>, tipoCalculo<str>, Media<float>, Mediana<float>, DesvioPadrao<float>, Minimo<float>, Maximo<float>
O endpoint ExpectativasMercadoTop5Anuais da API de Expectativas possui a propriedade Indicador, do tipo
str.
Vamos filtrar os dados com a propriedade Indicador igual a IPCA.
Como o tipo dessa propriedade é str, utilizamos uma string no filtro e o operador ==, que representa igualdade.
In [16]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')
In [17]: query = ep.query().filter(ep.Indicador == 'IPCA').limit(5)
In [18]: query.show()
URL:
https://olinda.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata/ExpectativasMercadoTop5Anuais
Query Parameters:
$format = json
$filter = Indicador eq 'IPCA'
$top = 5
Return: Indicador<str>, Data<str>, DataReferencia<str>, tipoCalculo<str>, Media<float>, Mediana<float>, DesvioPadrao<float>, Minimo<float>, Maximo<float>
O método show apresenta os parâmetros da query formatados, com isso podemos visualizar como os parâmetros da
consulta serão enviados à API.
Note que o operador == foi convertido para eq.
Podemos utilizar todos os operadores de comparação nos filtros.
In [19]: query.collect()
Out[19]:
Indicador Data DataReferencia ... DesvioPadrao Minimo Maximo
0 IPCA 2018-01-18 2019 ... 0.13 4.00 4.25
1 IPCA 2018-01-18 2020 ... 0.00 4.00 4.00
2 IPCA 2018-01-18 2021 ... 0.11 3.75 4.00
3 IPCA 2018-01-18 2018 ... 0.26 3.27 3.95
4 IPCA 2018-01-19 2019 ... 0.25 3.70 4.30
[5 rows x 9 columns]
Mais filtros podem ser adicionados ao método filter, e também podemos aninhar chamadas do método filter.
In [20]: query = (ep.query()
....: .filter(ep.Indicador == 'IPCA', ep.DataReferencia == 2023)
....: .filter(ep.Data >= date(2022, 1, 1))
....: .filter(ep.tipoCalculo == 'C')
....: .limit(5))
....:
In [21]: query.show()
URL:
https://olinda.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata/ExpectativasMercadoTop5Anuais
Query Parameters:
$format = json
$filter = Indicador eq 'IPCA' and DataReferencia eq '2023' and Data ge '2022-01-01' and tipoCalculo eq 'C'
$top = 5
Return: Indicador<str>, Data<str>, DataReferencia<str>, tipoCalculo<str>, Media<float>, Mediana<float>, DesvioPadrao<float>, Minimo<float>, Maximo<float>
In [22]: query.collect()
Out[22]:
Indicador Data DataReferencia ... DesvioPadrao Minimo Maximo
0 IPCA 2022-01-03 2023 ... 0.4385 2.5 3.8000
1 IPCA 2022-01-04 2023 ... 0.4385 2.5 3.8000
2 IPCA 2022-01-05 2023 ... 0.4385 2.5 3.8000
3 IPCA 2022-01-06 2023 ... 0.4385 2.5 3.8000
4 IPCA 2022-01-07 2023 ... 0.5711 2.5 4.2693
[5 rows x 9 columns]
Todos os filtros estão no atributo $filter da consulta e são concatenados com o operador booleano and.
Para combinar condições com or, use o operador | entre filtros. Use
parênteses em cada comparação, pois | tem precedência diferente dos
operadores de comparação do Python.
In [23]: query = (ep.query()
....: .filter((ep.Indicador == 'IPCA') | (ep.Indicador == 'IGP-M'))
....: .filter(ep.DataReferencia == 2023)
....: .limit(5))
....:
In [24]: query.show()
URL:
https://olinda.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata/ExpectativasMercadoTop5Anuais
Query Parameters:
$format = json
$filter = (Indicador eq 'IPCA' or Indicador eq 'IGP-M') and DataReferencia eq '2023'
$top = 5
Return: Indicador<str>, Data<str>, DataReferencia<str>, tipoCalculo<str>, Media<float>, Mediana<float>, DesvioPadrao<float>, Minimo<float>, Maximo<float>
Também é possível combinar filtros explicitamente com &. O operador nativo
or do Python não deve ser usado, porque ele avalia objetos em contexto
booleano em vez de construir uma expressão OData.
É necessário conhecer o tipo da propriedade para saber como passar o objeto para a consulta.
Os tipos de propriedade podem ser: str, float, int e datetime.
Para propriedades OData Edm.Date, passe um objeto datetime.date ou datetime.datetime para o método filter; strings de data não são convertidas automaticamente pelo construtor de filtros.
In [25]: ep = pix.get_endpoint("PixLiquidadosAtual")
In [26]: (ep.query()
....: .filter(ep.Data >= date(2023, 1, 1))
....: .limit(5)
....: .show())
....:
URL:
https://olinda.bcb.gov.br/olinda/servico/SPI/versao/v1/odata/PixLiquidadosAtual
Query Parameters:
$format = json
$filter = Data ge 2023-01-01
$top = 5
Return: Data<datetime>, Quantidade<int>, CanalPrimario<int>, CanalSecundario<int>, Total<float>, Media<float>
O objeto date ou datetime é formatado como data na consulta; note que não há aspas na definição da data no filtro.
Ordenando os Dados¶
A ordenação é definida no método orderby passando um objeto da classe
bcb.odata.framework.ODataPropertyOrderBy que é obtida dos métodos asc e desc da propriedade.
In [27]: ep = pix.get_endpoint("PixLiquidadosAtual")
In [28]: ep.Data.asc()
Out[28]: <Data asc>
Este objeto é passado para o método orderby na tripa na qual a query é construída.
In [29]: query = (ep.query()
....: .orderby(ep.Data.asc())
....: .limit(5))
....:
In [30]: query.show()
URL:
https://olinda.bcb.gov.br/olinda/servico/SPI/versao/v1/odata/PixLiquidadosAtual
Query Parameters:
$format = json
$orderby = Data asc
$top = 5
Return: Data<datetime>, Quantidade<int>, CanalPrimario<int>, CanalSecundario<int>, Total<float>, Media<float>
In [31]: query.collect()
Out[31]:
Data Quantidade CanalPrimario CanalSecundario Total Media
0 2020-11-03 2345 None None 210.24 89.65
1 2020-11-04 2629 None None 336.37 127.94
2 2020-11-05 16669 None None 2685.84 161.13
3 2020-11-06 57936 None None 21133.81 364.78
4 2020-11-07 11089 None None 2333.89 210.47
O método orderby pode receber diversas propriedades para a definição da ordenação.
In [32]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')
In [33]: query = (ep.query()
....: .orderby(ep.Data.desc(), ep.Indicador.desc())
....: .limit(5))
....:
In [34]: query.show()
URL:
https://olinda.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata/ExpectativasMercadoTop5Anuais
Query Parameters:
$format = json
$orderby = Data desc,Indicador desc
$top = 5
Return: Indicador<str>, Data<str>, DataReferencia<str>, tipoCalculo<str>, Media<float>, Mediana<float>, DesvioPadrao<float>, Minimo<float>, Maximo<float>
Também podem ser realizadas chamadas aninhadas do método orderby.
In [35]: query = (ep.query()
....: .orderby(ep.Data.desc())
....: .orderby(ep.Indicador.desc())
....: .limit(5))
....:
In [36]: query.show()
URL:
https://olinda.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata/ExpectativasMercadoTop5Anuais
Query Parameters:
$format = json
$orderby = Data desc,Indicador desc
$top = 5
Return: Indicador<str>, Data<str>, DataReferencia<str>, tipoCalculo<str>, Media<float>, Mediana<float>, DesvioPadrao<float>, Minimo<float>, Maximo<float>
Vejam que a consulta é exatamente a mesma.
Selecionando as Propriedades¶
O médoto select funciona de forma muito semelhante ao select de uma query SQL.
In [37]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')
In [38]: (ep.query()
....: .select(ep.Indicador, ep.Data, ep.DataReferencia, ep.tipoCalculo, ep.Media)
....: .orderby(ep.Data.desc())
....: .limit(5)
....: .collect())
....:
Out[38]:
Indicador Data DataReferencia tipoCalculo Media
0 Câmbio 2026-06-05 2026 M 5.0400
1 Câmbio 2026-06-05 2027 M 5.0090
2 Câmbio 2026-06-05 2028 M 5.0750
3 Câmbio 2026-06-05 2029 M 5.1753
4 Câmbio 2026-06-05 2030 M 5.2878
Selecionar as colunas é importante para reduzir o volume de dados trafegado, pois a API do BCB não tem um bom desempenho, logo, essas configurações aceleram as consultas.
Método limit¶
O método limit define a quantidade de linhas que será retornada pela consulta.
Esse método é importante para investigar as consultas na API de forma rápida.
In [39]: ep = pix.get_endpoint("PixLiquidadosAtual")
In [40]: (ep.query()
....: .filter(ep.Data >= date(2023, 1, 1))
....: .limit(5)
....: .collect())
....:
Out[40]:
Data Quantidade CanalPrimario CanalSecundario Total Media
0 2025-05-15 203155891 202530064 625827 1.051084e+08 517.38
1 2024-04-19 163588000 163124269 463731 7.911428e+07 483.62
2 2024-05-24 156097661 155912971 184690 6.866069e+07 439.86
3 2024-02-10 140720681 140509596 211085 2.550603e+07 181.25
4 2025-11-18 200922887 200484305 438582 9.788716e+07 487.19
Tipos de endpoints¶
Como foi visto anteriormente, a API do PIX (SPI) possui 4 EntitySets e estes são os endpoints dessa API.
Entretanto, há APIs que têm um outro tipo de endpoint, os FunctionImports.
A API do PTAX, por exemplo
In [41]: from bcb import PTAX
In [42]: ptax = PTAX()
In [43]: ptax.describe()
EntitySets:
EntitySet (Endpoint): Moedas
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoMoeda
Properties: simbolo<str>, nomeFormatado<str>, tipoMoeda<str>
FunctionImports:
Function: CotacaoMoedaPeriodoFechamento
Parameters: codigoMoeda <str>, dataInicialCotacao <str>, dataFinalCotacao <str>
EntitySet: _CotacaoMoedaPeriodoFechamento
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoDolarAberturaOuIntermediario
Properties: cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>, tipoBoletim <str>
Function: CotacaoMoedaAberturaOuIntermediario
Parameters: codigoMoeda <str>, dataCotacao <str>
EntitySet: _CotacaoMoedaAberturaOuIntermediario
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoDolarAberturaOuIntermediario
Properties: cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>, tipoBoletim <str>
Function: CotacaoMoedaDia
Parameters: moeda <str>, dataCotacao <str>
EntitySet: _CotacaoMoedaDia
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoMoeda
Properties: paridadeCompra <float>, paridadeVenda <float>, cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>, tipoBoletim <str>
Function: CotacaoMoedaPeriodo
Parameters: moeda <str>, dataInicial <str>, dataFinalCotacao <str>
EntitySet: _CotacaoMoedaPeriodo
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoMoeda
Properties: paridadeCompra <float>, paridadeVenda <float>, cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>, tipoBoletim <str>
Function: CotacaoDolarDia
Parameters: dataCotacao <str>
EntitySet: _CotacaoDolarDia
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoDolar
Properties: cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>
Function: CotacaoDolarPeriodo
Parameters: dataInicial <str>, dataFinalCotacao <str>
EntitySet: _CotacaoDolarPeriodo
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoDolar
Properties: cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>
Esta API tem 1 EntitySet e 6 FunctionImports.
Assim como os EntitySets, os FunctionImports também retornam dados em formato tabular.
A principal diferença entre os EntitySets e FunctionImports é que estes possuem parâmetros, como uma função, e
estes parâmetros devem ser definidos para que a consulta seja realizada.
Vamos ver o endpoint CotacaoMoedaPeriodo
In [44]: ptax.describe("CotacaoMoedaPeriodo")
Function: CotacaoMoedaPeriodo
Parameters: moeda <str>, dataInicial <str>, dataFinalCotacao <str>
EntitySet: _CotacaoMoedaPeriodo
EntityType: br.gov.bcb.olinda.servico.PTAX.TipoCotacaoMoeda
Properties: paridadeCompra <float>, paridadeVenda <float>, cotacaoCompra <float>, cotacaoVenda <float>, dataHoraCotacao <str>, tipoBoletim <str>
Este endpoint tem 3 parâmetros:
codigoMoeda <str>
dataInicial <str>
dataFinalCotacao <str>
Para conhecer como os parâmetros devem ser definidos é necessário ler a documentação da API.
Eventualmente a definição dos parâmetros não é óbvia.
Os parâmetros de data da PTAX aceitam strings ISO (YYYY-MM-DD),
datetime.date, datetime.datetime e pandas.Timestamp. Strings já no
formato PTAX também continuam aceitas. A biblioteca converte os valores
generalizados para o formato aceito pelo serviço PTAX: M/D/YYYY
(mês/dia/ano, sem zero à esquerda).
Vamos realizar uma consulta para obter as cotações de dólar americano entre 2022-01-01 e 2022-01-05.
In [45]: ep = ptax.get_endpoint("CotacaoMoedaPeriodo")
In [46]: (ep.query()
....: .parameters(moeda="USD",
....: dataInicial="2022-01-01",
....: dataFinalCotacao="2022-01-05")
....: .collect())
....:
Out[46]:
paridadeCompra paridadeVenda ... dataHoraCotacao tipoBoletim
0 1.0 1.0 ... 2022-01-03 10:04:22.186 Abertura
1 1.0 1.0 ... 2022-01-03 11:11:42.883 Intermediário
2 1.0 1.0 ... 2022-01-03 12:09:19.760 Intermediário
3 1.0 1.0 ... 2022-01-03 13:11:50.353 Intermediário
4 1.0 1.0 ... 2022-01-03 13:11:50.357 Fechamento
5 1.0 1.0 ... 2022-01-04 10:05:22.015 Abertura
6 1.0 1.0 ... 2022-01-04 11:05:20.148 Intermediário
7 1.0 1.0 ... 2022-01-04 12:10:19.466 Intermediário
8 1.0 1.0 ... 2022-01-04 13:08:59.118 Intermediário
9 1.0 1.0 ... 2022-01-04 13:08:59.123 Fechamento
10 1.0 1.0 ... 2022-01-05 10:06:19.404 Abertura
11 1.0 1.0 ... 2022-01-05 11:06:19.009 Intermediário
12 1.0 1.0 ... 2022-01-05 12:03:19.428 Intermediário
13 1.0 1.0 ... 2022-01-05 13:07:53.088 Intermediário
14 1.0 1.0 ... 2022-01-05 13:07:53.094 Fechamento
[15 rows x 6 columns]
Note que a primeira data é 2022-01-03, pois os primeiros dias do ano não são úteis.
Podemos aplicar filtros nessa consulta utilizando o método filter, da mesma forma que realizamos na consulta ao
EntitySet.
In [47]: (ep.query()
....: .parameters(moeda="USD",
....: dataInicial="2022-01-01",
....: dataFinalCotacao="2022-01-05")
....: .filter(ep.tipoBoletim == "Fechamento")
....: .collect())
....:
Out[47]:
paridadeCompra paridadeVenda ... dataHoraCotacao tipoBoletim
0 1.0 1.0 ... 2022-01-03 13:11:50.357 Fechamento
1 1.0 1.0 ... 2022-01-04 13:08:59.123 Fechamento
2 1.0 1.0 ... 2022-01-05 13:07:53.094 Fechamento
[3 rows x 6 columns]
Obtendo o Texto da API¶
Uma alternativa ao DataFrame retornado pela consulta, via o método collect, é obter o texto, em formato JSON
(padrão) ou XML, retornado pela consulta.
O método collect faz o parsing do texto retornado na consulta e cria um DataFrame, o método text retorna
esse texto bruto.
Isso é útil para fazer o armazenamento de dados da API para a construção de bancos de dados ou data lakes.
Para obter o conteúdo bruto, basta executar o método text ao invés do collect, ao fim da cadeia da consulta.
In [48]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')
In [49]: (ep.query()
....: .select(ep.Indicador, ep.Data, ep.DataReferencia, ep.tipoCalculo, ep.Media)
....: .orderby(ep.Data.desc())
....: .limit(5)
....: .text())
....:
Out[49]: '{"@odata.context":"https://was-p.bcnet.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata$metadata#ExpectativasMercadoTop5Anuais(Indicador,Data,DataReferencia,tipoCalculo,Media)","value":[{"Indicador":"Câmbio","Data":"2026-06-05","DataReferencia":"2026","tipoCalculo":"M","Media":5.0400},{"Indicador":"Câmbio","Data":"2026-06-05","DataReferencia":"2027","tipoCalculo":"M","Media":5.0090},{"Indicador":"Câmbio","Data":"2026-06-05","DataReferencia":"2028","tipoCalculo":"M","Media":5.0750},{"Indicador":"Câmbio","Data":"2026-06-05","DataReferencia":"2029","tipoCalculo":"M","Media":5.1753},{"Indicador":"Câmbio","Data":"2026-06-05","DataReferencia":"2030","tipoCalculo":"M","Media":5.2878}]}'
O texto retornado está no formato JSON.
Contudo, as APIs OData também retornam conteúdo em XML.
Para isso incluímos o método format na cadeia da consulta e passamos como parâmetro o tipo desejado.
In [50]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')
In [51]: (ep.query()
....: .select(ep.Indicador, ep.Data, ep.DataReferencia, ep.tipoCalculo, ep.Media)
....: .orderby(ep.Data.desc())
....: .format("xml")
....: .limit(5)
....: .text())
....:
Out[51]: '<?xml version=\'1.0\' encoding=\'UTF-8\'?><a:feed xmlns:a="http://www.w3.org/2005/Atom" xmlns:m="http://docs.oasis-open.org/odata/ns/metadata" xmlns:d="http://docs.oasis-open.org/odata/ns/data" m:context="https://was-p.bcnet.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata$metadata#ExpectativasMercadoTop5Anuais(Indicador,Data,DataReferencia,tipoCalculo,Media)"><a:entry><a:title/><a:summary/><a:updated>2026-06-15T07:22:25Z</a:updated><a:author><a:name/></a:author><a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#br.gov.bcb.olinda.servico.Expectativas.ExpectativasMercadoTop5Anual"/><a:content type="application/xml"><m:properties><d:Indicador>Câmbio</d:Indicador><d:Data>2026-06-05</d:Data><d:DataReferencia>2026</d:DataReferencia><d:tipoCalculo>M</d:tipoCalculo><d:Media m:type="Decimal">5.0400</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2026-06-15T07:22:25Z</a:updated><a:author><a:name/></a:author><a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#br.gov.bcb.olinda.servico.Expectativas.ExpectativasMercadoTop5Anual"/><a:content type="application/xml"><m:properties><d:Indicador>Câmbio</d:Indicador><d:Data>2026-06-05</d:Data><d:DataReferencia>2027</d:DataReferencia><d:tipoCalculo>M</d:tipoCalculo><d:Media m:type="Decimal">5.0090</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2026-06-15T07:22:25Z</a:updated><a:author><a:name/></a:author><a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#br.gov.bcb.olinda.servico.Expectativas.ExpectativasMercadoTop5Anual"/><a:content type="application/xml"><m:properties><d:Indicador>Câmbio</d:Indicador><d:Data>2026-06-05</d:Data><d:DataReferencia>2028</d:DataReferencia><d:tipoCalculo>M</d:tipoCalculo><d:Media m:type="Decimal">5.0750</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2026-06-15T07:22:25Z</a:updated><a:author><a:name/></a:author><a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#br.gov.bcb.olinda.servico.Expectativas.ExpectativasMercadoTop5Anual"/><a:content type="application/xml"><m:properties><d:Indicador>Câmbio</d:Indicador><d:Data>2026-06-05</d:Data><d:DataReferencia>2029</d:DataReferencia><d:tipoCalculo>M</d:tipoCalculo><d:Media m:type="Decimal">5.1753</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2026-06-15T07:22:25Z</a:updated><a:author><a:name/></a:author><a:category scheme="http://docs.oasis-open.org/odata/ns/scheme" term="#br.gov.bcb.olinda.servico.Expectativas.ExpectativasMercadoTop5Anual"/><a:content type="application/xml"><m:properties><d:Indicador>Câmbio</d:Indicador><d:Data>2026-06-05</d:Data><d:DataReferencia>2030</d:DataReferencia><d:tipoCalculo>M</d:tipoCalculo><d:Media m:type="Decimal">5.2878</d:Media></m:properties></a:content></a:entry></a:feed>'
O parâmetro output='text'¶
Para pipelines de dados onde é necessário persistir o dado bruto antes de qualquer transformação
(camada SOR/SOT), o parâmetro output='text' pode ser passado diretamente ao método collect
ou ao método get do endpoint.
Isso evita serializar um DataFrame de volta para texto, o que pode ser uma operação com perda de informação.
ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')
# via query chain
raw = (ep.query()
.filter(ep.Indicador == 'IPCA')
.limit(100)
.collect(output='text'))
# via atalho get()
raw = ep.get(ep.Indicador == 'IPCA', limit=100, output='text')
# salvar em disco
with open('expectativas_raw.json', 'w') as f:
f.write(raw)
O texto retornado é o JSON bruto da resposta OData, incluindo o campo @odata.context e o array value.
O comportamento padrão (retorno de DataFrame) é mantido quando o parâmetro não é informado.
Classe ODataAPI¶
O portal de Dados Abertos do Banco Central apresenta diversas APIs OData, são
dezenas de APIs disponíveis.
A URL com metadados de cada API pode ser obtida no portal.
A classe bcb.odata.api.ODataAPI permite acessar qualquer API OData de posse da sua URL.
Por exemplo, a API de estatísticas de operações registradas no Selic tem a seguinte URL:
https://olinda.bcb.gov.br/olinda/servico/selic_operacoes/versao/v1/odata/
que pode ser obtida no portal de dados abertos no link.
Essa API pode ser diretamente acessada através da classe bcb.odata.api.ODataAPI.
In [52]: from bcb import ODataAPI
In [53]: url = "https://olinda.bcb.gov.br/olinda/servico/selic_operacoes/versao/v1/odata/"
In [54]: service = ODataAPI(url)
In [55]: service.describe()
EntitySets:
EntitySet (Endpoint): DatasOperacoesSelic
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.DataMov
Properties: DataMovimento<str>
EntitySet (Endpoint): OperacoesDisponiveis
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.OperacoesDisponiveis
Properties: Codigo<str>, Categoria<str>, Descricao<str>
EntitySet (Endpoint): DataMesAnoUltimoMovimentoSelic
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.DataUltimoMovimentoSelic
Properties: DataUltimoMovimento<str>, MesUltimoMovimento<str>, AnoUltimoMovimento<str>
EntitySet (Endpoint): OperacoesRegistradas
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.OperacoesRegistradas
Properties: Codigo<str>, Categoria<str>
FunctionImports:
Function: OperacoesEmUmAno
Parameters: Ano <str>
EntitySet: _OperacoesEmUmAno
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.OperacoesEmUmAno
Properties: Data <datetime>, Codigo <str>, Categoria <str>, Quantidade <int>, Valor <float>
Function: EvolucaoTipoOperacaoMensal
Parameters: Codigo <str>
EntitySet: _EvolucaoTipoOperacaoMensal
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.EvolucaoTipoOperacaoMensal
Properties: Mes <str>, Codigo <str>, QuantidadeAcumulada <int>, ValorAcumulado <float>, QuantidadeMediaDiaria <int>, ValorMedioDiario <float>
Function: OperacoesEmUmaData
Parameters: Data <str>
EntitySet: _OperacoesEmUmaData
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.OperacoesEmUmaData
Properties: Data <datetime>, Codigo <str>, Categoria <str>, Quantidade <int>, Valor <float>
Function: EvolucaoTipoOperacaoDiaria
Parameters: Codigo <str>, Ano <str>
EntitySet: _EvolucaoTipoOperacaoDiaria
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.EvolucaoTipoOperacaoDiaria
Properties: Data <datetime>, Codigo <str>, Quantidade <int>, Valor <float>
Function: OperacoesEmUmMes
Parameters: Mes <str>
EntitySet: _OperacoesEmUmMes
EntityType: br.gov.bcb.olinda.servico.selic_operacoes.OperacoesEmUmMes
Properties: Mes <str>, Codigo <str>, Categoria <str>, QuantidadeAcumulada <int>, ValorAcumulado <float>, QuantidadeMediaDiaria <int>, ValorMedioDiario <float>