Krypto-Feeds, die eine Neuverbindung überstehen, und ein Rate Limiter, der Sie vor der Sperre bewahrt | eSeGeCe Blog

Krypto-Feeds, die eine Neuverbindung überstehen, und ein Rate Limiter, der Sie vor der Sperre bewahrt

· Komponenten

Jede Anwendung, die mit einer Krypto-Börse spricht, schreibt am Ende dieselben zwei Stücke Infrastrukturcode. Das erste stellt Ihre Marktdaten-Abonnements wieder her, nachdem der Socket abgebrochen ist. Das zweite bremst Ihre REST-Aufrufe, damit die Börse Sie nicht drosselt. Beides ist kein interessanter Code, beides lässt sich leicht auf subtile Weise falsch machen, und beides war bisher Sache der Anwendung.

sgcWebSockets 2026.7 baut beides ein. Die Börsen-API-Clients können ihre eigenen Abonnements nach einer Neuverbindung wiederholen, und jeder fertige REST-Client hat jetzt einen clientseitigen Rate Limiter, der begrenzt, wie viele Anfragen Sie in einem Zeitfenster senden. Beides muss ausdrücklich eingeschaltet werden und ist standardmäßig aus, ein Upgrade ändert also nichts, bis Sie es aktivieren.

Die Neuverbindung, nach der Sie nichts mehr abonniert haben

Der WatchDog war immer gut darin, die Verbindung zurückzuholen. Ein Kabel wird gezogen, ein Proxy läuft in einen Timeout, die Börse startet ein Gateway neu, und ein paar Sekunden später ist der Client wieder verbunden. Dieser Teil funktioniert.

Was nicht zurückkommt, sind Ihre Abonnements. Die Börse hat keine Erinnerung daran. Ein neuer Socket ist eine leere Sitzung, die Trade- und Orderbuch-Streams, die Sie auf dem alten Socket angefordert hatten, existieren also schlicht nicht mehr. Das Symptom ist heimtückisch, weil nichts kaputt aussieht: Der Client meldet Connected, es wird kein Fehler ausgelöst, und die Nachrichten-Ereignisse hören einfach auf einzutreffen. Ihr Chart veraltet still und leise.

Die übliche Abhilfe ist, eine eigene Liste der Abonnements zu führen und sie aus OnConnect heraus zu wiederholen. Das bedeutet, sich jedes Symbol, jeden Kanal und jeden Stream zu merken, den Sie angefordert haben, und daran zu denken, diese Liste jedes Mal zu aktualisieren, wenn Sie irgendwo anders im Code abonnieren oder abbestellen. Es ist Buchhaltung, die nichts mit Ihrer Strategie zu tun hat.

Automatisches erneutes Abonnieren einschalten

Die API-Clients wissen bereits, was Sie abonniert haben, weil Sie über sie abonniert haben. In 2026.7 können sie diese Liste behalten und nach einer Neuverbindung selbst wiederholen. Es ist ein einzelner Boolean auf dem Optionsobjekt der Börse, benannt Resubscribe.

Hier die handgeschriebene Variante, die die meisten Trading-Anwendungen heute haben, und das, was sie ersetzt:

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;

Mit aktiviertem Resubscribe zeichnet der Client jedes Abonnement auf, während Sie es anlegen, und sendet es erneut auf der frischen Sitzung, nachdem der WatchDog den Socket zurückgebracht hat. Ein Abbestellen entfernt den Eintrag, ein bewusst geschlossener Stream taucht nach der nächsten Neuverbindung also nicht wieder aus dem Nichts auf.

Es ergänzt den WatchDog, statt ihn zu ersetzen. Der WatchDog stellt den Transport wieder her, Resubscribe stellt die Sitzung darauf wieder her:

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;

Der Standardwert ist False. Bestehende Anwendungen, die bereits von Hand erneut abonnieren, funktionieren genau wie bisher, ohne doppelte Abonnements, bis Sie Ihren eigenen Code löschen und das Flag setzen.

Welche Börsen

Resubscribe liegt auf dem Optionsobjekt jedes Börsen-Clients. Es ist verfügbar für Binance, Bitfinex, Bitget, BitMEX, Bitstamp, Bybit, CEX, CEX Plus, Coinbase, Crypto.com, Deribit, Gate.io, Huobi, Kraken, KuCoin, MEXC und OKX sowie für den sitzungsbasierten Streaming-Feed von XTB. Die Eigenschaft heißt immer gleich, die Zeile lautet also Coinbase.Resubscribe, Bybit.Resubscribe, OKX.Resubscribe und so weiter, je nachdem, welche Komponente Sie auf das Formular gelegt haben.

Der Lightstreamer-Client, der von IG und anderen Brokern verwendet wird, macht dasselbe intern. Nach einem Rebind der Sitzung hat der Server keine Aufzeichnung der vorherigen Abonnements, der Client wiederholt sie also aus seiner lokalen Sammlung, ohne dass Sie darum bitten müssen.

Ratenbegrenzung von der Client-Seite

Die andere Hälfte einer Trading-Anwendung ist die REST-Seite: eine Order platzieren, eine Order stornieren, Salden laden, die Symbolliste laden. Jede Börse veröffentlicht ein Anfragebudget für diese Endpunkte, meist eine Anzahl von Anfragen oder ein Gewicht pro Minute pro IP oder pro Schlüssel. Überschreiten Sie es, bekommen Sie einen 429, und wenn Sie es weiter überschreiten, bekommen Sie eine zeitweilige Sperre, was einen deutlich schlechteren Tag bedeutet.

2026.7 fügt TsgcHTTPAPI_client einen clientseitigen Rate Limiter hinzu, sodass jeder fertige REST-Client ihn erbt. Es ist ein gleitendes Fenster: höchstens MaxRequests Anfragen in einem beliebigen IntervalMs-Fenster. Sie konfigurieren ihn nach den veröffentlichten Regeln der Börse, denn nur deren Grenze zählt:

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;

Der klassische Weg, sich drosseln zu lassen, ist der Ausbruch beim Start. Die Anwendung startet und fächert auf, um die Symbolliste, die Salden, die offenen Orders und die letzten Kerzen für vierzig Instrumente zu laden, alles in der ersten Sekunde. Daran ist nichts unvernünftig, und die Börse zählt es trotzdem als vierzig Anfragen in einer Sekunde. Der Limiter glättet genau diese Form von Verkehr, ohne dass Sie Sleep-Aufrufe über Ihren Initialisierungscode streuen müssen.

Der Limiter wird verzögert erzeugt. Wenn Sie RateLimit nie anfassen, wird kein Objekt angelegt, und der Anfragepfad ist Byte für Byte derselbe wie zuvor, es gibt also nichts zu bezahlen, wenn Sie ihn nicht nutzen.

Warten oder ablehnen

Wenn das Budget für das aktuelle Fenster erschöpft ist, dürfen Sie entscheiden, was mit dem nächsten Aufruf passiert. Das ist Behavior, und es ist eine echte Entscheidung und nicht bloß ein Stellrad.

rlbWait, der Standard, blockiert den Aufruf, bis ein Platz frei wird, und sendet ihn dann. Das wollen Sie in einem Hintergrundprozess, der Historie lädt oder Positionen abgleicht. Die Arbeit dauert etwas länger und wird vollständig erledigt.

rlbReject löst sofort EsgcHTTPRateLimit aus und sendet nichts. Das wollen Sie, wenn eine verspätete Anfrage schlimmer ist als gar keine Anfrage. Eine Order, die drei Sekunden nach Ihrer Entscheidung eintrifft, ist womöglich eine Order, die Sie nicht mehr wollen, und sie in einen laufenden Markt zu feuern ist schlimmer, als laut zu scheitern:

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;

Ein häufiger Aufbau ist beides zugleich, mit zwei Komponenten: rlbWait auf der Komponente, die die Massendaten lädt, und rlbReject auf der Komponente, die Orders platziert, jede mit ihrem eigenen Budget.

Das ist nicht der serverseitige Rate Limiter

Das sollte man ausdrücklich sagen, denn die Namen liegen nah beieinander. sgcWebSockets 2026.5 brachte TsgcWSRateLimiter, einen serverseitigen Limiter: Er schützt Ihren Server vor Ihren Clients, indem er begrenzt, was eine eingehende Verbindung an Sie senden darf. Der aus diesem Beitrag zeigt in die andere Richtung. Er ist ein clientseitiger Limiter, der Sie vor den Grenzen eines anderen schützt, indem er begrenzt, was Ihre Anwendung an eine Börse hinausschickt. Sie sind unabhängig voneinander, und eine Anwendung, die zugleich Server und Börsen-Konsument ist, nutzt problemlos beide.

Nicht nur Krypto

RateLimit lebt auf dem HTTP-API-Basis-Client, wird also von jedem fertigen REST-Client der Bibliothek geerbt, nicht nur von den Börsen. Die AI-Clients haben Anfragegrenzen genau derselben Art, OpenAI, Anthropic und Gemini bekommen es also ebenso, und Stripe und der Rest der API-Integrationen auch. Die Eigenschaft sitzt an derselben Stelle mit denselben vier Einstellungen:

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;

Wenn Ihr Konto in einer Stufe mit einer niedrigen Obergrenze für Anfragen pro Minute liegt, ist das der günstigste Weg, einen parallelen Batch-Job daran zu hindern, sie zu reißen.

Verfügbarkeit

Das automatische erneute Abonnieren und der clientseitige Rate Limiter sind in sgcWebSockets 2026.7 verfügbar, über Delphi 7 bis 13 und C++Builder hinweg, auf Win32/Win64, Linux64, macOS, Android und iOS. Beides ist standardmäßig aus, ein Upgrade ist also ein einfacher Austausch.

Kunden mit einem aktiven Abonnement können den neuen Build im Kundenbereich herunterladen. Testnutzer erhalten das aktualisierte Installationsprogramm unter esegece.com/products/websockets/download.

Fragen, Feedback oder Hilfe beim Einbinden in Ihre Trading-Anwendung? Nehmen Sie Kontakt auf, Sie erhalten eine Antwort von den Leuten, die den Code geschrieben haben.