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:

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.

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 o endpoints disponíveis na API.

In [3]: pix.describe()
EntitySets:
  PixLiquidadosAtual
  PixRemuneracaoContaPI
  PixLiquidadosIntradia
  PixDisponibilidadeSPI

Como vemos, a API do PIX tem 4 endpoints (EntitySets). Para ver as informações retornadas por cada endpoint é só executar 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>, Total<float>, Media<float>

Vemos que o endpoint PixLiquidadosAtual retorna 4 propriedades:

  • Data<datetime>: data das operações

  • Quantidade<int>: quantidade de operações realizadas na data

  • Total<float>: financeiro das operações realizdas na data

  • Media<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        Total   Media
0 2023-12-02   139072624  23360889.99  167.98
1 2024-04-19   163588000  79114284.18  483.62
2 2024-05-24   156097661  68660685.32  439.86
3 2024-02-10   140720681  25506025.17  181.25
4 2022-04-06    59981242  32855707.99  547.77

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 clausula where no 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 a n registros.

  • bcb.odata.framework.ODataQuery.parameters(): endpoints do tipo FunctionImports possuem 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         Total   Media
0 2024-06-13   146310122  5.830781e+07  398.52
1 2024-06-12   155053646  6.536795e+07  421.58
2 2024-06-11   161611592  7.162474e+07  443.19
3 2024-06-10   180385366  1.057377e+08  586.18
4 2024-06-09   123554195  1.607068e+07  130.07

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 datetime, pois na descrição do endpoint PixLiquidadosAtual a propriedade Data é do tipo datetime. 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 datetime

In [11]: (ep.query()
   ....:     .select(ep.Data, ep.Media)
   ....:     .filter(ep.Data >= datetime(2023, 1, 1))
   ....:     .orderby(ep.Media.desc())
   ....:     .limit(5)
   ....:     .collect())
   ....: 
Out[11]: 
        Data   Media
0 2023-05-02  661.07
1 2023-04-10  661.04
2 2023-01-02  652.51
3 2023-01-30  642.01
4 2024-04-01  633.91

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 >= datetime(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>, 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 >= '2022-01-01')
   ....:            .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.

É 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. Por exemplo, na API do PIX, a propriedade Data é do tipo datetime e por isso é necessário passar um objeto datetime para o método filter.

In [23]: ep = pix.get_endpoint("PixLiquidadosAtual")

In [24]: (ep.query()
   ....:    .filter(ep.Data >= datetime(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>, Total<float>, Media<float>

O objeto 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 [25]: ep = pix.get_endpoint("PixLiquidadosAtual")

In [26]: ep.Data.asc()
Out[26]: <Data asc>

Este objeto é passado para o método orderby na tripa na qual a query é construída.

In [27]: query = (ep.query()
   ....:            .orderby(ep.Data.asc())
   ....:            .limit(5))
   ....: 

In [28]: 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>, Total<float>, Media<float>

In [29]: query.collect()
Out[29]: 
        Data  Quantidade     Total   Media
0 2020-11-03        2345    210.24   89.65
1 2020-11-04        2629    336.37  127.94
2 2020-11-05       16669   2685.84  161.13
3 2020-11-06       57936  21133.81  364.78
4 2020-11-07       11089   2333.89  210.47

O método orderby pode receber diversas propriedades para a definição da ordenação.

In [30]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')

In [31]: query = (ep.query()
   ....:            .orderby(ep.Data.desc(), ep.Indicador.desc())
   ....:            .limit(5))
   ....: 

In [32]: 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 [33]: query = (ep.query()
   ....:            .orderby(ep.Data.desc())
   ....:            .orderby(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>

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 [35]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')

In [36]: (ep.query()
   ....:    .select(ep.Indicador, ep.Data, ep.DataReferencia, ep.tipoCalculo, ep.Media)
   ....:    .orderby(ep.Data.desc())
   ....:    .limit(5)
   ....:    .collect())
   ....: 
Out[36]: 
   Indicador       Data DataReferencia tipoCalculo   Media
0  PIB Total 2024-06-07           2024           L  2.3243
1  PIB Total 2024-06-07           2025           L  1.6753
2  PIB Total 2024-06-07           2026           L  1.8000
3  PIB Total 2024-06-07           2027           L  2.0000
4  PIB Total 2024-06-07           2028           L  2.0000

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 [37]: ep = pix.get_endpoint("PixLiquidadosAtual")

In [38]: (ep.query()
   ....:    .filter(ep.Data >= datetime(2023, 1, 1))
   ....:    .limit(5)
   ....:    .collect())
   ....: 
Out[38]: 
        Data  Quantidade        Total   Media
0 2023-12-02   139072624  23360889.99  167.98
1 2024-04-19   163588000  79114284.18  483.62
2 2024-05-24   156097661  68660685.32  439.86
3 2024-02-10   140720681  25506025.17  181.25
4 2023-07-11   103725918  47312155.16  456.13

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 [39]: from bcb import PTAX

In [40]: ptax = PTAX()

In [41]: ptax.describe()
EntitySets:
  Moedas
FunctionImports:
  CotacaoMoedaPeriodoFechamento
  CotacaoMoedaAberturaOuIntermediario
  CotacaoMoedaDia
  CotacaoMoedaPeriodo
  CotacaoDolarDia
  CotacaoDolarPeriodo

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 [42]: 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. Por exemplo, neste endpoint, os parâmetros dataInicial e dataFinalCotacao são formatados com mês-dia-ano (formato americano), ao invés de ano-mês-dia (formato ISO), e como o tipo dos parâmetros é str, uma formatação incorreta não retorna um erro, apenas retorna um DataFrame vazio.

Vamos realizar uma consulta para obter as cotações de dólar americano entre 2022-01-01 e 2022-01-05.

In [43]: ep = ptax.get_endpoint("CotacaoMoedaPeriodo")

In [44]: (ep.query()
   ....:    .parameters(moeda="USD",
   ....:                dataInicial="1/1/2022",
   ....:                dataFinalCotacao="1/5/2022")
   ....:    .collect())
   ....: 
Out[44]: 
    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 [45]: (ep.query()
   ....:    .parameters(moeda="USD",
   ....:                dataInicial="1/1/2022",
   ....:                dataFinalCotacao="1/5/2022")
   ....:    .filter(ep.tipoBoletim == "Fechamento")
   ....:    .collect())
   ....: 
Out[45]: 
   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 [46]: ep = em.get_endpoint('ExpectativasMercadoTop5Anuais')

In [47]: (ep.query()
   ....:    .select(ep.Indicador, ep.Data, ep.DataReferencia, ep.tipoCalculo, ep.Media)
   ....:    .orderby(ep.Data.desc())
   ....:    .limit(5)
   ....:    .text())
   ....: 
Out[47]: '{"@odata.context":"https://was-p.bcnet.bcb.gov.br/olinda/servico/Expectativas/versao/v1/odata$metadata#ExpectativasMercadoTop5Anuais(Indicador,Data,DataReferencia,tipoCalculo,Media)","value":[{"Indicador":"PIB Total","Data":"2024-06-07","DataReferencia":"2024","tipoCalculo":"L","Media":2.3243},{"Indicador":"PIB Total","Data":"2024-06-07","DataReferencia":"2025","tipoCalculo":"L","Media":1.6753},{"Indicador":"PIB Total","Data":"2024-06-07","DataReferencia":"2026","tipoCalculo":"L","Media":1.8000},{"Indicador":"PIB Total","Data":"2024-06-07","DataReferencia":"2027","tipoCalculo":"L","Media":2.0000},{"Indicador":"PIB Total","Data":"2024-06-07","DataReferencia":"2028","tipoCalculo":"L","Media":2.0000}]}'

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 [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())
   ....:    .format("xml")
   ....:    .limit(5)
   ....:    .text())
   ....: 
Out[49]: '<?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>2024-06-15T11:14:54Z</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>PIB Total</d:Indicador><d:Data>2024-06-07</d:Data><d:DataReferencia>2024</d:DataReferencia><d:tipoCalculo>L</d:tipoCalculo><d:Media m:type="Decimal">2.3243</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2024-06-15T11:14:54Z</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>PIB Total</d:Indicador><d:Data>2024-06-07</d:Data><d:DataReferencia>2025</d:DataReferencia><d:tipoCalculo>L</d:tipoCalculo><d:Media m:type="Decimal">1.6753</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2024-06-15T11:14:54Z</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>PIB Total</d:Indicador><d:Data>2024-06-07</d:Data><d:DataReferencia>2026</d:DataReferencia><d:tipoCalculo>L</d:tipoCalculo><d:Media m:type="Decimal">1.8000</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2024-06-15T11:14:54Z</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>PIB Total</d:Indicador><d:Data>2024-06-07</d:Data><d:DataReferencia>2027</d:DataReferencia><d:tipoCalculo>L</d:tipoCalculo><d:Media m:type="Decimal">2.0000</d:Media></m:properties></a:content></a:entry><a:entry><a:title/><a:summary/><a:updated>2024-06-15T11:14:54Z</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>PIB Total</d:Indicador><d:Data>2024-06-07</d:Data><d:DataReferencia>2028</d:DataReferencia><d:tipoCalculo>L</d:tipoCalculo><d:Media m:type="Decimal">2.0000</d:Media></m:properties></a:content></a:entry></a:feed>'

Classe ODataAPI

O portal de Dados Abertos to 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 [50]: from bcb import ODataAPI

In [51]: url = "https://olinda.bcb.gov.br/olinda/servico/selic_operacoes/versao/v1/odata/"

In [52]: service = ODataAPI(url)

In [53]: service.describe()
EntitySets:
  DatasOperacoesSelic
FunctionImports:
  OperacoesEmUmAno
  OperacoesEmUmaData