- Quanto tempo as oportunidades duram? Número de janelas acima do threshold, duração média, mediana (p50), p90 e máxima, distribuição de duração e horário do dia em que as janelas começam.
- Teria dado para operar? Um backtest simples com capital, tempo de transferência e custos líquidos, que separa as operações completadas das que expiraram antes de a transferência chegar.
/analise-historica (plano premium) e pode ser
aberta pelo botão “Ver análise histórica e backtest” no detalhe de uma
operação.
Fonte dos dados
Os cálculos usam a coleção MongoDBoperations_audit, gravada pelo
processamento REST a cada ~19 segundos. Ela tem limitações que valem para
todos os números:
Como uma janela é detectada
As amostras da rota são lidas em ordem cronológica. Uma janela começa na primeira amostra com spread ≥ threshold e termina quando:- uma amostra fica abaixo do threshold; ou
- a próxima amostra chega mais de 60 s depois da anterior (cerca de três ciclos perdidos, o que indica que o spread saiu da faixa gravada).
fim − início. Com basis=net o valor comparado é o
netSpread gravado na linha (notional de referência de US$ 1.000). Em
linhas antigas, sem o modelo de custo, o líquido é estimado com as mesmas
taxas padrão do cálculo de spread líquido (NET_SPREAD_DEFAULT_TAKER_RATE,
NET_SPREAD_DEFAULT_WITHDRAWAL_USD).
A incidência por hora é contada pelo início de cada janela, em UTC, e a tela
converte para o fuso do navegador.
Sugestão de tempo de transferência
A resposta trazsuggestedTransfer, calculado assim: a rede mais usada nas
janelas × a mediana de confirmações gravada em fees.network.confirmations
× um tempo de bloco aproximado por rede, mais 5 minutos de processamento da
exchange. Redes sem tempo de bloco conhecido não recebem sugestão. É só um
valor inicial: o usuário pode alterar o campo.
Hipóteses do backtest
- Capital único e uma operação por janela. Entra assim que o spread
atinge o threshold e o capital está livre. Janelas que começam e terminam
com o capital em trânsito contam como
skippedBusy. O rebalanceamento de volta para a exchange de compra não é modelado. - Rota inviável. Amostras com
executable=false(sem rede comum ou com saque/depósito suspenso) não abrem operação. Uma janela só com amostras assim conta comoskippedInfeasible. - Completada. A janela continua aberta quando a transferência chega
(
entrada + transferMinutes). O resultado usa o spread bruto da primeira amostra a partir da chegada, e não o da entrada. É a hipótese conservadora. - Expirada. A janela fechou antes da chegada. Como não existe dado abaixo de 4%, a hipótese é spread 0 com pagamento dos custos.
- Custos.
líquido% = bruto − (takerCompra + takerVenda) × 100 − saqueUSD / capital × 100, com as taxas da amostra de entrada. O custo de saque é fixo em USD, por isso pesa menos com capital maior. Operações cuja amostra não tinha custos completos são marcadas comcostsEstimatede contadas emestimatedCosts. - Em andamento. Uma operação aberta cuja janela ainda não fechou no fim do
histórico entra em
unresolvede não soma no resultado.
Endpoints
Os dois estão no limitador de arbitragem (30 req/min por IP), têm timeout de 10 s e cache de 30 minutos por combinação de parâmetros. Na inicialização o backend cria emoperations_audit o índice
{ticker, best_buy_exchange_name, best_sell_exchange_name, timestamp} usado
por essas consultas.
Código
crypto-core/internal/application/opportunity/: detecção das janelas, estatísticas, backtest e sugestão de transferênciacrypto-core/internal/infra/db/opportunity_history.go: leitura em streaming com projeção e o índicecrypto-core/internal/api/opportunity-history-api.go: handlers HTTPfront-argitragem/src/pages/opportunity-history/: a tela