Kaique Mitsuo Silva Yamamoto
CriptoTrading automatizado

VectorBT: Backtesting Ultrarrápido em Python

Como usar VectorBT para testar milhares de combinações de parâmetros em segundos, otimizar estratégias de trading em cripto e visualizar resultados com heatmaps e gráficos interativos.

VectorBT é a biblioteca Python mais rápida para backtesting de estratégias de trading. Enquanto frameworks tradicionais como Backtrader processam operações uma a uma (loop), VectorBT opera sobre arrays inteiros usando NumPy + Numba — alcançando velocidade próxima ao nível C.

  • GitHub: polakowo/vectorbt
  • Caso de uso ideal: otimização de parâmetros em larga escala (testar centenas ou milhares de combinações)
pip install vectorbt

Por que VectorBT é Diferente

AspectoBacktrader (loop)VectorBT (vetorizado)
Velocidade~1 combinação/s~1.000+ combinações/s
OtimizaçãoManual (loops externos)Nativa (broadcasting de arrays)
VisualizaçãoBásicaInterativa (Plotly)
Curva de aprendizadoFácilMédia
Casos de usoQualquer estratégiaEstratégias com parâmetros otimizáveis

Conceito Fundamental: Broadcasting

VectorBT testa múltiplos parâmetros simultaneamente passando arrays em vez de valores únicos:

import vectorbt as vbt
import numpy as np

# Dados: BTC últimos 2 anos
btc = vbt.YFData.download("BTC-USD", period="2y").get("Close")

# RSI com UM período (tradicional)
rsi_14 = vbt.RSI.run(btc, window=14)

# RSI com MÚLTIPLOS períodos (broadcasting)
rsi_multi = vbt.RSI.run(btc, window=[10, 14, 20, 30])
# → gera 4 séries de RSI ao mesmo tempo

Backtest Básico

import vectorbt as vbt

# Download de dados
btc = vbt.YFData.download("BTC-USD", period="2y").get("Close")

# Calcular RSI
rsi = vbt.RSI.run(btc, window=14)

# Definir sinais
entries = rsi.rsi_below(30)   # Compra quando RSI < 30
exits   = rsi.rsi_above(65)   # Vende quando RSI > 65

# Criar portfolio
portfolio = vbt.Portfolio.from_signals(
    btc,
    entries,
    exits,
    init_cash=10_000,
    fees=0.001,          # 0,1% por operação (Binance spot)
    slippage=0.0005,     # 0,05% de slippage
    freq='D'             # Frequência dos dados
)

# Resultado
print(portfolio.stats())

Saída de exemplo:

Start                         2023-01-01
End                           2024-12-31
Period                        730 days
Start Value                   10000.0
End Value                     13420.5
Total Return [%]              34.20
Annualized Return [%]         16.31
Benchmark Return [%]          89.40     ← Buy-and-hold
Max Drawdown [%]              -12.8
Win Rate [%]                  52.3
Profit Factor                 1.73
Sharpe Ratio                  1.44

Otimização de Parâmetros em Grade

O diferencial do VectorBT: testar todas as combinações de parâmetros com uma linha de código.

import vectorbt as vbt
import numpy as np

btc = vbt.YFData.download("BTC-USD", period="2y").get("Close")

# RSI com múltiplos períodos
rsi = vbt.RSI.run(btc, window=np.arange(10, 31, 2))   # 10, 12, 14...30 (11 valores)

# Múltiplos thresholds de entrada
entries = rsi.rsi_below(np.arange(25, 41, 5))   # 25, 30, 35, 40 (4 valores)
exits   = rsi.rsi_above(np.arange(60, 76, 5))   # 60, 65, 70, 75 (4 valores)

# 11 × 4 × 4 = 176 combinações testadas simultaneamente
portfolio = vbt.Portfolio.from_signals(
    btc, entries, exits,
    init_cash=10_000,
    fees=0.001,
    slippage=0.0005
)

# Heatmap de Profit Factor para cada combinação
# Eixo X: threshold de entrada; Eixo Y: período do RSI
pf = portfolio.profit_factor

# Selecionar apenas entradas (rsi_below) × período (window)
# (média sobre os thresholds de saída)
heatmap = pf.vbt.heatmap(
    x_level="rsi_below",
    y_level="rsi_window",
)
heatmap.show()

# Encontrar o melhor parâmetro
melhor_idx = pf.idxmax()
print(f"Melhor combinação: {melhor_idx}")
print(f"Profit Factor: {pf.max():.2f}")

Múltiplos Indicadores: MACD + RSI

import vectorbt as vbt
import pandas as pd

# Dados para 3 pares
pares = ["BTC-USD", "ETH-USD", "SOL-USD"]
dados = vbt.YFData.download(pares, period="2y").get("Close")

# MACD para todos os pares
macd = vbt.MACD.run(dados, fast_window=12, slow_window=26, signal_window=9)

# RSI para todos os pares
rsi = vbt.RSI.run(dados, window=14)

# Sinal combinado: MACD crossover + RSI saudável
entries = (
    macd.macd_above(macd.signal) &    # MACD acima da linha de sinal
    rsi.rsi_below(60)                  # RSI não sobrecomprado
)
exits = (
    macd.macd_below(macd.signal) |    # MACD abaixo da linha de sinal
    rsi.rsi_above(70)                  # RSI sobrecomprado
)

portfolio = vbt.Portfolio.from_signals(
    dados, entries, exits,
    init_cash=10_000,
    fees=0.001
)

# Estatísticas por par
print(portfolio.stats(agg_func=None))   # Sem agregação → por par

Visualização Interativa

# Plotar o portfolio com gráfico interativo (Plotly)
portfolio.plot().show()

# Gráfico de drawdown ao longo do tempo
portfolio.drawdown().plot().show()

# Retorno cumulativo
portfolio.cumulative_returns.plot().show()

# Ordens executadas no gráfico de preço
portfolio.orders.plot().show()

# Relatório completo em HTML (útil para documentar)
portfolio.plot().write_html("resultado_backtest.html")

Walk-Forward Analysis com VectorBT

import vectorbt as vbt
import pandas as pd
import numpy as np

btc = vbt.YFData.download("BTC-USD", period="3y").get("Close")

# Dividir em janelas de 90 dias (treino) + 30 dias (validação)
n_janelas = 8
resultados = []

for i in range(n_janelas):
    inicio_treino = i * 30
    fim_treino    = inicio_treino + 90
    inicio_val    = fim_treino
    fim_val       = inicio_val + 30

    if fim_val > len(btc):
        break

    treino    = btc.iloc[inicio_treino:fim_treino]
    validacao = btc.iloc[inicio_val:fim_val]

    # Otimizar no treino
    rsi_treino = vbt.RSI.run(treino, window=np.arange(10, 25))
    ent = rsi_treino.rsi_below(np.arange(25, 40, 5))
    sai = rsi_treino.rsi_above(65)
    pf_treino = vbt.Portfolio.from_signals(treino, ent, sai, fees=0.001)
    melhor_window = int(pf_treino.profit_factor.idxmax()['rsi_window'])
    melhor_below  = int(pf_treino.profit_factor.idxmax()['rsi_below'])

    # Validar com os melhores parâmetros
    rsi_val = vbt.RSI.run(validacao, window=melhor_window)
    ent_val = rsi_val.rsi_below(melhor_below)
    sai_val = rsi_val.rsi_above(65)
    pf_val = vbt.Portfolio.from_signals(validacao, ent_val, sai_val, fees=0.001)

    resultados.append({
        'janela': i + 1,
        'window': melhor_window,
        'below': melhor_below,
        'retorno_validacao': float(pf_val.total_return)
    })

df_wf = pd.DataFrame(resultados)
print(df_wf)
print(f"\nRetorno médio na validação: {df_wf['retorno_validacao'].mean():.2%}")

VectorBT vs Freqtrade: Quando Usar Cada Um

CritérioVectorBTFreqtrade
Otimização em escalaMuito melhor (broadcasting)OK (Hyperopt)
Deploy em produçãoNão (só backtesting)Sim (bot completo)
Machine LearningManual (sklearn externo)Nativo (FreqAI)
FacilidadeMédia (requer pandas/numpy)Alta (framework pronto)
Velocidade de backtestExcelenteBoa
Múltiplos paresSim (nativo)Sim
VisualizaçãoInterativa (Plotly)Básica

Workflow recomendado:

1. VectorBT → Encontrar os melhores parâmetros em grande escala
2. Freqtrade → Implementar a estratégia otimizada para produção
3. Paper trading → 30-90 dias
4. Produção → Capital real pequeno, escale gradualmente

Próximos Passos


Aviso Legal: Conteúdo educativo. Resultados de backtesting não garantem performance futura. Não constitui recomendação de investimento.

On this page