From b0fb43290ae480c9eec27fe05b64f7efac4a04da Mon Sep 17 00:00:00 2001 From: Wilson Freitas Date: Sun, 14 Jun 2026 18:11:19 -0300 Subject: [PATCH] Clean up documentation drift --- README.md | 30 +++++++++++++++++------- bcb/currency.py | 22 ++++++++++-------- bcb/sgs/__init__.py | 44 +++++++++++++++++++---------------- bcb/sgs/regional_economy.py | 12 +++++----- docs/async.rst | 18 ++++++++++---- docs/currency.rst | 8 +++---- docs/expectativas.rst | 4 +++- docs/odata.rst | 25 ++++++++++---------- docs/sgs.rst | 8 +++++-- docs/taxajuros.rst | 4 ++-- examples/async_usage.py | 16 +++++++++---- examples/currency_exchange.py | 7 +++--- examples/sgs_time_series.py | 5 ++-- 13 files changed, 120 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index 50bcfb0..bd6cb93 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Implementado no módulo `currency`, realiza webscraping no site do [Conversor de ### OData - APIs Estruturadas O Banco Central disponibiliza diversas informações em APIs que seguem o padrão [OData](https://odata.org). Inclui: -- **PTAX**: Boletins diários de taxas de câmbio com dados institucionalmentedetalhados +- **PTAX**: Boletins diários de taxas de câmbio com dados institucionalmente detalhados - **Expectativas**: Expectativas de mercado coletadas do Boletim FOCUS - **TaxaJuros**: Diversas taxas de juros (Selic, CDI, Cheque especial, etc.) - **MercadoImobiliario**: Dados de financiamento imobiliário @@ -60,7 +60,7 @@ Use esta tabela para escolher o módulo certo para seu caso de uso: | Dados de financiamento imobiliário | `bcb.odata` (MercadoImobiliario) | Originações, taxas médias, volumes | | Informações de instituições financeiras | `bcb.odata` (IFDATA) | Dados de balanço, informações regulatórias | | Análise de dados avançada com filtros | `bcb.odata` (qualquer serviço) | API encadeável, filtragem tipo SQL, ordenação, seleção | -| Busca concorrente de dados | Qualquer módulo com `async_get()` | Requisições não-bloqueantes, melhor performance para operações em massa | +| Busca concorrente de dados | APIs assíncronas (`sgs`, `currency` e OData) | Requisições não-bloqueantes com `async_get()`, `Endpoint.async_get()` e `ODataQuery.async_collect()` | ## Início Rápido @@ -106,16 +106,20 @@ df = endpoint.query().filter(endpoint.Indicador == "IPCA").limit(100).collect() - Serviços OData: Varia; consulte documentação BCB para endpoints específicos ### P: Posso buscar dados de forma assíncrona? -**R:** Sim! Todos os módulos têm métodos `async_get()` ou similares. Use-os para requisições concorrentes: +**R:** Sim. SGS e currency oferecem `async_get()`, e os endpoints OData oferecem `async_get()` e `async_collect()`. Feche o cliente assíncrono ao final de aplicações de longa duração: ```python import asyncio -from bcb import sgs +from bcb import http, sgs async def main(): - results = await asyncio.gather( - sgs.async_get(1), # SELIC - sgs.async_get(433), # IPCA - ) + try: + results = await asyncio.gather( + sgs.async_get(1), # SELIC + sgs.async_get(433), # IPCA + ) + return results + finally: + await http.aclose_async_client() asyncio.run(main()) ``` @@ -162,7 +166,7 @@ logger.setLevel(logging.DEBUG) - Limites de requisições: APIs BCB podem ter limites; implemente backoff se necessário - Cache: Cache de moedas persiste em memória; limpe se atualizações de dados importarem - Pool de conexões: Usa httpx com connection pooling por padrão -- API Assíncrona: Use métodos async para comportamento verdadeiramente não-bloqueante +- API Assíncrona: use métodos async para comportamento verdadeiramente não-bloqueante e chame `await bcb.http.aclose_async_client()` no encerramento de aplicações assíncronas longas ### P: Como contribuo ou reporto problemas? **R:** Visite o [repositório GitHub](https://github.com/wilsonfreitas/python-bcb) para: @@ -171,6 +175,14 @@ logger.setLevel(logging.DEBUG) - Enviar pull requests - Ver documentação +### P: Como gero a documentação localmente? +**R:** As dependências de documentação ficam no grupo `docs` do `uv`: +```shell +uv run --group docs sphinx-build -b html docs docs/_build/html +``` + +A saída HTML é gerada em `docs/_build/html`. Edite os arquivos fonte em `docs/`; não edite os arquivos gerados em `docs/_build`. + ### P: Onde encontro documentação mais detalhada? **R:** - [Documentação de API](https://wilsonfreitas.github.io/python-bcb/) diff --git a/bcb/currency.py b/bcb/currency.py index 05d25a7..bf82cd7 100644 --- a/bcb/currency.py +++ b/bcb/currency.py @@ -660,12 +660,12 @@ def get( Códigos das moedas padrão ISO. O código de uma única moeda que retorna uma série temporal univariada e uma lista de códigos retorna uma série temporal multivariada. - start : str, int, date, datetime, Timestamp - Data de início da série. - Interpreta diferentes tipos e formatos de datas. - end : string, int, date, datetime, Timestamp - Data de início da série. - Interpreta diferentes tipos e formatos de datas. + start : str, date, datetime or bcb.utils.Date + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. side : {"ask", "bid", "both"}, default "ask" Define se a série retornada vem com os ``ask`` prices, ``bid`` prices ou ``both`` para ambos. @@ -899,10 +899,12 @@ async def async_get( ---------- symbols : str, List[str] Códigos das moedas padrão ISO - start : str, int, date, datetime, Timestamp - Data de início da série - end : string, int, date, datetime, Timestamp - Data final da série + start : str, date, datetime or bcb.utils.Date + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. side : {"ask", "bid", "both"} ``'ask'``, ``'bid'`` ou ``'both'`` groupby : {"symbol", "side"} diff --git a/bcb/sgs/__init__.py b/bcb/sgs/__init__.py index 6643960..8934d14 100644 --- a/bcb/sgs/__init__.py +++ b/bcb/sgs/__init__.py @@ -291,12 +291,12 @@ def get( Com códigos numéricos é interessante utilizar os nomes com os códigos para definir os nomes nas colunas das séries temporais. - start : str, int, date, datetime, Timestamp - Data de início da série. - Interpreta diferentes tipos e formatos de datas. - end : string, int, date, datetime, Timestamp - Data final da série. - Interpreta diferentes tipos e formatos de datas. + start : str, date, datetime or bcb.utils.Date + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. last : int Retorna os últimos ``last`` elementos disponíveis da série temporal solicitada. Se ``last`` for maior que 0 (zero) os argumentos ``start`` @@ -371,12 +371,12 @@ def get_json( code : int Código da série temporal - start : str, int, date, datetime, Timestamp - Data de início da série. - Interpreta diferentes tipos e formatos de datas. - end : string, int, date, datetime, Timestamp - Data final da série. - Interpreta diferentes tipos e formatos de datas. + start : str, date, datetime or bcb.utils.Date + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. last : int Retorna os últimos ``last`` elementos disponíveis da série temporal solicitada. Se ``last`` for maior que 0 (zero) os argumentos ``start`` @@ -420,10 +420,12 @@ async def async_get_json( ---------- code : int Código da série temporal - start : str, int, date, datetime, Timestamp, optional - Data de início da série - end : string, int, date, datetime, Timestamp, optional - Data final da série + start : str, date, datetime or bcb.utils.Date, optional + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date, optional + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. last : int Retorna os últimos ``last`` elementos disponíveis @@ -480,10 +482,12 @@ async def async_get( ---------- codes : {int, List[int], List[str], Dict[str:int]} Código(s) da série temporal - start : str, int, date, datetime, Timestamp, optional - Data de início da série - end : string, int, date, datetime, Timestamp, optional - Data final da série + start : str, date, datetime or bcb.utils.Date, optional + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date, optional + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. last : int Retorna os últimos ``last`` elementos disponíveis multi : bool diff --git a/bcb/sgs/regional_economy.py b/bcb/sgs/regional_economy.py index e52e814..e2904b7 100644 --- a/bcb/sgs/regional_economy.py +++ b/bcb/sgs/regional_economy.py @@ -219,12 +219,12 @@ def get_non_performing_loans( mode (str): O tipo de inadimplência. Pode ser "PF" (pessoas físicas), "PJ" (pessoas jurídicas), "total" ou "all" (inadimplência total). - start : str, int, date, datetime, Timestamp - Data de início da série. - Interpreta diferentes tipos e formatos de datas. - end : string, int, date, datetime, Timestamp - Data final da série. - Interpreta diferentes tipos e formatos de datas. + start : str, date, datetime or bcb.utils.Date + Data de início da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. + end : str, date, datetime or bcb.utils.Date + Data final da série. Strings usam o formato ``YYYY-MM-DD``; + ``'today'`` e ``'now'`` também são aceitos. last : int Retorna os últimos ``last`` elementos disponíveis da série temporal solicitada. Se ``last`` for maior que 0 (zero) os argumentos ``start`` diff --git a/docs/async.rst b/docs/async.rst index ffc352e..f1e0c2a 100644 --- a/docs/async.rst +++ b/docs/async.rst @@ -77,12 +77,20 @@ Busca taxas de câmbio de forma assíncrona com a mesma interface que a versão .. code-block:: python import asyncio - from bcb import currency + from bcb import currency, http async def main(): - # Buscar taxas de câmbio - usd = await currency.async_get('USD', start='2024-01-01', end='2024-12-31') - print(usd.head()) + try: + # Buscar múltiplas taxas de câmbio em paralelo + rates = await currency.async_get( + ['USD', 'EUR'], + start='2024-01-01', + end='2024-12-31', + side='both', + ) + print(rates.head()) + finally: + await http.aclose_async_client() asyncio.run(main()) @@ -259,4 +267,4 @@ Veja Também * :ref:`SGS` — Documentação completa do módulo SGS * :ref:`Conversor de Moedas` — Documentação do módulo currency * :ref:`OData` — Documentação do cliente OData -* `asyncio — asyncpython `_ +* `asyncio — documentação Python `_ diff --git a/docs/currency.rst b/docs/currency.rst index c2fac88..eb75822 100644 --- a/docs/currency.rst +++ b/docs/currency.rst @@ -15,7 +15,7 @@ API OData de Moedas __ documentacao_ -A classe :py:class:`bcb.PTAX` retorna cotações de moedas os obtidas a partir da `API de Moedas`__ do BCB. +A classe :py:class:`bcb.PTAX` retorna cotações de moedas obtidas a partir da `API de Moedas`__ do BCB. Esta implementação é mais estável que a do :ref:`Conversor de Moedas`. .. ipython:: python @@ -47,7 +47,7 @@ são preenchidos com 0 para ter 2 dígitos. .. ipython:: python ptax.describe('CotacaoMoedaPeriodo') - + ep = ptax.get_endpoint('CotacaoMoedaPeriodo') (ep.query() .parameters(moeda='AUD', @@ -58,7 +58,7 @@ são preenchidos com 0 para ter 2 dígitos. Conversor de Moedas ------------------- -O módulo :py:mod:`bcb.currency` obtem dados de moedas do conversor de moedas do Banco Central através de webscraping. +O módulo :py:mod:`bcb.currency` obtém dados de moedas do conversor de moedas do Banco Central através de webscraping. Os parâmetros ``start`` e ``end`` aceitam strings ``YYYY-MM-DD``, ``datetime.date``, ``datetime.datetime`` ou :py:class:`bcb.utils.Date`. .. ipython:: python @@ -103,6 +103,6 @@ retornado um ``dict`` mapeando símbolo ISO → CSV string. f.write(raw) O CSV retornado usa ponto-e-vírgula como separador, datas no formato ``DDMMYYYY`` e vírgula -como separador decimal — exatamente como devolvido pela API PTAX do BCB. +como separador decimal — exatamente como devolvido pelo serviço de câmbio do BCB. O comportamento padrão (retorno de DataFrame) é mantido quando o parâmetro não é informado. diff --git a/docs/expectativas.rst b/docs/expectativas.rst index f7e266c..ab1aa34 100644 --- a/docs/expectativas.rst +++ b/docs/expectativas.rst @@ -91,9 +91,11 @@ ordenando colunas e selecionando as colunas na saída. .. ipython:: python + from datetime import date + (ep.query() .filter(ep.Indicador == 'IPCA', ep.DataReferencia == 2023) - .filter(ep.Data >= '2022-01-01') + .filter(ep.Data >= date(2022, 1, 1)) .filter(ep.tipoCalculo == 'C') .select(ep.Data, ep.Media, ep.Mediana) .orderby(ep.Data.desc()) diff --git a/docs/odata.rst b/docs/odata.rst index e5aa59f..aac1c15 100644 --- a/docs/odata.rst +++ b/docs/odata.rst @@ -118,18 +118,18 @@ Quero obter os 10 dias em 2023 que apresentam as maiores médias transacionadas 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``. +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. .. ipython:: python - from datetime import datetime + from datetime import date (ep.query() .select(ep.Data, ep.Media) - .filter(ep.Data >= datetime(2023, 1, 1)) + .filter(ep.Data >= date(2023, 1, 1)) .orderby(ep.Media.desc()) .limit(5) .collect()) @@ -145,7 +145,7 @@ mas não a executa. (ep.query() .select(ep.Data, ep.Media) - .filter(ep.Data >= datetime(2023, 1, 1)) + .filter(ep.Data >= date(2023, 1, 1)) .orderby(ep.Media.desc()) .limit(5) .show()) @@ -189,7 +189,7 @@ Mais filtros podem ser adicionados ao método ``filter``, e também podemos anin query = (ep.query() .filter(ep.Indicador == 'IPCA', ep.DataReferencia == 2023) - .filter(ep.Data >= '2022-01-01') + .filter(ep.Data >= date(2022, 1, 1)) .filter(ep.tipoCalculo == 'C') .limit(5)) query.show() @@ -199,18 +199,17 @@ Todos os filtros estão no atributo ``$filter`` da consulta e são concatenados É 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``. +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. .. ipython:: python ep = pix.get_endpoint("PixLiquidadosAtual") (ep.query() - .filter(ep.Data >= datetime(2023, 1, 1)) + .filter(ep.Data >= date(2023, 1, 1)) .limit(5) .show()) -O objeto ``datetime`` é formatado como data na consulta, note que não há aspas na definição da data no filtro. +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 ^^^^^^^^^^^^^^^^^^ @@ -284,7 +283,7 @@ Esse método é importante para investigar as consultas na API de forma rápida. ep = pix.get_endpoint("PixLiquidadosAtual") (ep.query() - .filter(ep.Data >= datetime(2023, 1, 1)) + .filter(ep.Data >= date(2023, 1, 1)) .limit(5) .collect()) @@ -419,10 +418,10 @@ O comportamento padrão (retorno de DataFrame) é mantido quando o parâmetro n Classe ODataAPI --------------- -O portal de Dados Abertos to Banco Central apresenta diversas APIs OData, são +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 :py:class:`bcb.odata.api.ODataAPI` permite acessar qualquer API Odata de posse da sua URL. +A classe :py:class:`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:: diff --git a/docs/sgs.rst b/docs/sgs.rst index 55b0d93..5e31118 100644 --- a/docs/sgs.rst +++ b/docs/sgs.rst @@ -1,10 +1,12 @@ SGS === -A função :py:func:`bcb.sgs.get` obtem os dados do webservice do Banco Central , -interface json do serviço BCData/SGS - +A função :py:func:`bcb.sgs.get` obtém os dados do webservice do Banco Central, +interface JSON do serviço BCData/SGS - `Sistema Gerenciador de Séries Temporais (SGS) `_. +Os parâmetros ``start`` e ``end`` aceitam strings ``YYYY-MM-DD``, ``datetime.date``, ``datetime.datetime`` ou :py:class:`bcb.utils.Date`. Também é possível usar ``last`` para buscar os últimos ``n`` pontos disponíveis. + Exemplos -------- @@ -70,6 +72,8 @@ O comportamento padrão (retorno de DataFrame) é mantido quando o parâmetro n Dados de Inadimplência de Operações de Crédito ============================================== +Os modos aceitos são ``PF`` (pessoas físicas), ``PJ`` (pessoas jurídicas) e ``total``; ``all`` é aceito como alias de ``total``. Os locais devem ser todos estados ou todos regiões, sem misturar os dois tipos na mesma chamada. + .. ipython:: python from bcb.sgs.regional_economy import get_non_performing_loans diff --git a/docs/taxajuros.rst b/docs/taxajuros.rst index 3f6456a..e305ee1 100644 --- a/docs/taxajuros.rst +++ b/docs/taxajuros.rst @@ -4,14 +4,14 @@ Taxas de Juros A API de taxas de juros de operações de crédito pode ser acessada através da classe :py:class:`bcb.TaxaJuros`. -.. _documentacao: https://olinda.bcb.gov.br/olinda/servico/TaxaJuros/versao/v1/documentacao +.. _documentacao: https://olinda.bcb.gov.br/olinda/servico/taxaJuros/versao/v2/documentacao __ documentacao_ Os dados são obtidos a partir da `API de Taxas de Juros`__. -Esta API tem os ``EntitySets``: +Esta API usa o serviço ``taxaJuros`` versão ``v2`` e tem os ``EntitySets``: .. ipython:: python diff --git a/examples/async_usage.py b/examples/async_usage.py index fcb1a31..8d06506 100644 --- a/examples/async_usage.py +++ b/examples/async_usage.py @@ -6,7 +6,7 @@ """ import asyncio -from bcb import sgs, currency +from bcb import http, sgs, currency from bcb.odata.api import Expectativas @@ -27,9 +27,13 @@ async def fetch_multiple_currencies(): """Buscar taxas de câmbio concorrentemente.""" print("Exemplo 2: Buscando taxas de câmbio concorrentemente") - # Buscar taxa do USD (nota: você precisaria implementar async multi-símbolo - # para isso ser verdadeiramente concorrente para diferentes símbolos) - df = await currency.async_get("USD", start="2024-01-01", end="2024-12-31") + # Buscar múltiplos símbolos em paralelo + df = await currency.async_get( + ["USD", "EUR"], + start="2024-01-01", + end="2024-12-31", + side="both", + ) print("Busca de câmbio assíncrona concluída") print(df.head()) print() @@ -78,9 +82,11 @@ async def main(): await concurrent_operations() except Exception as e: print(f"Erro: {type(e).__name__}: {e}") + finally: + await http.aclose_async_client() if __name__ == "__main__": # Executar os exemplos assíncronos - # Nota: Isso requer Python 3.7+ com asyncio + # Nota: o pacote requer Python 3.10+ asyncio.run(main()) diff --git a/examples/currency_exchange.py b/examples/currency_exchange.py index 0165219..274c92d 100644 --- a/examples/currency_exchange.py +++ b/examples/currency_exchange.py @@ -5,7 +5,8 @@ sistema PTAX do Banco Central (cotações diárias de câmbio). """ -from datetime import datetime +import datetime as dt + from bcb import currency # Buscar uma única moeda (USD) @@ -60,11 +61,9 @@ # Limpar o cache se executando múltiplas requisições currency.clear_cache() -print("Cache limpo para requisições fresgas") +print("Cache limpo para requisições frescas") # Obter taxa de câmbio de hoje (aproximada) -import datetime as dt - today = dt.date.today() today_rates = currency.get("USD", start=today - dt.timedelta(days=30), end=today) print("\nTaxas de Câmbio Recentes do USD") diff --git a/examples/sgs_time_series.py b/examples/sgs_time_series.py index 0faee45..790020a 100644 --- a/examples/sgs_time_series.py +++ b/examples/sgs_time_series.py @@ -5,7 +5,6 @@ do SGS (Sistema Gerenciador de Séries Temporais) do Banco Central. """ -import pandas as pd from bcb import sgs # Buscar uma única série temporal @@ -23,7 +22,9 @@ # Buscar múltiplas séries temporais de uma vez # SELIC (1) e IPCA (433) -multi_series = sgs.get([("SELIC", 1), ("IPCA", 433)], start="2023-01-01", end="2024-12-31") +multi_series = sgs.get( + [("SELIC", 1), ("IPCA", 433)], start="2023-01-01", end="2024-12-31" +) print("Múltiplas Séries Temporais (SELIC + IPCA)") print(multi_series.head()) print()