Uma planilha financeira que alguém atualiza à mão já não aguenta o volume quando os dados chegam de mais de uma fonte. O Alpha Signal, plataforma real que construí e mantenho, processa mais de 8 milhões de linhas por dia em quatro serviços rodando sob Docker — banco, ETL, API e dashboard —, cobrindo EUA, Brasil e cripto, com um agendador que dispara 12 tarefas por conta própria todo dia útil, sem operação manual.

O padrão por trás disso não é específico de mercado financeiro: é dados em tempo real, cálculo, ação — e serve qualquer operação que precisa decidir a partir de volume alto. Dá para montar uma versão simplificada desse padrão sem replicar a escala inteira? Dá, e o ponto de entrada não muda: ingestão, score, e uma tela que atualiza sozinha.

O que você precisa

  • Python 3.11+
  • Conta Supabase (Postgres + Realtime) — a camada gratuita cobre o protótipo
  • Node.js e Next.js para o dashboard
  • Docker e Docker Compose
  • Arquivos CSV de transações de exemplo, ou uma fonte real se já tiver
  • Opcional: chave de API de LLM, só para explicar anomalias já sinalizadas — não para processar todas as linhas
  • Tempo: mais de duas semanas para a versão completa com dashboard ao vivo

Passo 1: monte o pipeline de ingestão

Comece pela fonte mais simples: arquivos CSV numa pasta monitorada. As etapas são ler e validar o schema, normalizar datas, moedas e categorias, e inserir no Supabase em lote.

create table transactions (
  id uuid primary key default gen_random_uuid(),
  source text not null,
  date timestamp not null,
  description text,
  category text,
  amount numeric not null,
  type text check (type in ('credit', 'debit')),
  score numeric default 0,
  flags jsonb default '[]',
  created_at timestamp default now()
);

create index idx_transactions_date on transactions(date desc);

Resultado: rodando o processador contra um CSV de teste, as linhas aparecem na tabela transactions.

LEIA TAMBÉM · Caso realO Equity Tracker não prevê o mercado — lê 8 milhões de registros por diaUm programa busca os preços de fechamento de ações e criptomoedas todo dia, organiza tudo num banco e marca o que mudou de comportamento. Você abre uma página de manhã e já encontra o resultado pronto.

Passo 2: implemente o motor de regras

Regras configuráveis, cada uma soma um score e pode adicionar uma flag:

RULES = [
    {"name": "alto_valor", "condition": lambda t: t["amount"] > 10000, "score": 8, "flag": "Transação de alto valor"},
    {"name": "fora_horario", "condition": lambda t: t["date"].hour < 6 or t["date"].hour > 22, "score": 5, "flag": "Transação fora do horário comercial"},
    {"name": "categoria_nova", "condition": lambda t: is_new_category(t), "score": 3, "flag": "Categoria não vista nos últimos 90 dias"},
]

Cada transação recebe a soma dos scores das regras acionadas, mais a lista de flags. Resultado: transações de teste com valor alto ou horário atípico aparecem com score maior que zero.

Passo 3: some detecção estatística de anomalias, IA só para explicar

Rodar um modelo de linguagem em 8 milhões de linhas por dia não cabe em orçamento nenhum — por isso a ordem importa. Primeiro, estatística simples (z-score ou desvio da média móvel de 30 dias por categoria) sinaliza os outliers. Só as transações sinalizadas passam por uma chamada de IA, para gerar uma explicação legível — nunca todas as linhas.

Prompt: "Analise esta transação sinalizada. Com base no histórico do cliente
(média por categoria, horários típicos, valores típicos), explique por que
ela parece anômala."

Resultado: as transações sinalizadas ganham um campo de explicação em texto, sem custo de IA nas outras milhões.

Passo 4: calcule agregações em tempo real e cacheie as métricas

Totais diários, médias móveis e tendências por categoria ou conta ficam caros de recalcular a cada requisição do dashboard. Um job separado, rodando em intervalo curto e independente da ingestão, atualiza um cache dessas métricas. Resultado: consultar o cache devolve as métricas do dia sem tocar na tabela de transações inteira.

Passo 5: construa o dashboard com Next.js e Supabase Realtime

Um componente cliente assina mudanças na tabela via postgres_changes:

const channel = supabase
  .channel('transactions-changes')
  .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'transactions' }, (payload) => {
    // atualizar estado do dashboard com payload.new
  })
  .subscribe()

Filtros por período, categoria e conta completam a interface. Resultado: uma transação nova inserida no Passo 1 aparece no dashboard sem recarregar a página.

Passo 6: configure alertas e exportação de relatórios

Um alerta — Telegram, e-mail ou webhook — dispara quando o score de uma transação passa de um limiar definido, e a exportação em PDF inclui o período filtrado no dashboard. Resultado: uma transação de score alto notifica fora do dashboard, sem alguém precisar estar olhando a tela.

Passo 7: suba com Docker e agende a ingestão contínua

O Docker Compose reúne o worker de ingestão, a API, o dashboard e o job de agregação do Passo 4. Um agendador dispara a ingestão em intervalos regulares, sem depender de alguém rodar na mão.

docker compose up -d

Resultado: o pipeline completo rodando sozinho — dado entra, é pontuado, aparece no dashboard em tempo real, e os alertas saem quando o score justifica.

LEIA TAMBÉM · ExplicaçãoO que separa um protótipo de IA de um sistema em produção são três peças baratasMostrar IA funcionando uma vez é fácil. O difícil é deixar rodando todo dia sem ninguém olhando. Três peças simples — Docker para empacotar, healthcheck para vigiar, agendador para disparar — fazem quase todo o trabalho.

O que pode dar errado

Dashboard não atualiza mesmo com o Realtime configurado — a tabela não foi adicionada à publicação: alter publication supabase_realtime add table transactions;. Erro comum e silencioso.

Rodar IA em cada uma das milhões de linhas por dia estoura o orçamento — estatística filtra primeiro, IA só analisa o que já foi sinalizado.

Dados de fontes diferentes chegando em formatos diferentes de data e moeda — normalize antes de gravar, nunca depois.

Consultas ficando lentas conforme a tabela cresce — índice em date desde o primeiro dia, não como correção depois.

Próximos passos

Adicionar fontes além de CSV — APIs bancárias, webhooks — sem mudar o schema da tabela. Score configurável por cliente ou conta, em vez de um conjunto único de regras global. Trocar polling por evento na ingestão, para reduzir a latência entre o dado existir e ele aparecer pontuado.

O pipeline prova o padrão dados em tempo real, cálculo, ação. Depois que ele roda sozinho, o desafio deixa de ser captar dado e passa a ser decidir o que fazer com o alerta.