Roadmap · atualizado em 2026-09-25

O que falta decidir antes de ligar o MT5

0 de 13 decisões ainda abertas. Cada uma aponta o arquivo e a linha que ela destrava. Tudo aqui saiu de medição — backtest sobre 10 anos de ouro real, replay dos agentes, simulação de 4.000 caminhos. Nada é palpite.

0 pendentes0 já em PR13 PRs mergeadas

Bloco A

As decisões, em ordem

D1DECIDIDOdecide: CEO + quem opera o PC Windows

Qual corretora (e quais CFDs ela oferece)

Define os ativos disponíveis e o TAMANHO DE CONTRATO de cada um. Hoje o código assume um binário isXAU ? 100 : 100_000 — errado para índice (US500: contrato 1-10) e petróleo (USOIL: 1.000 bbl), em 5 lugares.

Opções: Corretora com US500 + USOIL + EURUSD + XAUUSD em CFD · Só ouro (mantém tudo como está)

ET recomenda: Corretora com os 4 — e me passar o nome pra eu fechar a tabela de símbolos.

Destrava: nada — CEO delegou ao ET em 25/09 ("pode fazer isso aí mesmo"): IC Markets Raw Spread (menor spread publicado no ouro; Tickmill Raw como alternativa). Comparação e fontes em docs/pesquisa/CORRETORAS-MT5.md. ABRIR A CONTA é do CEO/Marcelo; o ET não mexe em dinheiro · Fonte: executor.agent.ts:664,1006 · risk.controller.ts:150 · paper-trading.service.ts:157 · reviewer.agent.ts:163

D2DECIDIDOdecide: CEO

Conta DEMO antes de qualquer conta real

Spread, slippage e execução reais da corretora, com dinheiro fictício. É o único teste que valida a ponte MT5 (hoje 0 trades ao vivo) sem risco.

Opções: Demo primeiro, N semanas em PAPER_TRADING · Direto na real

ET recomenda: Demo primeiro. Sem exceção.

Destrava: nada — executar no PC Windows · Fonte: STATE.md · bridge/mt5_bridge.py

D3DECIDIDOdecide: CEO

Ligar RISK_FRAMEWORK_ENABLED=true por padrão

Os 7 gates de risco (semanal, mensal, correlação, notional, regime…) rodam SÓ com essa env = true. Default é OFF e produção não liga. O PR #77 deixou os gates corretos — mas eles dormem até alguém setar a flag.

Opções: default true no código · setar só no .env do servidor · deixar OFF

ET recomenda: default true. Gate de risco desligado é decoração.

Destrava: nada — ON por padrão; e o dryRun do paper agora RODA os gates (antes pulava) · Fonte: executor.agent.ts riskFrameworkEnabled() !== "false" (este PR) · PR #77

D4DECIDIDOdecide: CEO (foi diretiva sua em 2026-04-17, XAU-FOCUS.md)

Revogar a trava XAUUSD para MEDIR outros ativos

validate.ts:8 derruba o boot com qualquer par ≠ XAUUSD, e o backtest tem o símbolo cravado em 3 pontos. Sem revogar, não existe número para US500/USOIL/EURUSD — só faixa.

Opções: Revogar só no backtest (medição, prod intacta) · Revogar em tudo · Manter só ouro

ET recomenda: Só no backtest primeiro. Número antes de código de produção.

Destrava: só medição; o bot ao vivo continua XAUUSD-only por design · Fonte: backtest.controller.ts run({ symbol }) · scripts/*-real.ts --symbol (este PR) · validate.ts:8 segue travando o BOT

D5DECIDIDOdecide: CEO

Motor de decisão: regras (F2) ou squad de IA

Medido sobre ouro real: F2 D1 deu 6,09%/ano com 80% das janelas out-of-sample positivas e 160 trades em 10 anos. O squad de IA (4 agentes Claude) deu 6 trades em 19 meses (+1,8%) e o Judge nunca passou de 60% de confiança.

Opções: F2 em todos os ativos; squad como camada opcional depois · Squad como motor principal

ET recomenda: F2. Reproduzível, testado (890 testes), custo zero por decisão.

Destrava: nada — CEO delegou ao ET em 25/09: F2 (regras) é o motor ao vivo. Ligado por SIGNAL_ENGINE=f2 (+ F2_PRESET=momentum, F2_THRESHOLD=0.05, F2_TIMEFRAME=D1) — o MESMO motor que o backtest mede; default do código segue squad para prod não mudar em silêncio. src/services/f2-signal.service.ts · Fonte: docs/qa-fluxos/BACKTEST-REAL.md · PR #76

D6DECIDIDOdecide: CEO (só importa se D5 = squad)

Portão de confiança do squad: 65% → 55%

O portão pedia 65%. Em 66 debates reais o Judge nunca passou de 60% — com 65 o bot NUNCA opera. A distribuição tem um vazio entre 40% e 55%: o portão certo mora aí.

Opções: 55% · 60% · manter 65% (zero trades)

ET recomenda: 55%. Já é argumento de CLI (--min-confidence) na branch fix/llm-cli-mode.

Destrava: nada — é argumento de CLI; 55 fica a critério de quem roda · Fonte: replay.ts --min-confidence (PR #79, mergeado) · log de 66 debates

D7DECIDIDOdecide: CEO

Risco por trade: 1% ou 1,5%

Simulação de 4.000 caminhos de 10 anos com o edge medido. 1%: nenhum caminho zerou, pior tombo 28%. 1,5%: 6,09%/ano, 80% das janelas OOS, pior tombo 11,5% no backtest. 5% (o antigo teto): 88% dos caminhos caem mais de 30%.

Opções: 1% (zero ruína medida) · 1,5% (validado no walk-forward) · acima de 2% — o validador agora BARRA

ET recomenda: 1% até existir histórico em conta demo. PR #77 já pôs default 1% e teto 2%.

Destrava: nada — default 1%, teto 2%; e o sizing do framework agora respeita MAX_RISK_PER_TRADE (antes usava 0,5% fixo e ignorava o env) · Fonte: constants.ts:28 · validate.ts:37 · PR #77 (mergeado)

D8DECIDIDOdecide: CEO

Meta de retorno realista

50%/ano exige 3-5 ativos a 2-5% de risco, com 30% de chance de tombo > 30%. Zero risco de zerar: ouro sozinho a 1% = 4,1%/ano. Os ~22%/ano com 5 ativos a 1% pressupunham 5 edges iguais à do ouro — medido em 2026-09-25, o motor tem 1 (ver D12). Os dois objetivos não cabem juntos, e o teto honesto hoje é o do ouro.

Opções: zero ruína (~4% ouro só / ~22% com 5 ativos) · 50%/ano aceitando drawdown real · meta intermediária

ET recomenda: Escolher UM e escrever aqui. Toda calibração depende disso.

Destrava: nada — CEO em 24/09: "quero 0 risco de zerar"; em 25/09 delegou o fechamento: ZERO RUÍNA. MAX_RISK_PER_TRADE=1.0 (o validador barra > 2), expectativa honesta ~4,1%/ano no ouro (4.000 caminhos, nenhum zerou, pior tombo 28%). 50%/ano fica registrado como ambição, não como meta operacional · Fonte: simulação 2026-09-24 (4.000 caminhos)

D9DECIDIDOdecide: CEO

Timeframe operacional: D1 ou H1

D1: 16 trades/ano, expectativa +0,318 por trade, 86,7% das janelas OOS positivas. H1: 183 trades/ano, expectativa +0,068, 65% das janelas, e subir o risco para 1% quebra a estratégia (44 trades/ano, expectativa negativa). 14× mais trades deram 9× menos retorno.

Opções: D1 (estável) · H1 (volume, edge dilui)

ET recomenda: D1. Volume só faz sentido vindo de mais ativos, não de timeframe menor.

Destrava: nada — CEO 25/09 ("pode seguir"): D1. Marcelo põe TIMEFRAME=D1 no .env (checklist passo 4); o default do código segue H1 até a demo confirmar o loop ao vivo em D1 · Fonte: scripts/sweep-real.ts · scripts/walkforward-real.ts (PR #76)

D10DECIDIDOdecide: CEO

Tirar o seed do Dockerfile de produção

Dockerfile:27 roda npm run seed:all no build e :52 copia o banco pra imagem. Resultado: o dashboard de PRODUÇÃO mostra 450 trades e win rate 57,5% gerados por Math.random() (seed.ts:396) como se fossem performance real.

Opções: Remover o seed (prod sobe vazio e honesto) · Imagem demo separada com carimbo "DEMONSTRAÇÃO" · Manter

ET recomenda: Remover. Zero-mock é regra da casa e este é o pior lugar pra quebrá-la.

Destrava: nada — CEO 25/09 ("fecha e mergeia"): seed removido da imagem no #82. Prod nasce com banco vazio; landing/analytics mostram estado vazio até trade real · Fonte: Dockerfile:27,52 · seed.ts:17,396 · docs/qa-fluxos/ACHADOS.md P0-1

D11DECIDIDOdecide: CEO

devDependencies na imagem de prod (e o gate audit-high vermelho)

Dockerfile:13 roda npm ci sem --omit=dev e :50 copia node_modules inteiro. 3 vulns high do CLI do prisma embarcam em prod, e por isso o gate audit-high (ci/local-ci.py:56) fica vermelho em todos os PRs — corretamente.

Opções: npm prune --omit=dev no fim do builder · bump prisma 6→8 (major) · ignorar

ET recomenda: prune no builder: a imagem encolhe e as 3 high somem de verdade.

Destrava: nada — CEO 25/09: prune de devDependencies no builder (#82), com test -d/-f que falha o build se levar o Prisma Client ou o better-sqlite3. O audit-high já tinha sido zerado pelo #83 (overrides deepmerge-ts) · Fonte: Dockerfile:13,50 · ci/local-ci.py:56 · PR #75 · ACHADOS.md P0-2

D12DECIDIDOdecide: CEO (após D1)

Quais ativos entram no portfólio

MEDIDO em 2026-09-24/25 com o mesmo motor F2 (walk-forward D1, custo relativo): US500 momentum 0,05 = 66,7% das janelas positivas mas Sharpe 0,11 (sinal estável, retorno nulo); USOIL 46,7%; EURUSD 37,5%. Ouro = 86,7% / Sharpe 1,00. O edge do ouro NÃO se repete: as 5 edges usam o cluster do ouro (DXY, US10Y, VIX, SPX). A conta de ~22%/ano com 5 ativos pressupunha 5 edges iguais à do ouro — hoje existe 1. Prata anda 0,85-0,95 com ouro (volume, não proteção).

Opções: só XAUUSD agora; outro ativo só com edge PRÓPRIA que passe o walk-forward · XAUUSD + US500 momentum 0,05 (estável, mas Sharpe ≈ 0 — não soma retorno) · XAUUSD + XAGUSD (não diversifica)

ET recomenda: Só XAUUSD. Cada ativo novo é trabalho de pesquisa (features do próprio ativo), não configuração — e entra só depois de 60%+ das janelas OOS com Sharpe > 0,5.

Destrava: nada — CEO 25/09 ("pode seguir"): SÓ XAUUSD. Outro ativo só entra com edge própria medida (≥60% janelas OOS e Sharpe ≥ 0,5 líquido) · Fonte: docs/qa-fluxos/BACKTEST-REAL.md § Rodada 2 · scripts/walkforward-real.ts --symbol --threshold

D13DECIDIDOdecide: CEO (depois de D1 e D2)

Abrir frente de ações por notícia/macro?

Pergunta do CEO em 2026-09-25. O george hoje usa macro só para o ouro e usa CALENDÁRIO, não notícia (as "headlines" da ponte são linhas do calendário ForexFactory). Literatura: sinal de notícia em ações existe, dura dias, concentra em small cap e encolhe com 10 bps de custo; alpha de sentimento caiu 66% (IR 0,76 → 0,25); custos comem 70-100% do PEAD. CFD de ação custa mais que ouro e tem gap. Nada disso muda o bot de ouro.

Opções: não abrir agora — foco no ouro até D1/D2 · só MEDIR: estudo de evento D1 com dado grátis, zero dinheiro, mesma régua do ouro (≥60% janelas OOS e Sharpe ≥ 0,5 líquido) · pesquisa completa (features por empresa, LLM com corte temporal)

ET recomenda: Só medir, depois de D1 (custo real do CFD) e D2 (demo). Prometer % antes de medir seria número inventado.

Destrava: nada agora — CEO 25/09 ("pode seguir"): só MEDIR, depois de D1 (custo real do CFD) e D2 (demo). Nenhum trade de ação antes disso · Fonte: docs/pesquisa/NOTICIAS-MACRO-ACOES.md (com as fontes)

Bloco B

O que já foi medido — não refazer

O quêMedidoFonte
Motor F2 ao vivo (D5) — fidelidade ao backtestmomentum thr 0,05 em D1 dá o MESMO resultado com ou sem as séries macro (10 anos: +27,49% / 160 trades vs +27,79% / 163; walk-forward 86,7% / Sharpe 1,03 idêntico) → a v1 ao vivo roda só com as velas D1 da corretora. 14 testes de costura (vela em formação fora, 1 decisão por vela SÓ quando entra, stop/alvo por ATR, zero token, Executor sem piso de LLM para F2). Desvio que resta: entrada na abertura da SESSÃO London/NY, não da vela (até 7 h) — medir na demosrc/services/f2-signal.service.ts · tests/f2-signal-service.test.ts · tests/executor-hardvalidate.test.ts
Ponte MT5 com dado FICTÍCIO em produção (P1-3)com MT5 real e fonte fora, a ponte devolvia calendário (NFP "daqui a 2h" para sempre), headlines e book INVENTADOS ao bot. Corrigido: mock só em modo dev (sem módulo MetaTrader5); com MT5 real, vazio + aviso no logbridge/mt5_bridge.py get_economic_calendar() · fetch_news_headlines() · get_orderbook()
Outros ativos com o mesmo motor (walk-forward D1, custo relativo)US500 momentum 0,05: 66,7% janelas positivas / Sharpe 0,11 · USOIL 46,7% / −0,22 · EURUSD 37,5% / −0,38 · nenhum passa os gates no backtest cheio. Ouro: 86,7% / 1,00BACKTEST-REAL.md § Rodada 2
Ouro D1 — 0,05 é do preset momentummomentum 0,30 → 73,3% · momentum 0,05 → 86,7% · balanced 0,05 → 40%. Reproduzido com o script commitado (o flag --threshold era ignorado antes)scripts/walkforward-real.ts
Defeitos de medição fechadoscusto fixo em US$ do ouro aplicado ao EURUSD dava −99% (artefato) → custo relativo; --threshold ignorado no walk-forward → ligadoslippageFor() · walkforward-real.ts
Ouro D1, threshold 0,05, risco 0,5% (10 anos)+27,5% total · 16 trades/ano · expectativa +0,318 · 13 de 15 janelas OOS positivasPR #76
Ouro D1, risco 1% — zero ruína4,1%/ano · nenhum de 4.000 caminhos zerou · pior tombo 28%simulação 2026-09-24
Segurar ouro no mesmo período+250% em 10 anos (13,55%/ano) — nenhuma configuração do bot chega pertoYahoo GC=F
Squad de IA (4 agentes Claude), 19 meses6 trades · +1,8% · Judge nunca > 60% · com portão 65%: zero tradesreplay via CLI, R$ 0,00
Edges macro ligadas no backtestBalanced 5-Edge saiu de 1 trade/−0,5% para 58 trades/+8,5%/DD 2,5%PR #76
Testes890 verdes (51 revividos que nunca rodavam) · tsc limpo · next build okPR #77
Proteções reais hoje em prodhalt diário −3% (controller) · SL/TP no servidor MT5 · sem martingale · 7 gates do framework LIGADOS por padrão (D3) — inclusive em paper/dryRunbot.controller.ts:297 · mt5_bridge.py:669 · PR #77 · D3
Alavancagem: o que o gate de notional faz de fatosizing é ATR-based (stop = ATR×1,5). Em volatilidade baixa, 1% de risco vira notional >120% da equity e o gate REJEITA — é a trava de alavancagem, não bug. Teto vivo = 120% (igual ao backtest); a trava de ruína segue MAX_RISK_PER_TRADE ≤ 2%risk-gates.ts liveConstraints() · position-sizing.ts
Paper (conta demo) e os gatesANTES: o dryRun retornava antes da flag → a demo testaria SEM gate nenhum. AGORA: sizing + gates rodam, só a ordem é puladaexecutor.agent.ts evaluate()/executeViaRiskFramework(options.dryRun)

Bloco C

No PC Windows com o MT5 — nesta ordem

  1. Decidir D1 e D2 acima. Sem corretora e sem "demo primeiro", não começar.
    Como provar que deu certo: Estado desta página
  2. Instalar o MetaTrader 5 da corretora e abrir a conta DEMO.
    Como provar que deu certo: Login no terminal MT5 com saldo fictício
  3. Python 3.10+ e pip install -r bridge/requirements.txt (MetaTrader5>=5.0.45, Flask, pandas…). No MESMO .env da ponte: MT5_LOGIN, MT5_PASSWORD e MT5_SERVER da conta demo (mt5_bridge.py:73-75 e mt5.login em :1899) — sem isso a ponte sobe em modo MOCK e o bot analisa vela inventada.
    Como provar que deu certo: pip list mostra MetaTrader5 · GET /health da ponte devolve status diferente de "mock"
  4. No .env do bot: PAIRS=XAUUSD (ATENÇÃO — o .env.example do repo traz 6 pares e o validador aceita SÓ XAUUSD desde o XAU-FOCUSED MODE: copiar como está faz o bot NÃO subir, com "Par inválido") · MT5_BRIDGE_URL=http://<ip-do-windows>:5001 · MT5_BRIDGE_SECRET=<mesmo segredo nos dois lados, mín. 16 chars> · PAPER_TRADING=true (D2) · MAX_RISK_PER_TRADE=1.0 (D8) · TIMEFRAME=D1 (D9) · SIGNAL_ENGINE=f2 · F2_PRESET=momentum · F2_THRESHOLD=0.05 · F2_TIMEFRAME=D1 (D5) · RISK_FRAMEWORK_ENABLED=true (D3, já é o default) · DASHBOARD_PASSWORD (mín. 8) · JWT_SECRET e BOT_API_SECRET (mín. 16).
    Como provar que deu certo: GET /api/health/census mostra as envs presentes · o boot imprime "✅ Configuração validada com sucesso"
  5. Subir a ponte: python bridge/mt5_bridge.py.
    Como provar que deu certo: GET http://<ip>:5001/health → 200
  6. A CATRACA: `npm start` morre com "BLOQUEADO (NO_ACTIVE_PLAN)" enquanto não houver recarga vigente no ledger. Sem gateway de pagamento configurado, a porta de OPS é: npm run entitlement -- grant --plan compute-credit-100 (grava linha REAL com source=manual-ops, auditável).
    Como provar que deu certo: npm run entitlement -- status mostra a linha vigente · o log do boot diz "🔓 Recarga ativa"
  7. Abrir o dashboard → aba Status.
    Como provar que deu certo: Conexão MT5 sai de OFFLINE; GET /api/manual/quote → 200 com preço
  8. Aba Backtest → rodar Momentum Tilt, D1, 3000 barras.
    Como provar que deu certo: Primeiro número com candle DA CORRETORA (não Yahoo). Comparar com +13,16% do GC=F
  9. US500, USOIL e EURUSD JÁ foram medidos com dado Yahoo (BACKTEST-REAL.md § Rodada 2): nenhum repete o edge do ouro. Só refazer com candle da corretora se D12 mudar.
    Como provar que deu certo: scripts/walkforward-real.ts --symbol <ATIVO> --threshold 0.05 → ≥60% janelas OOS positivas E Sharpe OOS ≥ 0,5
  10. PAPER_TRADING=true na demo por, no mínimo, 4 semanas. Comparar trades reais × backtest.
    Como provar que deu certo: Aba Paper e Analytics com trades REAIS (não seed)
  11. NUNCA: conta real antes da demo · risco > 2% (o validador barra) · martingale (não existe no código, que continue assim).
    Como provar que deu certo: validate.ts:37 · grep martingale = 0
  12. Com a ponte ligada ao MT5 real, conferir que NADA vem inventado: calendário, headlines e book. Se a corretora não tem DOM, o book deve vir "unavailable" (o bot trata como sem book), nunca um book com volumes aleatórios.
    Como provar que deu certo: GET /economic-calendar → eventos com data real (não NFP "daqui a 2h" toda vez) · GET /orderbook/XAUUSD → depth > 0 OU pressure "unavailable" · log da ponte sem linha "[MOCK]" após conectar

Bloco D

PRs desta frente

  • #74 — QA de Fluxos + 2 P0 do Dockerfile (mergeado 2026-09-24)
  • #75 — 4 vulns de prod fechadas (express/qs/socket.io-parser) (mergeado 2026-09-24)
  • #76 — Backtest sobre ouro real + edges macro + walk-forward + calculadora (mergeado 2026-09-24)
  • #77 — Gates de drawdown com dado real + teto 2% + 51 testes revividos (mergeado 2026-09-24)
  • #78 — Esta página: /roadmap + links na home + STATE.md (mergeado 2026-09-24)
  • #79 — LLM_MODE=cli nunca funcionou + portão do squad vira --min-confidence (mergeado 2026-09-24)
  • #80 — D3: framework de risco LIGADO por padrão (paper roda gates) + D4: --symbol no backtest (mergeado 2026-09-24)
  • #81 — TOTP com tela + CORS do feed + 3 rotas com botão + ponte sem dado inventado com MT5 real (P1-3) + medição US500/USOIL/EURUSD + pesquisa notícias/ações (D13) (mergeado 2026-09-25)
  • #82 — RASCUNHO (não buildado aqui): D10 sem seed na imagem + D11 sem devDeps no runtime — o CEO decide, o build da Railway prova (mergeado 2026-09-25 por ordem do CEO — build da Railway é a prova (não buildado localmente))
  • #83 — overrides deepmerge-ts ^8 — zera o audit-high que mantinha o ci-local/root vermelho desde #74 (mergeado 2026-09-25 — primeiro ci-local/root VERDE desde #74)
  • #84 — P2-3 fechado com a lista certa das 5 rotas sem tela (por design) + #83 no roadmap (mergeado 2026-09-25 — CI verde)
  • #85 — data/ temporário por worker (o gate `test` da main caía por colisão entre workers) + decisões D9-D13 (mergeado 2026-09-25 — CI verde)
  • #86 — SIGNAL_ENGINE=f2: o motor medido no backtest passa a decidir ao vivo (D5) + D1 corretora + D8 zero ruína (mergeado 2026-09-25 — CI verde)

Esta página é gerada de web/src/lib/roadmap.ts. Decisão tomada → mudar o estado lá. Detalhe técnico de cada achado: docs/qa-fluxos/.