Backtesting em Python

Um backtest mínimo de cruzamento de médias móveis

6 min

Vamos transformar a ideia do cruzamento de SMAs em um backtest vetorizado pequeno e autocontido usando só pandas e NumPy. Isto mostra a lógica; um framework real adiciona tratamento de ordens e relatórios apropriados.

A estratégia

Fique comprado quando a média móvel rápida está acima da lenta; fique de fora caso contrário. Uma posição apenas comprada, tudo ou nada.

import numpy as np
import pandas as pd

def backtest_sma(df, fast=20, slow=50, cost_bps=2):
    px = df["close"]
    sma_fast = px.rolling(fast).mean()
    sma_slow = px.rolling(slow).mean()

    # Signal: 1 when fast above slow, else 0
    signal = (sma_fast > sma_slow).astype(int)

    # CRITICAL: trade on the NEXT bar to avoid look-ahead
    position = signal.shift(1).fillna(0)

    # Costs charged when the position changes
    trades = position.diff().abs().fillna(0)
    cost = trades * (cost_bps / 10000.0)

    ret = px.pct_change().fillna(0)
    strat_ret = position * ret - cost
    equity = (1 + strat_ret).cumprod()
    return equity, strat_ret

A linha mais importante de todas

position = signal.shift(1).fillna(0)

O shift(1) é tudo. O sinal é calculado a partir do fechamento de uma barra, mas você não pode agir sobre ele até a barra seguinte abrir. Sem esse shift você está operando com informação que ainda não tinha — viés de look-ahead instantâneo e um backtest que parece mágico e não vale nada.

Lendo o resultado

equity, r = backtest_sma(df)
sharpe = np.sqrt(252) * r.mean() / r.std()
print("final equity:", round(equity.iloc[-1], 3))
print("approx Sharpe:", round(sharpe, 2))

Ressalvas honestas

Isto omite slippage além do custo fixo, assume que você sempre executa no fechamento, ignora dimensionamento de posição e venda a descoberto, e usa um único instrumento e período. É um esqueleto didático. Qualquer curva de capital que ele produza é hipotética — trate-a como ponto de partida para os testes rigorosos do resto desta trilha, não como um resultado em que confiar.

Terminou de ler?
Aviso de risco

Este conteúdo tem finalidade exclusivamente educacional e informativa e não constitui recomendação de investimento, consultoria financeira, tributária ou jurídica. Operar e investir envolvem risco, incluindo a possível perda de capital. Qualquer desempenho exibido por ferramentas de terceiros é hipotético e não promessa de resultado futuro. Faça sua própria análise e considere orientação profissional antes de qualquer decisão.