GaiaEx AcademyGaiaEx Academy
Análise de Dados com Pandas, NumPy e Matplotlib
DesenvolvedorProgramação12 min read

Análise de Dados com Pandas, NumPy e Matplotlib

Limpando, transformando e visualizando dados financeiros como um quant

Compartilhar Posts

NumPy: O Motor Por Baixo do Capô

Toda computação financeira séria em Python, no fim das contas, roda através do NumPy. Enquanto listas em Python são flexíveis, elas são lentas — cada elemento é um objeto Python completo com sobrecarga de verificação de tipo. Os arrays do NumPy armazenam números brutos em blocos de memória contíguos, permitindo operações que rodam 100x mais rápido do que loops em Python puro.

Aqui está a diferença na prática:

import numpy as np

# Create an array of 1 million random daily returns
returns = np.random.normal(0.0005, 0.02, 1_000_000)

# Vectorized operations — no loops needed
cumulative = np.cumprod(1 + returns)  # Growth of $1
sharpe = returns.mean() / returns.std() * np.sqrt(252)
max_drawdown = np.min(cumulative / np.maximum.accumulate(cumulative) - 1)

print(f"Sharpe Ratio: {sharpe:.3f}")
print(f"Max Drawdown: {max_drawdown:.2%}")

Conceitos-chave do NumPy para finanças:

  • Operações vetorizadas — aplique matemática a arrays inteiros de uma vez em vez de percorrer elemento por elemento.
  • Broadcasting — alinha automaticamente arrays de formatos diferentes para operações aritméticas (ex.: subtrair uma média escalar de cada elemento).
  • Álgebra linearnp.linalg fornece multiplicação de matrizes, decomposição em autovalores, e solucionadores usados na otimização de portfólio.
  • Amostragem aleatória — simulações de Monte Carlo, amostragem bootstrap, e modelagem estocástica todas dependem de np.random.

Dica de desempenho: sempre prefira operações vetorizadas do NumPy em vez de loops for em Python. Uma otimização de portfólio sobre 500 ativos que leva 30 segundos com loops pode terminar em menos de 50 milissegundos com NumPy vetorizado — uma aceleração de 600x.

NumPy: contiguous memory + vectorized ops ndarray — dtype, shape, strides (C-contiguous) one loop in C/Fortran, not a million Python bytecode steps broadcasting: align shapes for element-wise math e.g. returns vector − scalar mean, or (n,) with (n, m) matrix rows linalg: cov, eig, solve — portfolio math lives here
Arrays são o caminho rápido; broadcasting é como você mantém o código legível sem loops.

Pandas: DataFrames para Dados Financeiros

Se o NumPy é o motor, o pandas é o painel de controle. Ele envolve arrays do NumPy em estruturas rotuladas e indexadas que tornam a manipulação de dados financeiros intuitiva e expressiva.

As duas estruturas centrais são:

  • Series — uma única coluna de dados com um índice (pense: uma série temporal de preços de fechamento).
  • DataFrame — uma tabela de colunas, cada uma uma Series, compartilhando um índice comum (pense: dados de candlestick OHLCV).

Carregar e inspecionar dados é direto:

import pandas as pd

# Read from CSV
df = pd.read_csv("btc_daily.csv", parse_dates=["date"], index_col="date")

# Or from JSON (common in API responses)
df = pd.read_json("https://api.example.com/candles?symbol=ETH")

# Quick inspection
print(df.shape)          # (365, 5)
print(df.dtypes)         # Column types
print(df.describe())     # Statistical summary
print(df.tail())         # Last 5 rows

O que torna o pandas indispensável para finanças é seu DatetimeIndex. Uma vez que seu índice é do tipo datetime, você desbloqueia operações poderosas de série temporal:

# Slice by date range
q1_data = df["2025-01":"2025-03"]

# Resample daily data to weekly OHLC
weekly = df["close"].resample("W").ohlc()

# Forward-fill missing data (weekends, holidays)
df = df.asfreq("D").ffill()

Essas operações lidam com as realidades confusas dos dados financeiros — lacunas, diferenças de fuso horário, timestamps irregulares — para que você possa focar na análise em vez do encanamento de dados.

Cálculos Rolling: Médias Móveis e Volatilidade

A análise financeira é inerentemente por janela. Você raramente se importa com um único ponto de dado isoladamente — o contexto vem de como ele se relaciona com o histórico recente. O método .rolling() do pandas é sua ferramenta principal aqui.

import pandas as pd
import numpy as np

# Assume df has a "close" column with DatetimeIndex
df["sma_20"] = df["close"].rolling(20).mean()
df["sma_50"] = df["close"].rolling(50).mean()
df["ema_12"] = df["close"].ewm(span=12).mean()

# Daily returns and rolling volatility
df["returns"] = df["close"].pct_change()
df["vol_30d"] = df["returns"].rolling(30).std() * np.sqrt(365)

# Bollinger Bands
df["bb_upper"] = df["sma_20"] + 2 * df["close"].rolling(20).std()
df["bb_lower"] = df["sma_20"] - 2 * df["close"].rolling(20).std()

# Rolling correlation between two assets
df["corr_btc_eth"] = df["btc_returns"].rolling(60).corr(df["eth_returns"])

Cálculos rolling chave que todo trader deveria conhecer:

  • Média Móvel Simple (SMA) — média com peso igual sobre N períodos. Atrasada mas estável.
  • Média Móvel Exponencial (EMA) — pesa dados recentes mais fortemente via .ewm(). Mais responsiva a mudanças de preço.
  • Volatilidade Rolling — desvio padrão dos retornos sobre uma janela, anualizado. Essencial para dimensionamento de posição e orçamentos de risco.
  • Correlação Rolling — mede como dois ativos se movem juntos ao longo do tempo. Crítico para a diversificação de portfólio.

Em plataformas como a GaiaEx, você pode extrair dados históricos de candles através da API de trading, carregá-los em um DataFrame do pandas, e calcular esses indicadores em segundos — tudo enquanto seus ativos permanecem seguros na sua carteira MPC.

GroupBy e Agregação para Análise de Portfólio

Quando você está gerenciando múltiplos ativos, .groupby() se torna essencial. Ele permite que você divida dados por categoria, aplique cálculos, e combine resultados — o padrão split-apply-combine.

# DataFrame with multiple assets
trades = pd.DataFrame({
    "symbol": ["BTC", "ETH", "BTC", "SOL", "ETH", "BTC"],
    "side": ["buy", "buy", "sell", "buy", "sell", "buy"],
    "pnl": [120.5, -45.2, 89.0, 210.3, 55.8, -30.1],
    "volume": [5000, 3200, 4800, 1500, 2900, 5100],
})

# Performance by asset
summary = trades.groupby("symbol").agg(
    total_pnl=("pnl", "sum"),
    avg_pnl=("pnl", "mean"),
    trade_count=("pnl", "count"),
    total_volume=("volume", "sum"),
    win_rate=("pnl", lambda x: (x > 0).mean()),
)

print(summary.sort_values("total_pnl", ascending=False))

Padrões avançados de agregação para trabalho de portfólio:

  • GroupBy multinível — agrupe por símbolo e lado para ver o desempenho de comprado vs. vendido por ativo.
  • Funções de agregação personalizadas — calcule índices de Sharpe, índices de Sortino, ou drawdown máximo por grupo de ativo.
  • Tabelas pivot — reformate dados para ver retornos mensais por ativo em um formato amigável a heatmap usando pd.pivot_table().
  • Resampling com groupby — combine o resampling baseado em tempo com agrupamento categórico para análise de série temporal multi-ativo.

Matplotlib: Gráficos de Ação de Preço e Sinais

Dados sem visualização são apenas números. O Matplotlib transforma sua análise em gráficos que revelam padrões invisíveis nos dados brutos.

import matplotlib.pyplot as plt
import matplotlib.dates as mdates

fig, axes = plt.subplots(3, 1, figsize=(14, 10),
                         sharex=True, gridspec_kw={"height_ratios": [3, 1, 1]})

# Price + Moving Averages
axes[0].plot(df.index, df["close"], label="Close", linewidth=1.2)
axes[0].plot(df.index, df["sma_20"], label="SMA 20", linestyle="--")
axes[0].fill_between(df.index, df["bb_upper"], df["bb_lower"],
                     alpha=0.1, color="blue", label="Bollinger Bands")
axes[0].set_ylabel("Price (USD)")
axes[0].legend(loc="upper left")

# Volume bars
colors = ["green" if c > o else "red"
          for c, o in zip(df["close"], df["open"])]
axes[1].bar(df.index, df["volume"], color=colors, alpha=0.7)
axes[1].set_ylabel("Volume")

# Rolling Volatility
axes[2].plot(df.index, df["vol_30d"], color="purple")
axes[2].set_ylabel("30d Volatility")
axes[2].axhline(y=0.8, color="red", linestyle=":", alpha=0.5)

axes[2].xaxis.set_major_formatter(mdates.DateFormatter("%b %Y"))
plt.tight_layout()
plt.savefig("analysis_dashboard.png", dpi=150)
plt.show()

Isso produz um dashboard profissional de três painéis: ação de preço com Bandas de Bollinger no topo, volume no meio, e volatilidade na parte inferior. Esse layout espelha o que você veria em terminais de negociação profissionais.

Para visualização estatística, o seaborn constrói sobre o Matplotlib com funções de mais alto nível:

import seaborn as sns

# Return distribution
sns.histplot(df["returns"].dropna(), bins=100, kde=True)

# Correlation heatmap across assets
corr_matrix = portfolio_returns.corr()
sns.heatmap(corr_matrix, annot=True, cmap="RdYlGn", center=0)
Pandas → analysis; Matplotlib → insight DataFrame index + columns rolling resample groupby Series metrics returns, vol, Sharpe matplotlib.pyplot — figure, axes, artists price volume indicators seaborn optional — same Artist layer, prettier defaults
O pandas prepara tabelas organizadas; o Matplotlib as mapeia para eixos que você pode anotar e compartilhar.

Juntando Tudo: Um Pipeline de Análise Completo

O verdadeiro poder emerge quando você encadeia essas ferramentas em um pipeline repetível. Aqui está um fluxo de trabalho que quants profissionais usam diariamente:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

def analyze_asset(symbol: str, df: pd.DataFrame) -> dict:
    """Full analysis pipeline for a single asset."""
    df["returns"] = df["close"].pct_change()
    df["log_returns"] = np.log(df["close"] / df["close"].shift(1))

    return {
        "symbol": symbol,
        "total_return": (df["close"].iloc[-1] / df["close"].iloc[0]) - 1,
        "annual_vol": df["returns"].std() * np.sqrt(365),
        "sharpe": df["returns"].mean() / df["returns"].std() * np.sqrt(365),
        "max_drawdown": (df["close"] / df["close"].cummax() - 1).min(),
        "skewness": df["returns"].skew(),
        "kurtosis": df["returns"].kurtosis(),
    }

# Analyze multiple assets
results = [analyze_asset(sym, data) for sym, data in assets.items()]
summary = pd.DataFrame(results).set_index("symbol")
print(summary.round(4))

Esse pipeline pega dados brutos de preço e produz um perfil completo de risco-retorno para cada ativo. A partir daqui, você pode alimentar essas métricas em um otimizador de portfólio, gerar recomendações de alocação, ou disparar sinais de rebalanceamento.

A pilha pandas-NumPy-Matplotlib é a fundação sobre a qual tudo o mais em Python financeiro se constrói. Domine essas três bibliotecas e você terá as habilidades para analisar qualquer mercado, construir qualquer indicador, e visualizar qualquer estratégia — seja negociando ações na NYSE, cripto na GaiaEx, ou derivativos na CME.