Toda aplicação que conversa com uma exchange de cripto acaba escrevendo os mesmos dois pedaços de encanamento. O primeiro restaura suas inscrições de dados de mercado depois que o socket cai. O segundo desacelera suas chamadas REST para que a exchange não limite você. Nenhum dos dois é código interessante, ambos são fáceis de errar de forma sutil, e ambos ficaram por conta da aplicação até agora.
O sgcWebSockets 2026.7 traz os dois embutidos. Os clientes de API das exchanges podem reproduzir suas próprias inscrições depois de uma reconexão, e todo cliente REST pronto agora tem um limitador de taxa no lado do cliente que limita quantas requisições você envia em uma janela de tempo. Ambos são opcionais e vêm desligados por padrão, então atualizar não muda nada até você ligá-los.
A reconexão que deixa você inscrito em nada
O WatchDog sempre foi bom em trazer a conexão de volta. Um cabo é desconectado, um proxy expira, a exchange reinicia um gateway, e alguns segundos depois o cliente está conectado de novo. Essa parte funciona.
O que não volta são suas inscrições. A exchange não tem memória delas. Um socket novo é uma sessão em branco, então os streams de negócios e de livro de ofertas que você pediu no socket antigo simplesmente não existem mais. O sintoma é desagradável porque nada parece quebrado: o cliente informa Connected, nenhum erro é levantado, e os eventos de mensagem simplesmente param de chegar. Seu gráfico envelhece em silêncio.
A solução habitual é manter sua própria lista de inscrições e reproduzi-la a partir de OnConnect, o que significa lembrar de cada símbolo, cada canal e cada stream que você pediu, e lembrar de atualizar essa lista toda vez que você se inscreve ou cancela a inscrição em outro ponto do código. É uma contabilidade que não tem nada a ver com a sua estratégia.
Ligando a reinscrição automática
Os clientes de API já sabem em que você se inscreveu, porque você se inscreveu através deles. No 2026.7 eles podem guardar essa lista e reproduzi-la sozinhos após uma reconexão. É um único Boolean no objeto de opções da exchange, chamado Resubscribe.
Aqui está a versão feita à mão que a maioria dos apps de trading tem hoje, e o que a substitui:
uses
sgcWebSocket, sgcWebSocket_API_Binance;
// Before: keep your own list and replay it on every reconnect.
procedure TForm1.OnBinanceConnect(Connection: TsgcWSConnection);
begin
sgcWSAPI_Binance1.SubscribeTrades('btcusdt');
sgcWSAPI_Binance1.SubscribeTicker('btcusdt');
sgcWSAPI_Binance1.SubscribeTrades('ethusdt');
// ... and every other symbol you had open, in the right order.
end;
// After: the API client replays them for you.
sgcWSAPI_Binance1.Binance.Resubscribe := True;
Com Resubscribe habilitado, o cliente registra cada inscrição conforme você a faz, e depois que o WatchDog traz o socket de volta ele as envia novamente na sessão nova. Cancelar uma inscrição remove a entrada, então um stream que você fechou deliberadamente não ressurge dos mortos na próxima reconexão.
Ele funciona em conjunto com o WatchDog, e não em substituição a ele. O WatchDog restaura o transporte, o Resubscribe restaura a sessão em cima dele:
uses
sgcWebSocket, sgcWebSocket_API_Kraken;
begin
sgcWebSocketClient1.WatchDog.Enabled := True;
sgcWebSocketClient1.WatchDog.Timeout := 5; // retry the socket every 5 seconds
sgcWSAPI_Kraken1.Client := sgcWebSocketClient1;
sgcWSAPI_Kraken1.Kraken.Resubscribe := True; // and restore the streams on top
sgcWebSocketClient1.Active := True;
sgcWSAPI_Kraken1.SubscribeTrade(['XBT/USD', 'ETH/USD']);
end;
O padrão é False. As aplicações existentes que já se reinscrevem manualmente continuam funcionando exatamente como antes, sem inscrições duplicadas, até você apagar seu próprio código e ligar a opção.
Quais exchanges
Resubscribe está no objeto de opções de cada cliente de exchange. Está disponível em Binance, Bitfinex, Bitget, BitMEX, Bitstamp, Bybit, CEX, CEX Plus, Coinbase, Crypto.com, Deribit, Gate.io, Huobi, Kraken, KuCoin, MEXC e OKX, e no feed de streaming baseado em sessão da XTB. A propriedade é sempre escrita da mesma forma, então a linha fica Coinbase.Resubscribe, Bybit.Resubscribe, OKX.Resubscribe e assim por diante, dependendo de qual componente você colocou no formulário.
O cliente Lightstreamer, que é usado pela IG e por outras corretoras, faz a mesma coisa internamente. Depois de um rebind de sessão o servidor não tem registro das inscrições anteriores, então o cliente as reproduz a partir de sua coleção local sem que você peça.
Limites de taxa, pelo lado do cliente
A outra metade de um app de trading é o lado REST: enviar uma ordem, cancelar uma ordem, carregar saldos, carregar a lista de símbolos. Toda exchange publica um orçamento de requisições para esses endpoints, normalmente um número de requisições ou um peso por minuto, por IP ou por chave. Ultrapasse e você recebe um 429, e se continuar ultrapassando recebe um banimento temporário, o que é um dia bem pior.
O 2026.7 adiciona um limitador de taxa no lado do cliente a TsgcHTTPAPI_client, então todo cliente REST pronto o herda. É uma janela deslizante: no máximo MaxRequests requisições em qualquer janela de IntervalMs. Você o configura a partir das regras publicadas pela exchange, porque o limite da exchange é o único que importa:
uses
sgcHTTP_API, sgcHTTP_API_Binance;
var
oBinance: TsgcHTTP_API_Binance_Rest;
begin
oBinance := TsgcHTTP_API_Binance_Rest.Create(nil);
try
oBinance.RateLimit.Enabled := True;
oBinance.RateLimit.IntervalMs := 60000; // one minute window
oBinance.RateLimit.MaxRequests := 1000; // stay under the published budget
oBinance.RateLimit.Behavior := rlbWait; // default
// Every request through this component now takes a slot first.
oBinance.GetAccountInformation;
finally
oBinance.Free;
end;
end;
A forma clássica de acabar limitado é a rajada na inicialização. A aplicação sobe e dispara em paralelo a carga da lista de símbolos, dos saldos, das ordens abertas e dos últimos candles de quarenta instrumentos, tudo no primeiro segundo. Nada nisso é irracional, e ainda assim a exchange conta como quarenta requisições em um segundo. O limitador suaviza exatamente esse formato de tráfego sem que você precise espalhar chamadas de Sleep pelo seu código de inicialização.
O limitador é criado de forma preguiçosa. Se você nunca tocar em RateLimit, nenhum objeto é alocado e o caminho da requisição é byte a byte o que era antes, então não há custo algum quando você não o usa.
Esperar ou rejeitar
Quando o orçamento da janela atual se esgota, você escolhe o que acontece com a próxima chamada. Isso é o Behavior, e é uma decisão de verdade, não um simples botão de ajuste.
rlbWait, o padrão, bloqueia a chamada até que uma vaga fique livre e então a envia. É o que você quer em um worker em segundo plano que está carregando histórico ou reconciliando posições. O trabalho demora um pouco mais e tudo é concluído.
rlbReject levanta EsgcHTTPRateLimit imediatamente e não envia nada. É o que você quer quando uma requisição atrasada é pior do que nenhuma requisição. Uma ordem que chega três segundos depois de você decidir enviá-la pode ser uma ordem que você não quer mais, e dispará-la em um mercado em movimento é pior do que falhar de forma clara:
uses
SysUtils, sgcHTTP_API, sgcHTTP_API_Binance;
begin
oBinance.RateLimit.Enabled := True;
oBinance.RateLimit.IntervalMs := 1000;
oBinance.RateLimit.MaxRequests := 10;
oBinance.RateLimit.Behavior := rlbReject;
try
oBinance.NewOrder('BTCUSDT', 'BUY', 'LIMIT', ...);
except
on E: EsgcHTTPRateLimit do
// Budget exhausted. Drop the order rather than send it stale.
LogWarning('rate limit hit, order not sent: ' + E.Message);
end;
end;
Uma configuração comum é usar os dois, com dois componentes: rlbWait no componente que faz a carga em massa, e rlbReject no componente que envia ordens, cada um com seu próprio orçamento.
Este não é o limitador de taxa do lado do servidor
Vale ser explícito, porque os nomes são parecidos. O sgcWebSockets 2026.5 trouxe o TsgcWSRateLimiter, que é um limitador do lado do servidor: ele protege o seu servidor dos seus clientes, limitando o que uma conexão de entrada pode enviar para você. O deste artigo aponta para o lado oposto. É um limitador do lado do cliente que protege você dos limites de outra pessoa, limitando o que sua aplicação envia para uma exchange. São independentes, e uma aplicação que é ao mesmo tempo um servidor e um consumidor de exchange vai usar os dois sem problema.
Não é só para cripto
RateLimit vive no cliente HTTP API base, então é herdado por todos os clientes REST prontos da biblioteca, não apenas os das exchanges. Os clientes de IA têm limites de requisições exatamente do mesmo tipo, então OpenAI, Anthropic e Gemini também o recebem, assim como Stripe e o restante das integrações de API. A propriedade está no mesmo lugar, com as mesmas quatro configurações:
uses
sgcHTTP_API, sgcHTTP_API_OpenAI;
begin
oOpenAI.RateLimit.Enabled := True;
oOpenAI.RateLimit.IntervalMs := 60000;
oOpenAI.RateLimit.MaxRequests := 500; // your tier's requests per minute
oOpenAI.RateLimit.Behavior := rlbWait;
end;
Se a sua conta está em um plano com um teto baixo de requisições por minuto, esta é a maneira mais barata de impedir que um lote paralelo o estoure.
Disponibilidade
A reinscrição automática e o limitador de taxa no lado do cliente estão disponíveis no sgcWebSockets 2026.7 em Delphi 7 até 13 e C++Builder, em Win32/Win64, Linux64, macOS, Android e iOS. Ambos vêm desligados por padrão, então a atualização é direta.
Clientes com assinatura ativa podem baixar a nova versão na área de clientes. Usuários em avaliação podem obter o instalador atualizado em esegece.com/products/websockets/download.
Dúvidas, comentários ou ajuda para integrar isso ao seu app de trading? Entre em contato, você receberá a resposta de quem escreveu o código.
