Pular para conteúdo

Debug de Modelos

Como investigar problemas comuns.

Modelo está retornando sempre NO_TRADE

Causa 1: confiança baixa

# Verificar manualmente
docker exec forex_worker python -c "
import joblib, json
from app.models.predict import load_champion, predict
m = load_champion('EURUSD', 'H1')
print(m.predict_proba(X)[-5:])
"

Se probs estão tipo [0.33, 0.32, 0.35] (próximas de 1/3) — modelo está incerto. Razões:

  • Features ruidosas/quebradas
  • Mercado em range (modelo treinado em trend)
  • Dataset desbalanceado

Causa 2: conformal filtrando tudo

# configs/model.yaml
training:
  conformal_alpha: 0.15   # 85% cobertura

Se α muito baixo (ex: 0.05 = 95% cobertura) → muitos NO_TRADE.

Teste:

# Aumenta temporariamente e ver diferença
conformal_alpha: 0.25   # cobertura 75% — mais sinais, mas menos confiáveis

Causa 3: regime mismatch

Modelo foi treinado em regime A, mercado está em B.

# Ver distribution
docker exec forex_db psql -U forex -d forex -c "
  SELECT regime, COUNT(*) FROM predictions
  WHERE symbol_id = (SELECT symbol_id FROM symbols WHERE symbol='EURUSD')
    AND created_at >= NOW() - INTERVAL '7 days'
  GROUP BY regime;"

Modelo não está sendo carregado

Sintoma: log diz "modelo não encontrado" ou /api/scan ignora ativo.

# Listar champions ativos no DB
docker exec forex_db psql -U forex -d forex -c "
  SELECT s.symbol, t.tf_code, mr.model_v, mr.is_active, mr.auc_wf
  FROM model_registry mr
  JOIN symbols s USING(symbol_id)
  JOIN timeframes t USING(tf_id)
  WHERE mr.is_active = TRUE
  ORDER BY s.symbol, t.tf_code;"

Se não aparece o ativo X TF:

# Listar pickles no filesystem
ls models/lgbm_EURUSD_H1_*.pkl

Se existir mas não está active → problema na promotion. Ver meta.json:

cat models/lgbm_EURUSD_H1_v<hash>.meta.json | jq '.approved, .is_active, .wf_metrics'

approved: false → rejeitado por gates. Lógica:

  • auc < 0.58 ou
  • auc_p5 < 0.55 ou
  • ece > 0.25 ou
  • pf < 0.95

Como promover manualmente (sem passar gates)

Use com cuidado

Bypass de gates pode colocar modelo perdedor em produção.

docker exec forex_db psql -U forex -d forex -c "
  UPDATE model_registry
  SET is_active = TRUE
  WHERE model_v = 'lgbm_EURUSD_H1_v<hash>';"

Marcar o anterior como inactive:

UPDATE model_registry
SET is_active = FALSE
WHERE symbol_id = (SELECT symbol_id FROM symbols WHERE symbol='EURUSD')
  AND tf_id = (SELECT tf_id FROM timeframes WHERE tf_code='H1')
  AND model_v != 'lgbm_EURUSD_H1_v<hash>';

Sempre atualizar o .meta.json correspondente também (set is_active: true).

Predição está demorando (>500ms)

# Profile
docker exec forex_worker python -c "
import time
from app.models.predict import predict_for_slot

t0 = time.time()
res = predict_for_slot('EURUSD', 'H1')
print(f'Tempo: {(time.time()-t0)*1000:.1f}ms')
print(res)
"

Causas comuns:

  • Modelo gigante (>50MB) — feature_clustering desabilitado?
  • Features pesadas (FDA com janela enorme)
  • DB lento (cache de candles desligado)

Como adicionar novo modelo (ex: LSTM)

  1. Implementar em app/models/train_lstm.py
  2. Adicionar ao ensemble em train_lightgbm.py (apesar do nome):
ensemble_models = [
    ("lgbm", train_lgbm(...)),
    ("xgb",  train_xgb(...)),
    ("cat",  train_cat(...)),
    ("lstm", train_lstm(...)),    # novo
]
  1. Atualizar configs/model.yaml:
training:
  ensemble_weight_lgbm: 0.40
  ensemble_weight_xgb:  0.25
  ensemble_weight_cat:  0.15
  ensemble_weight_lstm: 0.20    # novo
  1. Validar com 1 símbolo:
python scripts/run_training.py --symbol EURUSD --tf H1 --dry-run
  1. Atualizar ADR-003 explicando os novos pesos.

Drift detection — como ler

scripts/check_models.py:

docker exec forex_worker python scripts/check_models.py

Output:

Model lgbm_EURUSD_H1_v85b52764
  PSI:      0.12  ✓ (threshold 2.0)
  CUSUM:    1.4   ⚠️ (threshold 2.5)
  recent_pf: 1.08 ✓
  recent_auc: 0.594 ✓
  status:   OK

Model lgbm_GBPJPY_M15_v...
  PSI:      2.3  ✗ FAIL
  → CUSUM rollback triggered
  → Promoting older version: lgbm_GBPJPY_M15_v...

Histórico de modelos (B2 sticky)

Cada modelo treinado fica no models-history/ do B2 para sempre:

# Listar todas as versões de um slot
python scripts/restore_from_b2.py --list-models EURUSD_H1

Útil para auto-rollback CUSUM ou investigação histórica.