Como calcular a inflação implícita e decidir o melhor Tesouro Direto

Image Como calcular a inflação implícita e decidir o melhor Tesouro Direto


Existe um jeito simples (e que quase ninguém conhece) para decidir entre os dois tipos. Vou mostrar isso programando Vou criar um script em Python que automatiza essa análise para os títulos do Tesouro Direto. O script vai extrair as taxas dos títulos prefixados e dos títulos IPCA+, fazer os cálculos necessários e exibir os resultados em uma tabela.

O que é a Inflação Implícita no Contexto do Tesouro Direto?

A inflação implícita é a expectativa do mercado para a inflação futura, calculada a partir da diferença entre as taxas dos títulos do Tesouro Prefixado e do Tesouro IPCA+. Ela indica a inflação esperada para o período de vencimento dos títulos e é um indicador importante para os investidores decidirem onde aplicar seu dinheiro.

Como a Inflação Implícita é Calculada?

A inflação implícita é obtida com a seguinte fórmula:

image-0.2834554491822372

Onde:

  • Taxa Prefixada: Taxa de juros oferecida pelo Tesouro Prefixado para um determinado vencimento.
  • Taxa do Tesouro IPCA+: Taxa fixa do Tesouro IPCA+ para o mesmo vencimento.
  • Essa relação mostra a inflação esperada para o período, pois o Tesouro IPCA+ remunera o investidor com uma taxa fixa + inflação, enquanto o Tesouro Prefixado oferece um retorno fixo.

    Exemplo Prático

    Suponha que para um título com vencimento em 2029, as taxas sejam:

  • Tesouro Prefixado 2029: 10,5% ao ano
  • Tesouro IPCA+ 2029: 5,2% ao ano
  • Aplicando a fórmula:

    image-0.03932664745263059

    Isso significa que o mercado espera uma inflação média de 5,03% ao ano até 2029.

    Como Utilizar a Inflação Implícita na Escolha de Investimentos?

    Comparação com a inflação projetada

  • Se você acredita que a inflação real será maior que a inflação implícita, o Tesouro IPCA+ pode ser mais vantajoso.
  • Se a inflação real for menor, o Tesouro Prefixado pode render mais.
  • Vamos ao código

  • 1 Extrai as informações dos títulos prefixados e indexados ao IPCA
  • class TesouroDiretoExtractor:
        """Classe para extrair dados do Tesouro Direto utilizando vários métodos"""
    
        def __init__(self):
            self.tesouro_url = "https://www.tesourodireto.com.br/titulos/precos-e-taxas.htm"
            self.tesouro_api_url = "https://www.tesourodireto.com.br/json/br/com/b3/tesourodireto/service/api/treasurybondsinfo.json"
            self.headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
            }
            self.titulos_prefixados = []
            self.titulos_ipca = []
    
        def _fazer_requisicao(self, url: str) -> Optional[requests.Response]:
            """Faz uma requisição HTTP para a URL especificada"""
            try:
                response = requests.get(url, headers=self.headers)
                response.raise_for_status()
                return response
            except requests.exceptions.RequestException as e:
                logger.error(f"Erro ao acessar a URL {url}: {e}")
                return None
    
        def _extrair_titulos_do_json(self, script_content: str) -> None:
            """Extrai informações de títulos de um script contendo JSON"""
            try:
                json_match = re.search(r'window\.TD\.titulos\s*=\s*(\[.*?\]);', script_content, re.DOTALL)
                if not json_match:
                    return
    
                json_data = json.loads(json_match.group(1))
    
                for titulo_data in json_data:
                    nome = titulo_data.get('nome', '')
                    vencimento = titulo_data.get('vencimento', '')
    
                    try:
                        rentabilidade = float(titulo_data.get('rentabilidade', '0').replace('%', '').replace(',', '.').strip())
                    except (ValueError, AttributeError):
                        rentabilidade = 0
    
                    if not vencimento:
                        continue
    
                    try:
                        vencimento_data = datetime.strptime(vencimento, '%d/%m/%Y')
                    except ValueError:
                        try:
                            vencimento_data = datetime(int(vencimento), 1, 1)
                        except ValueError:
                            continue
    
                    titulo = Titulo(nome, vencimento, vencimento_data, rentabilidade)
    
                    if TipoTitulo.PREFIXADO in nome:
                        self.titulos_prefixados.append(titulo)
                    elif TipoTitulo.IPCA in nome:
                        self.titulos_ipca.append(titulo)
    
            except Exception as e:
                logger.error(f"Erro ao extrair dados do script: {e}")

    Código completo em:

  • 2 Para cada título prefixado, encontra o título IPCA+ com vencimento mais próximo
  • for item in api_data['response']['TrsrBdTradgList']:
        nome = item.get('TrsrBd', {}).get('nm', '')
        vencimento = item.get('TrsrBd', {}).get('mtrtyDt', '')
        taxa_str = item.get('TrsrBd', {}).get('anulInvstmtRate', '')
        if taxa_str or taxa_str == 0.0:
            taxa_str = item.get('TrsrBd', {}).get('anulRedRate', '')
    
        if not nome or not vencimento or taxa_str <= 0.0:
            continue
    
        try:
            taxa = float(taxa_str)
            vencimento_data = datetime.strptime(vencimento.split("T")[0], "%Y-%m-%d")
            vencimento_str = vencimento_data.strftime('%d/%m/%Y')
    
            titulo = Titulo(nome, vencimento_str, vencimento_data, taxa)
    
            if TipoTitulo.PREFIXADO in nome:
                self.titulos_prefixados.append(titulo)
            elif TipoTitulo.IPCA in nome:
                self.titulos_ipca.append(titulo)
        except (ValueError, TypeError) as e:
            logger.warning(f"Erro ao processar item da API: {e}")
            continue
    def calcular_comparativo(titulos_prefixados: List[Dict], titulos_ipca: List[Dict]) -> List[Dict]:
        """Calcula o comparativo entre títulos prefixados e IPCA+"""
        logger.info("Calculando comparativos entre títulos")
    
        resultados = []
    
        if not titulos_prefixados or not titulos_ipca:
            logger.warning("Não há dados suficientes para calcular o comparativo")
            return resultados
    
        # Ordenar títulos por data de vencimento
        titulos_prefixados.sort(key=lambda x: x["vencimento_data"])
        titulos_ipca.sort(key=lambda x: x["vencimento_data"])
    
        # Para cada título prefixado, encontrar o IPCA+ mais próximo em termos de vencimento
        for prefixado in titulos_prefixados:
            # Encontrar o IPCA+ mais próximo
            ipca_mais_proximo = None
            diferenca_minima = float('inf')
    
            for ipca in titulos_ipca:
                diferenca = abs((prefixado["vencimento_data"] - ipca["vencimento_data"]).days)
                if diferenca < diferenca_minima:
                    diferenca_minima = diferenca
                    ipca_mais_proximo = ipca
    
            if ipca_mais_proximo:
                # Calcular a inflação implícita
                prefixado_valor = 1 + (prefixado["rentabilidade"] / 100)
                ipca_valor = 1 + (ipca_mais_proximo["rentabilidade"] / 100)
                resultado = (prefixado_valor / ipca_valor) - 1
                resultado_percentual = resultado * 100
    
                # Criar objeto de resultado e converter para dicionário
                titulo_prefixado = Titulo(
                    prefixado["nome"],
                    prefixado["vencimento"],
                    prefixado["vencimento_data"],
                    prefixado["rentabilidade"]
                )
    
                titulo_ipca = Titulo(
                    ipca_mais_proximo["nome"],
                    ipca_mais_proximo["vencimento"],
                    ipca_mais_proximo["vencimento_data"],
                    ipca_mais_proximo["rentabilidade"]
                )
    
                comparativo = ResultadoComparativo(
                    titulo_prefixado,
                    titulo_ipca,
                    resultado_percentual
                )
    
                resultados.append(comparativo.to_dict())
    
        return resultados
    def exibir_resultados(resultados: List[Dict]) -> Optional[pd.DataFrame]:
        """Exibe os resultados da análise de inflação implícita"""
        if not resultados:
            logger.warning("Não foi possível calcular os resultados devido à falta de dados")
            return None
    
        # Converter para DataFrame
        df = pd.DataFrame(resultados)
    
        # Exibir cabeçalho
        display(Markdown("# ANÁLISE DE INFLAÇÃO IMPLÍCITA NO TESOURO DIRETO"))
    
        # Criar uma versão simplificada para exibição
        df_display = df[["Título Prefixado", "Taxa Prefixado (%)",
                         "Título IPCA+", "Taxa IPCA+ (%)",
                         "Inflação Implícita (%)"]]
    
        # print(tabulate(df_display, headers='keys', tablefmt='grid', showindex=False))
        html_table = df_display.to_html(index=False)
        display(HTML(html_table))
    
    
        # Exibir explicação e recomendação para cada par de títulos
        display(Markdown("# INTERPRETAÇÃO E RECOMENDAÇÃO"))
    
        for i, row in enumerate(resultados):
            display(Markdown(f"### Par {i+1}: {row['Título Prefixado']} vs {row['Título IPCA+']} \n"))
            display(Markdown(f"Inflação Implícita: **{row['Inflação Implícita (%)']:.2f}%**"))
            display(Markdown("O que significa: Este é o valor médio anual do IPCA até o vencimento"))
            display(Markdown("que o mercado está prevendo implicitamente."))
            display(Markdown(f"Recomendação: **{row['Recomendação']}**"))
            display(Markdown("<hr>"))
    
        # Explicação adicional
        display(Markdown("## EXPLICAÇÃO DETALHADA:"))
        ...

    Referencias

    Código completo em:




    Como calcular a inflação implícita e decidir o melhor Tesouro Direto em Python.