ETL Tickers Financeiros

Python · yfinance · PostgreSQL · dbt · Pandas

Python yfinance PostgreSQL dbt Pandas SQLAlchemy

Descrição do Projeto

Pipeline ETL para coleta de dados históricos de ações de bancos brasileiros através da API yfinance, com processamento e armazenamento em PostgreSQL e transformações orquestradas via dbt (Data Build Tool).

O projeto se divide em três partes: coleta de dados históricos de fechamento de ações (ITUB, BBDC4, BBAS3, SANB11), processamento e carga no banco relacional, e camada de transformação com dbt para preparar os dados para análises e visualizações.

Arquitetura do Pipeline

┌──────────────────────┐
│    yfinance API      │
│  Dados de ações B3   │
│  · ITUB  · BBDC4     │
│  · BBAS3 · SANB11    │
└──────────┬───────────┘
           │ Python + yfinance
           ▼
┌──────────────────────┐
│   Processamento      │
│  · Pandas DataFrame  │
│  · Limpeza e formato │
│  · SQLAlchemy Engine │
└──────────┬───────────┘
           │ INSERT / UPSERT
           ▼
┌──────────────────────┐
│     PostgreSQL       │
│  Tabela raw:         │
│  · tickers_historico │
└──────────┬───────────┘
           │ dbt run
           ▼
┌──────────────────────┐
│        dbt           │
│  · staging           │
│  · analytics         │
│  · testes e docs     │
└──────────┬───────────┘
           │
           ▼
┌──────────────────────┐
│   Análises e BI      │
│  PostgreSQL queries  │
└──────────────────────┘

Fluxo de Dados

  1. Coleta: Python + yfinance baixa dados históricos de fechamento dos tickers
  2. Processamento: Pandas organiza os dados em DataFrame com colunas padronizadas
  3. Carga: SQLAlchemy insere os dados na tabela raw do PostgreSQL
  4. Transformação: dbt aplica camadas staging e analytics com modelos SQL

Stack Tecnológica

Linguagem & Bibliotecas

  • Python 3.8+
  • yfinance — API de dados financeiros
  • Pandas — manipulação de dados
  • SQLAlchemy — ORM e conexão DB

Banco de Dados

  • PostgreSQL
  • Tabelas raw e analytics
  • Schemas separados por camada

Transformação

  • dbt (Data Build Tool)
  • Modelos staging e analytics
  • Testes de qualidade de dados
  • Documentação automatizada

Tickers Monitorados

  • ITUB — Itaú Unibanco
  • BBDC4 — Bradesco
  • BBAS3 — Banco do Brasil
  • SANB11 — Santander

Exemplos de Código

Coleta de Dados com yfinance

import yfinance as yf
import pandas as pd
from sqlalchemy import create_engine
from datetime import datetime

# Tickers dos principais bancos brasileiros
TICKERS = ['ITUB', 'BBDC4', 'BBAS3', 'SANB11']

# Adicionar sufixo .SA para B3
tickers_sa = [f'{t}.SA' for t in TICKERS]

# Baixar dados históricos (últimos 2 anos)
df = yf.download(
    tickers_sa,
    period='2y',
    interval='1d'
)

# Processar e formatar para PostgreSQL
df_clean = df.stack(level=0).reset_index()
df_clean.columns = ['data', 'ticker', 'open', 'high',
                    'low', 'close', 'adj_close', 'volume']

# Conectar ao PostgreSQL e inserir
engine = create_engine(os.getenv('DATABASE_URL'))
df_clean.to_sql('raw_tickers', engine, if_exists='append', index=False)

Modelo dbt — staging

-- models/staging/stg_tickers.sql
{{ config(materialized='view') }}

SELECT
    data,
    ticker,
    CAST(open AS DECIMAL(10,2)) AS preco_abertura,
    CAST(high AS DECIMAL(10,2)) AS preco_maximo,
    CAST(low AS DECIMAL(10,2)) AS preco_minimo,
    CAST(close AS DECIMAL(10,2)) AS preco_fechamento,
    volume AS volume_negociado
FROM {{ source('raw', 'raw_tickers') }}
WHERE close > 0
  AND data >= '2022-01-01'

Modelo dbt — analytics

-- models/analytics/metricas_diarias.sql
{{ config(materialized='table') }}

SELECT
    data,
    ticker,
    preco_fechamento,
    LAG(preco_fechamento) OVER (
        PARTITION BY ticker ORDER BY data
    ) AS fechamento_anterior,
    ROUND(
        (preco_fechamento - LAG(preco_fechamento) OVER (
            PARTITION BY ticker ORDER BY data
        )) / NULLIF(LAG(preco_fechamento) OVER (
            PARTITION BY ticker ORDER BY data
        ), 0) * 100, 2
    ) AS variacao_pct,
    volume_negociado
FROM {{ ref('stg_tickers') }}
ORDER BY data DESC, ticker

Desafios e Soluções

1. Dados da B3 com sufixo .SA

Desafio: Tickers brasileiros na yfinance exigem o sufixo .SA, gerando confusão no mapeamento.

Solução: Função de mapeamento automático que adiciona o sufixo e mantém o ticker original na tabela.

2. Volumetria de dados históricos

Desafio: 2 anos de dados diários para 4 tickers gera milhares de registros.

Solução: Lógica de upsert com controle de data para evitar duplicação e permitir execuções incrementais.

3. Qualidade e consistência

Desafio: Dados zerados ou nulos em feriados e fins de semana.

Solução: Filtros no modelo staging do dbt removem registros com close = 0 e datas inválidas.

Resultados

4

Tickers Monitorados

2 anos

Histórico Coletado

dbt

Transformações SQL

Entregáveis

Aprendizados