Kaique Mitsuo Silva Yamamoto
CriptoTrading automatizado

Como Fazer Backtesting Rigoroso em Cripto

Guia completo de backtesting para estratégias de trading em cripto: metodologia, métricas essenciais, armadilhas de overfitting, walk-forward analysis e ferramentas (TradingView, VectorBT, Freqtrade, Backtrader).

Backtesting é simular sua estratégia em dados históricos para entender como ela teria se saído no passado. É o passo mais crítico antes de colocar capital real em qualquer bot — e o mais frequentemente feito de forma errada.

Regra de ouro: uma estratégia que não passou no backtesting nunca deve operar com capital real. Uma estratégia que passou no backtesting ainda precisa de paper trading antes do capital real.


Por que Backtesting Mal Feito é Perigoso

Os erros mais comuns que fazem um backtest parecer lucrativo quando não é:

ErroImpactoSolução
Sem taxasSuperestima lucro em 10-40%Inclua maker/taker/slippage
Look-ahead biasUsa dados do futuro para decidirVerifique que indicadores usam apenas close passado
OverfittingOtimizado para o passado, falha no futuroValide em dados out-of-sample
Período únicoFunciona só em bull marketTeste em múltiplos ciclos (bull + bear + lateral)
Execução perfeitaAssume que ordens são sempre preenchidasAdicione slippage e simule rejeições
Dados ruinsGaps, dados incorretos, survivorship biasUse feeds de dados verificados

Metodologia de Backtesting em 5 Etapas

Etapa 1: Hipótese Clara

Antes de codificar, defina:

  • O que a estratégia faz? (ex: "compra quando RSI < 30 e fecha quando RSI > 60")
  • Por que deveria funcionar? (lógica de mercado, não apenas fit histórico)
  • Em que condições de mercado? (lateral, tendência, alta volatilidade)

Etapa 2: Separar Dados de Treinamento e Validação

Dados totais disponíveis: 4 anos de dados (2021-2024)

├── Treinamento (70%): 2021-2023
│   └── Aqui você otimiza os parâmetros

└── Validação / Out-of-Sample (30%): 2024
    └── Aqui você testa sem tocar nos parâmetros

Se a estratégia funciona bem no treinamento mas mal na validação → está overfitted.

Etapa 3: Incluir Custos Reais

ExchangeParMakerTakerSlippage típico
BinanceBTC/USDT Spot0,10%0,10%0,05%
BinanceBTCUSDT Perp0,02%0,05%0,03%
BybitBTC/USDT Spot0,10%0,10%0,05%
BybitBTCUSDT Perp (maker)0,02%0,05%0,03%
OKXBTCUSDT Perp0,02%0,05%0,03%

Etapa 4: Walk-Forward Analysis

Em vez de otimizar em todo o histórico de uma vez, otimize em janelas deslizantes:

Janela 1: Treina em Jan-Jun 2022 → Valida em Jul-Sep 2022
Janela 2: Treina em Apr-Sep 2022 → Valida em Out-Dez 2022
Janela 3: Treina em Jul-Dez 2022 → Valida em Jan-Mar 2023
...

Se os parâmetros ótimos variam muito entre janelas → estratégia é instável.

Etapa 5: Paper Trading (Simulação ao Vivo)

Antes do capital real, rode a estratégia em tempo real mas com capital fictício:

  • Duração mínima: 30-90 dias
  • Volume: pelo menos 50 operações para ter significância estatística
  • Se o performance ao vivo divergir muito do backtest → revise o modelo

Ferramentas de Backtesting

1. TradingView Strategy Tester (Pine Script)

Prós: mais fácil, visual, sem instalação, dados históricos de alta qualidade Contras: limitado a estratégias simples, sem flexibilidade para lógica complexa

//@version=5
strategy("Backtest Simples", initial_capital=10000,
         commission_type=strategy.commission.percent, commission_value=0.1,
         slippage=2)

rsi = ta.rsi(close, 14)
ema200 = ta.ema(close, 200)

if rsi < 30 and close > ema200
    strategy.entry("Long", strategy.long)

if rsi > 65
    strategy.close("Long")

Veja os resultados em Strategy Tester > Performance Summary.

Métricas mais importantes no TradingView:

  • Net Profit
  • Profit Factor
  • Max Drawdown
  • Total Closed Trades (mínimo: 30-50 trades)
  • Percent Profitable

2. VectorBT (Python) — O Mais Rápido

Por que usar: testa milhares de combinações de parâmetros em segundos, usando NumPy + Numba para performance de nível C.

pip install vectorbt
import vectorbt as vbt
import pandas as pd

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

# RSI com vectorbt
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 e calcular resultado
portfolio = vbt.Portfolio.from_signals(
    btc,
    entries,
    exits,
    init_cash=10_000,
    fees=0.001,        # 0,1% por operação
    slippage=0.0005    # 0,05% de slippage
)

# Métricas
print(portfolio.stats())
portfolio.plot().show()

Otimização de parâmetros em grade:

# Testar todas as combinações de RSI (10 a 20) e threshold (25 a 35)
rsi = vbt.RSI.run(btc, window=vbt.Default(range(10, 21)))

entries = rsi.rsi_below(vbt.Default(range(25, 36)))
exits   = rsi.rsi_above(65)

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

# Heatmap de profit factor por combinação
portfolio.profit_factor.vbt.heatmap(
    x_level="rsi_above", y_level="rsi_below"
).show()

3. Freqtrade — Bot + Backtesting Completo

O Freqtrade é um framework open-source que inclui bot, backtesting, otimização e paper trading — tudo integrado.

pip install freqtrade
freqtrade create-userdir --userdir user_data

Criar estratégia:

# user_data/strategies/RSIStrategy.py
from freqtrade.strategy import IStrategy
import talib.abstract as ta
import pandas as pd

class RSIStrategy(IStrategy):
    timeframe = '1h'
    stoploss  = -0.05    # Stop de 5%
    roi = {"0": 0.10}    # Take profit de 10%

    def populate_indicators(self, dataframe: pd.DataFrame, metadata: dict):
        dataframe['rsi']    = ta.RSI(dataframe, timeperiod=14)
        dataframe['ema200'] = ta.EMA(dataframe, timeperiod=200)
        return dataframe

    def populate_entry_trend(self, dataframe, metadata):
        dataframe.loc[
            (dataframe['rsi'] < 30) &
            (dataframe['close'] > dataframe['ema200']),
            'enter_long'
        ] = 1
        return dataframe

    def populate_exit_trend(self, dataframe, metadata):
        dataframe.loc[
            dataframe['rsi'] > 65,
            'exit_long'
        ] = 1
        return dataframe

Rodar backtesting:

freqtrade backtesting \
  --strategy RSIStrategy \
  --timeframe 1h \
  --timerange 20220101-20231231 \
  --fee 0.001

Resultado gerado automaticamente:

BACKTESTING REPORT
------------------
Pair       | Trades | Win% | Profit | Drawdown
BTCUSDT    |   87   | 54%  | 23.4%  | -8.2%
ETHUSDT    |   92   | 51%  | 18.7%  | -9.1%
Total      |  179   | 52%  | 21.1%  | -9.8%

Otimização com Hyperopt:

freqtrade hyperopt \
  --strategy RSIStrategy \
  --hyperopt-loss SharpeHyperOptLoss \
  --epochs 200 \
  --timeframe 1h

4. Backtrader — Clássico e Flexível

pip install backtrader
import backtrader as bt

class RSIStrategy(bt.Strategy):
    params = dict(rsi_period=14, rsi_oversold=30, rsi_overbought=65)

    def __init__(self):
        self.rsi = bt.indicators.RSI(period=self.p.rsi_period)

    def next(self):
        if self.rsi < self.p.rsi_oversold and not self.position:
            self.buy()
        elif self.rsi > self.p.rsi_overbought and self.position:
            self.sell()

cerebro = bt.Cerebro()
cerebro.addstrategy(RSIStrategy)
cerebro.broker.setcash(10000)
cerebro.broker.setcommission(commission=0.001)

# Adicionar dados (ex: CSV da Binance)
data = bt.feeds.GenericCSVData(dataname='btcusdt_1h.csv',
                               dtformat='%Y-%m-%d %H:%M:%S',
                               datetime=0, open=1, high=2, low=3, close=4, volume=5)
cerebro.adddata(data)
cerebro.run()
cerebro.plot()

Métricas Essenciais para Avaliar uma Estratégia

MétricaFórmula / DefiniçãoReferência Mínima
Net ProfitLucro total no períodoPositivo
Win RateTrades vencedores / total> 40% (depende do payoff)
Profit FactorGanhos brutos / Perdas brutas> 1,5
Max DrawdownMaior queda de pico a vale< 20%
Sharpe Ratio(Retorno - RF) / Volatilidade> 1,0
Sortino RatioSimilar ao Sharpe, só downside risk> 1,5
Avg Trade DurationTempo médio por operaçãoDepende da estratégia
Recovery FactorNet Profit / Max Drawdown> 3

O payoff importa tanto quanto o win rate:

Estratégia A: 60% win rate, lucro médio = US$50, perda média = US$150
Expectativa = (0,60 × 50) - (0,40 × 150) = 30 - 60 = -US$30 por trade ✗

Estratégia B: 40% win rate, lucro médio = US$200, perda média = US$80
Expectativa = (0,40 × 200) - (0,60 × 80) = 80 - 48 = +US$32 por trade ✓

Próximos Passos


Aviso Legal: Conteúdo educativo. Performance passada não é garantia de resultado futuro. Não constitui recomendação de investimento.

On this page