O problema
O spread de uma oportunidade é calculado sobre o topo do livro — o melhor preço de compra contra o melhor preço de venda:O cálculo
O spread realizável consome o livro de ofertas até preencher um alvo de volume e calcula o preço médio ponderado (VWAP) efetivamente pago e recebido:- na exchange de compra, consumimos os asks (é contra eles que se compra);
- na exchange de venda, consumimos os bids.
3.1% @ $1k · 1.9% @ $5k · 0.8% @ $10k: o mesmo par,
avaliado em três tamanhos de operação.
O campo depth
Oportunidades spot podem trazer um array depth, uma entrada por faixa:
Quando
insufficientLiquidity é true, o effectiveSpread é o spread da
liquidez que existia — não do notional pedido. No exemplo acima, os 0.78%
referem-se aos 10.000. É por isso que
filledNotional* existe: sem ele, o número parece uma promessa que o livro não
sustenta.Quando depth não vem
O campo é opcional e some do payload quando não pôde ser calculado. Todo
consumidor precisa tratar a ausência. Os motivos legítimos:
- Fora do top-N. A listagem (
GET /v1/arbitrage) só enriquece asNoportunidades de maior spread bruto — buscar o book de todas a cada tick multiplicaria o custo de rede. O detalhe (GET /v1/arbitrage/{id}) sempre calcula. - Cotação não suportada. Pares cotados fora de USD/stablecoins, BRL e EUR não têm como ter a faixa convertida.
- Book indisponível. Falha ou timeout na consulta à exchange.
- Streaming. O canal SSE
GET /v1/realtime/arbitragepublica direto do motor de comparação e não passa pelo enriquecimento, então oportunidades vindas por ele nunca trazemdepth. - Kill switch.
DEPTH_ENABLED=false.
Moedas e conversão
As faixas são definidas em USD para serem comparáveis entre pares. Como o livro está na moeda de cotação, é a faixa que é convertida (alvo = faixa × taxa), não os preços nível a nível — e o VWAP volta para USD no final.
USD,USDT,USDC,BUSD,DAI,TUSD,FDUSDsão tratadas como paridade 1:1 com o dólar. Um depeg de 0,3% desloca a faixa de “9.970 de profundidade real; como o spread é uma razão, o número de manchete não muda.BRLeEURusam a cotação do serviço de câmbio. Ele não atualiza em fins de semana nem fora do horário comercial, então num boot frio de sábado pares nessas moedas podem ficar semdepth.
A taxa se cancela na razão entre os dois VWAP. Uma cotação desatualizada só
desloca qual fatia do livro é amostrada — nunca distorce o
effectiveSpread.Profundidade publicada por exchange
OinsufficientLiquidity reflete o book que a exchange devolveu. Algumas
truncam:
Quando o alvo não é atingido por esse limite e não por falta de liquidez real,
bookExhausted vem true — a interface mostra “book truncado pela exchange”
em vez de “liquidez insuficiente”.
Configuração
Custo de rede
Cada oportunidade exige dois livros (a perna de compra e a de venda). Três camadas mantêm isso barato:- Corte top-N — de até 25 linhas para 5 na listagem.
- Cache de profundidade (20s) — absorve o poll de 10s do front-end, com singleflight colapsando requisições concorrentes idênticas.
- Cache de book (4min) — um dado par em uma dada exchange custa no máximo uma ida à rede a cada 4 minutos, independentemente de quantas oportunidades ou clientes o referenciem.