<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Felipe Ignacio</title>
    <description>The latest articles on DEV Community by Felipe Ignacio (@fmaignacio).</description>
    <link>https://dev.to/fmaignacio</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3783033%2F0d55a99e-6ffd-4856-89e7-65ecc400d202.png</url>
      <title>DEV Community: Felipe Ignacio</title>
      <link>https://dev.to/fmaignacio</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/fmaignacio"/>
    <language>en</language>
    <item>
      <title>Como contornei o limite de 10 anos da API do Banco Central com Python (async)</title>
      <dc:creator>Felipe Ignacio</dc:creator>
      <pubDate>Fri, 20 Feb 2026 18:56:55 +0000</pubDate>
      <link>https://dev.to/fmaignacio/como-eu-resolvi-o-limite-de-10-anos-da-api-do-banco-central-do-brasil-com-python-poh</link>
      <guid>https://dev.to/fmaignacio/como-eu-resolvi-o-limite-de-10-anos-da-api-do-banco-central-do-brasil-com-python-poh</guid>
      <description>&lt;h1&gt;
  
  
  Uma solução open source para baixar séries históricas completas do Bacen usando paginação automática, asyncio e cache local.
&lt;/h1&gt;




&lt;p&gt;Em 2025, o Banco Central do Brasil passou a limitar consultas da API SGS a no máximo 10 anos por requisição.&lt;/p&gt;

&lt;p&gt;Para quem trabalha com séries econômicas longas — dólar desde os anos 80, Selic desde os anos 90 ou inflação histórica — isso quebrou pipelines inteiros de análise.&lt;/p&gt;

&lt;p&gt;Criei o &lt;strong&gt;BacenData&lt;/strong&gt; para resolver isso de forma transparente.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR — uma chamada resolve tudo
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bacendata&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;

&lt;span class="n"&gt;dolar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dolar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1984-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agora, se o intervalo for maior que 10 anos, a API retorna erro 400 ou uma resposta vazia. Para obter dados completos do Dólar (código 1), que existe desde 1984, você precisaria fazer pelo menos 5 requisições separadas, concatenar os resultados e remover duplicatas.&lt;/p&gt;

&lt;p&gt;É exatamente isso que o BacenData automatiza.&lt;/p&gt;

&lt;h2&gt;
  
  
  Como baixar 40 anos de dados em uma única chamada
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;pip&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;bacendata&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bacendata&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;

&lt;span class="c1"&gt;# Série completa do Dólar — 40+ anos em uma chamada
&lt;/span&gt;&lt;span class="n"&gt;dolar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dolar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1984-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;dolar&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; registros de &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dolar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; a &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;dolar&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por baixo dos panos, o BacenData:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Calcula os intervalos&lt;/strong&gt;: divide o período solicitado em chunks de no máximo 10 anos&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faz requisições paralelas&lt;/strong&gt;: usa &lt;code&gt;asyncio.gather&lt;/code&gt; com um &lt;code&gt;Semaphore(5)&lt;/code&gt; para limitar a 5 requisições simultâneas (cortesia com o servidor do BACEN)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Combina os resultados&lt;/strong&gt;: concatena todos os DataFrames, remove duplicatas de datas sobrepostas e ordena cronologicamente&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trata erros individuais&lt;/strong&gt;: se um intervalo retornar 404 (dados não disponíveis naquele período), ele é ignorado sem abortar a consulta inteira&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;O resultado é um &lt;code&gt;pandas.DataFrame&lt;/code&gt; limpo, pronto para análise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Funcionalidades principais
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Aliases para séries populares
&lt;/h3&gt;

&lt;p&gt;Em vez de decorar códigos numéricos, use nomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Estes são equivalentes:
&lt;/span&gt;&lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2020-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dolar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2020-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O BacenData vem com 14 séries pré-configuradas:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Alias&lt;/th&gt;
&lt;th&gt;Código&lt;/th&gt;
&lt;th&gt;Descrição&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;selic&lt;/td&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;Taxa Selic diária&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;selic_meta&lt;/td&gt;
&lt;td&gt;432&lt;/td&gt;
&lt;td&gt;Meta Selic definida pelo Copom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;selic_mensal&lt;/td&gt;
&lt;td&gt;4390&lt;/td&gt;
&lt;td&gt;Selic acumulada no mês&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ipca&lt;/td&gt;
&lt;td&gt;433&lt;/td&gt;
&lt;td&gt;IPCA variação mensal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;dolar&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Dólar PTAX venda&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;euro&lt;/td&gt;
&lt;td&gt;21619&lt;/td&gt;
&lt;td&gt;Euro PTAX compra&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;cdi&lt;/td&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;CDI diário&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;igpm&lt;/td&gt;
&lt;td&gt;189&lt;/td&gt;
&lt;td&gt;IGP-M variação mensal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;juros_pf&lt;/td&gt;
&lt;td&gt;20714&lt;/td&gt;
&lt;td&gt;Taxa média de juros PF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;juros_pj&lt;/td&gt;
&lt;td&gt;20715&lt;/td&gt;
&lt;td&gt;Taxa média de juros PJ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;inadimplencia_pf&lt;/td&gt;
&lt;td&gt;21112&lt;/td&gt;
&lt;td&gt;Inadimplência PF&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;inadimplencia_pj&lt;/td&gt;
&lt;td&gt;21113&lt;/td&gt;
&lt;td&gt;Inadimplência PJ&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;reservas&lt;/td&gt;
&lt;td&gt;13621&lt;/td&gt;
&lt;td&gt;Reservas internacionais (USD)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;focus_ipca&lt;/td&gt;
&lt;td&gt;13522&lt;/td&gt;
&lt;td&gt;Expectativa Focus IPCA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2. Múltiplas séries de uma vez
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;df&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Selic&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;IPCA&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;433&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Dólar&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;2015-01-01&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;df&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;head&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resultado:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                Selic   IPCA  Dólar
data
2015-01-02  0.046189    NaN  2.694
2015-01-05  0.046189    NaN  2.702
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Últimos N valores
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Últimos 12 valores do IPCA
&lt;/span&gt;&lt;span class="n"&gt;ipca&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ipca&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;last&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Cache inteligente
&lt;/h3&gt;

&lt;p&gt;O BacenData mantém um cache SQLite local com TTL automático por tipo de série:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Séries diárias: cache de 6 horas&lt;/li&gt;
&lt;li&gt;Séries mensais: cache de 24 horas
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Desativar cache se necessário
&lt;/span&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;bacendata.wrapper.cache&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;desativar&lt;/span&gt;
&lt;span class="nf"&gt;desativar&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Metadados das séries
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sgs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# {'codigo': 1, 'nome': 'Taxa de câmbio - Livre - Dólar americano (venda) - diário',
#  'periodicidade': 'D', 'unidade': 'u.m.c./US$', ...}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Como funciona por dentro
&lt;/h2&gt;

&lt;p&gt;A arquitetura é simples e pragmática:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bacendata/
├── wrapper/
│   ├── bacen_sgs.py    # Core: get(), aget(), metadata()
│   ├── catalogo.py     # 14 séries pré-configuradas
│   ├── cache.py        # Cache SQLite com TTL
│   └── exceptions.py   # Exceções customizadas
├── api/
│   ├── app.py          # FastAPI app factory
│   └── routes/         # Endpoints REST
└── schemas/
    └── series.py       # Pydantic models
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A paginação em detalhe
&lt;/h3&gt;

&lt;p&gt;O coração do BacenData é a função &lt;code&gt;_buscar_com_paginacao&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_buscar_com_paginacao&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inicio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;intervalos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_gerar_intervalos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inicio&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fim&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_anos&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;semaforo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Semaphore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_com_semaforo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ini&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;semaforo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;_buscar_serie_periodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ini&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;SerieNaoEncontrada&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;BacenAPIError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;  &lt;span class="c1"&gt;# Intervalo sem dados, não aborta
&lt;/span&gt;
    &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;fetch_com_semaforo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ini&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ini&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fi&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;intervalos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;resultados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;todos_dados&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sublista&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;resultados&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sublista&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;todos_dados&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;SerieNaoEncontrada&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;codigo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;todos_dados&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O &lt;code&gt;Semaphore(5)&lt;/code&gt; é crucial: sem ele, uma consulta de 40 anos geraria 5 requisições simultâneas de uma vez, podendo sobrecarregar o servidor do BACEN. Com o semáforo, nunca passamos de 5 conexões paralelas.&lt;/p&gt;

&lt;p&gt;O &lt;code&gt;try/except&lt;/code&gt; no &lt;code&gt;fetch_com_semaforo&lt;/code&gt; resolve outro problema sutil: quando o usuário pede "todos os dados disponíveis", o BacenData gera intervalos desde 1960. Para séries que começaram em 1984, os intervalos de 1960-1970 e 1970-1980 retornam 404. Sem o try/except, o &lt;code&gt;asyncio.gather&lt;/code&gt; falharia inteiramente.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack técnica
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;httpx&lt;/strong&gt; (async): HTTP client — escolhido por suporte nativo a async, ao contrário do &lt;code&gt;requests&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;asyncio&lt;/strong&gt;: paralelismo de I/O para paginação&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;pandas&lt;/strong&gt;: retorno em DataFrame para integração fácil com o ecossistema Python de dados&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SQLite&lt;/strong&gt;: cache local leve, sem dependências extras&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FastAPI&lt;/strong&gt;: API REST com docs automáticas (Swagger/ReDoc)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Streamlit + Plotly&lt;/strong&gt;: dashboard interativo para não-programadores&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  API REST
&lt;/h2&gt;

&lt;p&gt;O BacenData também expõe uma API REST para integração com qualquer linguagem/sistema:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Instalar&lt;/span&gt;
pip &lt;span class="nb"&gt;install &lt;/span&gt;bacendata[api]

&lt;span class="c"&gt;# Rodar&lt;/span&gt;
uvicorn bacendata.api.app:create_app &lt;span class="nt"&gt;--factory&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Endpoints:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /api/v1/series/{codigo}?start=2020-01-01&amp;amp;end=2025-01-01
GET /api/v1/series/{codigo}/metadata
POST /api/v1/series/bulk  (múltiplas séries)
GET /api/v1/catalogo
GET /api/v1/catalogo/search?q=selic
GET /health
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Exemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s2"&gt;"http://localhost:8000/api/v1/series/1?start=2025-01-01&amp;amp;last=5"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"codigo"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nome"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Taxa de câmbio - Livre - Dólar americano (venda) - diário"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dados"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-01-02"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"valor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.1797&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-01-03"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"valor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;6.1627&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"total_registros"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Dashboard interativo
&lt;/h2&gt;

&lt;p&gt;Para quem não programa, o BacenData tem um dashboard Streamlit público:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://bacendata.streamlit.app" rel="noopener noreferrer"&gt;https://bacendata.streamlit.app&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Features:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gráficos interativos com zoom e hover&lt;/li&gt;
&lt;li&gt;Comparação lado a lado de até 3 séries&lt;/li&gt;
&lt;li&gt;Média móvel configurável&lt;/li&gt;
&lt;li&gt;Download CSV/Excel&lt;/li&gt;
&lt;li&gt;Todos os 14 indicadores disponíveis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Por que criei o BacenData
&lt;/h2&gt;

&lt;p&gt;Eu precisava dessas séries para análise econômica e modelagem de risco. Fazer manualmente várias requisições, concatenar dados e tratar duplicatas não escala.&lt;/p&gt;

&lt;p&gt;O BacenData nasceu para automatizar esse processo.&lt;/p&gt;

&lt;h2&gt;
  
  
  Experimente agora
&lt;/h2&gt;

&lt;p&gt;Se você trabalha com dados econômicos, risco ou fintech, o BacenData elimina horas de coleta manual.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/fmaignacio/bacendata" rel="noopener noreferrer"&gt;github.com/fmaignacio/bacendata&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PyPI&lt;/strong&gt;: &lt;a href="https://pypi.org/project/bacendata/" rel="noopener noreferrer"&gt;pypi.org/project/bacendata&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard&lt;/strong&gt;: &lt;a href="https://bacendata.streamlit.app" rel="noopener noreferrer"&gt;bacendata.streamlit.app&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Site&lt;/strong&gt;: &lt;a href="https://bacendata.com" rel="noopener noreferrer"&gt;bacendata.com&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Dá uma olhada e me conta o que achou.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>opensource</category>
      <category>tutorial</category>
      <category>api</category>
    </item>
  </channel>
</rss>
