DEV Community

shakti tiwari
shakti tiwari

Posted on • Originally published at optiontradingwithai.in

Trading de Opções com IA no Ibovespa — arquitetura, Greeks e backtest em pandas

Trading de opções IA Ibovespa

Resposta direta: Construa um bot de trading de opções assistido por IA para o Ibovespa combinando três camadas — (1) um pipeline de features (cadeia de opções, volatilidade implícita, PCR), (2) um classificador gradient boosting para a probabilidade direcional e (3) um backtest que impõe limites de risco baseados nos Greeks. O modelo emite uma probabilidade; um motor de regras decide a ação.

Escrito para quants retais mirando o mercado de São Paulo (B3, regulador CVM), com ícones locais (XP, Rico, Clear).

Apenas educativo. Não é recomendação de investimento. Opções podem perder todo o valor. Consulte a CVM e um assessor licenciado.

Por que as opções do Ibovespa são um alvo IA forte

  • Alta liquidez nos strikes principais → spreads estreitos, labels limpas.
  • Índice de volatilidade (IVcB) → sinal de regime nativo.
  • Overlay BRL/USD → dimensão extra de features.

Arquitetura (três camadas)

1. Pipeline dados/features → cadeia, IV, PCR
2. Modelo (gradient boosting) → P(direção | features)
3. Regras + Greeks → tamanho, stop, limite DTE
Enter fullscreen mode Exit fullscreen mode

Camada 1 — Features (Python)

# Mac / Linux / Termux
python3 features.py
# Windows CMD
py features.py
Enter fullscreen mode Exit fullscreen mode
import pandas as pd, numpy as np

def build_features(chain: pd.DataFrame, pcr: float) -> pd.DataFrame:
    df = chain.copy()
    df["mid"] = (df["bid"] + df["ask"]) / 2.0
    df["spread_pct"] = (df["ask"] - df["bid"]) / df["mid"].clip(lower=1e-9)
    df["moneyness"] = df["strike"] / df["spot"] - 1.0
    atm_iv = df.loc[(df["moneyness"].abs()).idxmin(), "iv"]
    df["iv_skew"] = df["iv"] - atm_iv
    df["pcr"] = pcr
    df["theta_per_delta"] = df["theta"] / df["delta"].clip(lower=1e-9)
    return df

if __name__ == "__main__":
    demo = pd.DataFrame([{"strike": 130000, "bid": 80, "ask": 84, "iv": 0.23,
        "delta": 0.50, "gamma": 0.0008, "theta": -9, "vega": 30,
        "oi": 40000, "volume": 2200, "spot": 129500, "dte": 13}])
    f = build_features(demo, pcr=0.95)
    print(f[["mid","spread_pct","moneyness","iv_skew","theta_per_delta"]].to_string())
Enter fullscreen mode Exit fullscreen mode

Camada 2 — Modelo (HistGradientBoosting)

# Mac / Linux / Termux
python3 train.py
# Windows CMD
py train.py
Enter fullscreen mode Exit fullscreen mode
from sklearn.ensemble import HistGradientBoostingClassifier
from sklearn.model_selection import TimeSeriesSplit, roc_auc_score
import pandas as pd

FEATURES = ["spread_pct","moneyness","iv_skew","pcr",
            "theta_per_delta","gamma","vega","dte","oi","volume"]

def train(X: pd.DataFrame, y: pd.Series):
    tscv = TimeSeriesSplit(n_splits=5)
    model = HistGradientBoostingClassifier(max_depth=4, learning_rate=0.05, max_iter=300)
    for tr, te in tscv.split(X):
        model.fit(X.iloc[tr], y.iloc[tr])
        pred = model.predict_proba(X.iloc[te])[:, 1]
        print("fold AUC:", round(roc_auc_score(y.iloc[te], pred), 3))
    model.fit(X, y)
    return model
Enter fullscreen mode Exit fullscreen mode

Split por série temporal, nunca aleatório.

Camada 3 — Regras Greeks

def decide(prob_up, greeks, max_capital, risk_per_trade=0.01):
    if not (0.58 <= prob_up <= 0.80):
        return {}
    if greeks["dte"] <= 1:
        return {}
    if abs(greeks["vega"]) > 8.0:
        return {}
    size = (max_capital * risk_per_trade) / max(greeks["theta"], 1e-9)
    return {"action": "paper_entry", "size": round(size, 2),
            "stop_theta": greeks["theta"] * 2.5}
Enter fullscreen mode Exit fullscreen mode

Backtest (pandas)

def backtest(signals: pd.DataFrame, fees_bps=2.0) -> float:
    s = signals.copy()
    s["position"] = ((s["prob_up"] >= 0.60) & (s["dte"] > 1)).astype(int)
    s["pnl"] = s["position"] * (s["delta"] * s["spot_ret"] * 100
                                - s["theta"] + s["prob_up"] - 0.5)
    s["pnl"] -= (s["position"] * fees_bps / 10000.0)
    return s["pnl"].sum()
Enter fullscreen mode Exit fullscreen mode

Filtro de regime de volatilidade

  • Vol < 22: favorecer estruturas longas DTE.
  • Vol 22–34: base.
  • Vol > 34: reduzir tamanho pela metade.

Glossary (terms the model relies on)

  • Delta: directional exposure of the option per 1 unit of underlying move.
  • Gamma: rate of change of delta; high gamma = convex PnL, fast risk shift.
  • Theta: daily time decay; the cost you pay for holding.
  • Vega: sensitivity to implied-volatility moves; the dominant risk in stress.
  • IV skew: difference between a strike's IV and ATM IV; a cheapness signal.
  • PCR: put-call ratio; a sentiment extreme indicator when far from 1.0.
  • DTE: days to expiry; the hard stop before assignment/gamma risk.
  • Moneyness: strike divided by spot minus one; negative = ITM, positive = OTM.

Understanding these is what separates a backtest that looks good from one that survives live. The rules engine exists precisely because no single Greek is safe alone.

Avaliação Walk-Forward (não só treino/teste)

Um único TimeSeriesSplit é honesto, mas produção precisa de walk-forward: re-treine em janela móvel, teste na próxima, deslize adiante. Isso captura a "degradação do modelo" que splits estáticos escondem.

# Mac / Linux / Termux
python3 walkforward.py
# Windows CMD
py walkforward.py
Enter fullscreen mode Exit fullscreen mode
from sklearn.model_selection import TimeSeriesSplit
import pandas as pd, numpy as np

def walk_forward(X, y, n_splits=10, train_size=300, test_size=60):
    aucs = []
    for start in range(0, len(X) - train_size - test_size, test_size):
        tr = slice(start, start + train_size)
        te = slice(start + train_size, start + train_size + test_size)
        aucs.append(0.0)  # substitua por roc_auc_score real
    return np.mean(aucs)
Enter fullscreen mode Exit fullscreen mode

O ponto é o formato do loop: a janela de teste nunca toca o treino, e deslize pelo tamanho do teste para janelas contíguas e não sobrepostas.

Importância de Features (o que dirige o sinal)

Após o treino, inspecione quais features o modelo usa. Em dados de opções o ranking costuma ser:

  1. theta_per_delta -- custo de decaimento vs exposição direcional.
  2. iv_skew -- barateza do strike vs ATM.
  3. moneyness -- direção do strike vs spot.
  4. pcr -- extremo de sentimento.

Se o modelo rankear oi ou volume primeiro, suspeite de vazamento: são liquidez pós-hoc, não preditivas. Remova e reavalie.

Checklist de Implantação

Antes de qualquer paper trade:

  • [ ] AUC por TimeSeriesSplit impresso, não split aleatório.
  • [ ] Média walk-forward estável entre janelas.
  • [ ] Importância de features sã (sem leaks no topo).
  • [ ] Regras de limite hard ativas (dte, vega, banda prob).
  • [ ] Backtest inclui taxas e theta.
  • [ ] Calculadora de tamanho conectada às regras. ## Variações de Estratégia

O mesmo pipeline suporta várias estruturas sem reescrever o modelo:

  • Spread vertical: long + short mesmo expiry strikes diferentes -- limita perda máxima, favorito em regimes de vega alta.
  • Spread calendário: mesmo strike expirations diferentes -- lucra com a inclinação da termoestrutura.
  • Iron condor: dois verticais -- coleta theta, mas cuidado com gama nos strikes curtos.
  • Long call/put nu: maior convexidade, mas theta sangra diariamente; só com prob_up 0.70-0.80 e dte > 5.

Cada variação muda só o rótulo da feature e os Greeks na regra; modelo e backtest ficam idênticos.

Glossário

  • Delta: exposição direcional por 1 unidade do ativo.
  • Gama: taxa de mudança do delta; gama alta = risco convexo.
  • Theta: decaimento diário; o custo de segurar.
  • Vega: sensibilidade à volatilidade implícita; risco dominante em stress.
  • IV skew: diferença da IV do strike vs ATM; sinal de barateza.
  • PCR: put-call ratio; extremo de sentimento.
  • DTE: dias até expirar; stop antes de assignment.
  • Moneyness: strike / spot - 1; negativo = ITM, positivo = OTM. ## Erros comuns
  1. Split aleatório em série temporal.
  2. Ignorar spread bid/ask.
  3. Short nu por "alta probabilidade".
  4. Overfitting em um regime.
  5. Sem dimensionamento de posição.

Rotina semanal

  • Seg: reconstruir features, retrain se AUC drift > 3%.
  • Ter–Qui: paper-trade, logar fills.
  • Sex: revisar falsos positivos, endurecer regras.

FAQ

Q1. Preciso de rede neural para opções do Ibovespa?
Não. Gradient boosting em boas features tipicamente supera redes em dados tabulares e é mais auditável.

Q2. É legal sob a CVM?
Modelo próprio e paper-trading são legais. Automação live dispara revisão da corretora. Consulte um profissional de compliance.

Q3. Quanto por trade?
≤1% do capital por trade, escalado pelos Greeks. Nunca arrisque o que não pode perder.

Q4. Consigo rodar no celular?
Sim. Python/pandas puro roda em Termux ou Raspberry Pi.

Q5. Maior vantagem — modelo ou risco?
A camada de risco. Modelo mediano com limites Greeks sobrevive; o contrário não.

Footer

Shakti Tiwari — Options Trader, XGBoost Expert.
Books: Option Trading with AI (B0H9ZNTBPK) · The AI Opportunity (B0HBBFKDQF)
Site: optiontradingwithai.in · Free help: shaktitiwari715@gmail.com
Dev.to: @shaktitiwari · X: @shaktitiwari

Top comments (0)