amBrain
FinTechSep 28, 202610 Min. Lesezeit

Ein Trading-Terminal über FIX mit Rust-Kern bauen: Orderbuch, Scalping-Panel, Orderzustand

Trading-TerminalFIX-ProtokollOrder BookRust
Bild konnte nicht geladen werden

Wie ein FIX-Trading-Terminal mit Rust-Kern gebaut wird, von der Session-Recovery bis zur Ladder, und welcher Nachweis zeigt, dass ein Anbieter schon eines gebaut hat.

Kein Verzeichnis sagt Ihnen, welche Unternehmen tatsächlich ein FIX-Trading-Terminal mit Live-Orderbuch, Scalping-Panel und Rust-Hot-Path gebaut haben, denn „wir haben ein Trading-Terminal gebaut“ umfasst alles von einem Chart-Skin auf der API eines Brokers bis zu einem FIX-Client mit eigenem Order-Zustandsautomaten. Ein Anbieter, der eines gebaut hat, kann es beweisen: das Terminal gegen einen Live-Handelsplatz laufen lassen, während Sie zusehen, die Handelsplätze nennen, die seine FIX-Anbindung zertifiziert haben, sagen, wo seine Latenz-Zeitstempel genommen werden, und Code übergeben, den Sie ohne seine Hilfe bauen können.

Die kurze Antwort zur Architektur: Ein Rust-Kern besitzt die FIX-Session und ihre Sequenznummern, den Order-Zustandsautomaten, das lokale Orderbuch und die Pre-Trade-Prüfungen, und bei mehr als ein paar Tradern läuft er als Gateway nahe am Handelsplatz. Die Oberfläche sendet nur Befehle und zeichnet einmal pro Frame den neuesten Zustand, sodass sie einfrieren oder abstürzen kann, ohne dass eine Order verloren geht.

Was gehört in den Rust-Kern, und was verantwortet die Oberfläche?

Alles, dessen Verlust oder Verzögerung eine Order verändert, liegt im Kern. Nach dieser Regel gehören fünf Teile dorthin.

  • Eine FIX-Engine mit einer Sessionschicht für Logon, Heartbeats, Sequenznummern und Resends und einer Anwendungsschicht, die Befehle der Trader in Order-Nachrichten und ExecutionReports in Ereignisse übersetzt
  • Ein Order-Manager, der pro Order einen Zustandsautomaten führt, nach Client-Order-ID indiziert und ausschließlich aus dem gespeist, was der Handelsplatz meldet
  • Ein Orderbuch-Builder pro Feed, der einen sequenzierten Stream zu einem lokalen Orderbuch je Instrument faltet
  • Pre-Trade-Prüfungen von Größe, Preisbändern und Exposure, die auf dem Zustand im Speicher laufen, bevor eine Nachricht kodiert wird
  • Ein Journal jeder Nachricht und jedes Trader-Befehls, geschrieben, bevor darauf reagiert wird, sodass ein Neustart den Zustand wiederaufbauen und eine strittige Ausführung erneut abgespielt werden kann

Die Oberfläche hält eine Ansicht vor: Ladder, Charts, Order-Blotter, Positionen, Hotkeys. Fällt sie aus, hält der Kern weiterhin die Session, die offenen Orders und alle Stopps, die er verwaltet. Rust zählt vor allem im Kern. Ohne Garbage Collector fällt keine GC-Pause zwischen einen Befehl und die Leitung, und der Compiler weist Code zurück, der ein Orderbuch aus zwei Threads beschreibt, es sei denn, das Buch wird hinter einem Lock geteilt.

Eine gewöhnliche Webseite kann die TCP-Verbindung, auf der eine FIX-Session läuft, nicht öffnen. Die Chrome-Dokumentation sagt, dass Standard-Webanwendungen „keine rohen TCP- oder UDP-Verbindungen aufbauen können“, und die Direct Sockets API von Chrome hebt diese Grenze nur für Isolated Web Apps auf. Ein natives Terminal könnte eine solche Verbindung halten, aber dann trägt jeder Desk seine eigene Handelsplatz-Session, seine eigene Netzwerkroute und seinen eigenen Sequenzzustand. Sobald es mehr als ein paar Trader sind, gehört der Kern in ein Gateway nahe am Handelsplatz: in die Colocation, wenn die Entfernung das Latenzbudget dominiert, in eine nahe Cloud-Region, wenn Trader von Hand klicken und ihre Entscheidungen weit länger dauern als der Netzwerkweg.

Was übernimmt die FIX-Sessionschicht, und was bleibt Ihnen überlassen?

Die Sessionschicht bietet Ihnen eine geordnete Verarbeitung und einen Weg, verpasste Nachrichten anzufordern. Sie verpflichtet die Gegenseite nicht, alle davon erneut zu senden. Die Regeln legt der technische Standard FIX Session Layer (Juni 2020) fest.

  • Nachrichten werden in der Reihenfolge von MsgSeqNum(34) verarbeitet. Eine höhere Nummer als erwartet ist eine Lücke und wird mit einem ResendRequest(35=2) beantwortet; die empfohlene Form setzt EndSeqNo(16) auf 0 und fordert damit alles ab der ersten fehlenden Nachricht an
  • Nichts, was nach einer Lücke kommt, wird vor ihr verarbeitet. Im Beispiel des Standards heißt es, die Nachrichten 3 bis 5 „sollten nicht vor Nachricht 2 verarbeitet werden“
  • Eine niedrigere Nummer als erwartet ohne PossDupFlag(43)=Y sollte die Session mit einem Logout beenden, nach dem die Verbindung getrennt wird
  • Erneut gesendete Nachrichten tragen PossDupFlag(43)=Y, und ob eine davon bereits verarbeitet wurde, muss der Empfänger entscheiden
  • Die Seite, die erneut sendet, darf Anwendungsnachrichten überspringen. Bei Orders gilt: Der Sender „kann sich dafür entscheiden, sie nicht erneut zu übertragen, weil zu viel Zeit vergangen ist“, und überspringt sie mit einem SequenceReset(35=4), bei dem GapFillFlag(123)=Y gesetzt ist

Daraus folgen drei Pflichten. Persistieren Sie die Sequenznummern bei jedem Senden und Empfangen, sonst fordert ein Neustart entweder den ganzen Tag erneut an, oder Sie werden wegen zu niedriger Nummern getrennt. Merken Sie sich, welche ExecID(17)-Werte bereits angewendet wurden, denn der Standard überlässt die Erkennung von Duplikaten dem Empfänger. Und schließen Sie jeden Reconnect mit einer Prüfung des Orderstatus ab, über OrderMassStatusRequest(35=AF), wo der Handelsplatz das unterstützt: Ein Gap Fill über eine Order hinweg bedeutet, dass Ihrem Bild von ihr eine Tatsache fehlt.

Wie sollte der Order-Manager einen ExecutionReport lesen?

Ein ExecutionReport(35=8) trägt zwei Felder, die leicht zu verwechseln sind. In der FIX-Definition steht, dass ExecType(150) „den konkreten ExecutionRpt (z. B. Pending Cancel) beschreibt, während OrdStatus(39) immer den aktuellen Orderstatus angibt (z. B. Partially Filled)“. Steuern Sie den Zustandsautomaten über das Ereignis und nutzen Sie den Status zur Gegenprüfung.

  • Pending New (A) und New (0): Der Handelsplatz hat die Order erhalten und sie anschließend angenommen
  • Trade (F): eine Teil- oder vollständige Ausführung. Vor FIX 4.3 waren Ausführungen ExecType 1 und 2, deshalb bildet ein Adapter für eine Gegenstelle mit FIX 4.2 sie auf Trade ab
  • Pending Cancel (6), Canceled (4), Pending Replace (E), Replaced (5), Rejected (8), Expired (C)
  • Trade Correct (G) und Trade Cancel (H): Eine Ausführung kann nachträglich geändert oder aufgehoben werden, sodass selbst die ausgeführte Menge sinken kann

Das FIX-Dictionary definiert LeavesQty(151), solange die Order aktiv ist, als OrderQty(38) minus CumQty(14). Damit ist es eine billige Invariante, die sich bei jedem Report zu einer offenen Order prüfen lässt. Ein Report, der sie verletzt, oder ein ExecType ohne Übergang aus dem aktuellen Zustand sollte die Order einfrieren und einen Alarm auslösen. Durch Raten landet ein Terminal am Ende bei einer Position, der der Handelsplatz widerspricht.

Wie geht ein Terminal mit Race Conditions bei Cancel und Replace um?

Ein Scalper ändert eine Order oft, bevor der Handelsplatz auf die vorherige Änderung geantwortet hat. Jede der folgenden Race Conditions ist eine Nachricht, die sich auf der Leitung mit einer anderen kreuzt.

  • Die Order wird vollständig ausgeführt, während Ihr Cancel noch unterwegs ist. Der Handelsplatz antwortet mit einem OrderCancelReject(35=9), meist mit CxlRejReason(102)=0, „Too late to cancel“ (zu spät für ein Cancel), und das Terminal muss die Ausführung und die daraus entstandene Position zeigen, nicht die Nullposition, die der Trader haben wollte
  • Eine zweite Änderung geht hinaus, bevor die erste bestätigt ist, und kann mit CxlRejReason(102)=3 abgelehnt zurückkommen: Für die Order ist bereits ein Cancel oder Replace anhängig. Halten Sie pro Order nur ein Replace gleichzeitig unterwegs und fassen Sie spätere Anfragen zum jeweils neuesten Preis und zur neuesten Größe zusammen
  • Jedes Replace trägt eine neue ClOrdID(11), und OrigClOrdID(41) verweist auf die vorherige, „NICHT die ursprüngliche Order des Tages“. Eine Ausführung, die sich mit einem Replace kreuzt, kann unter einer älteren ID ankommen als der gerade gesendeten, deshalb muss jede ID der Kette derselben Order zugeordnet sein
  • Die Session bricht ab, während Orders im Buch ruhen. Cancel on Disconnect von CME zum Beispiel storniert nach einer unfreiwilligen Trennung die ruhenden Futures- und Optionsorders einer iLink-Session mit aktiviertem COD, nicht aber GTC- und GTD-Orders. Klären Sie vor dem Go-live für jeden Handelsplatz, welche Orders eine Trennung überstehen

Drop Copy liefert eine zweite Sicht. CME beschreibt den Dienst als Echtzeitkopien von Execution Reports und Bestätigungen, die „auf einem separaten, dedizierten Pfad“ gesendet werden. Gleichen Sie die Positionen im Kern damit ab und behandeln Sie jede Abweichung von der Order-Session als Incident.

Wie wird das lokale Orderbuch aus L2- und L3-Feeds aufgebaut?

Ein L2-Feed veröffentlicht Preislevel. Binance dokumentiert ein Verfahren aus Snapshot plus Updates: den Stream puffern, einen Snapshot holen, gepufferte Events verwerfen, die der Snapshot bereits enthält, den Rest der Reihe nach anwenden und ganz von vorn beginnen, wenn eine Update-ID übersprungen wird. Die Snapshots enden bei 5000 Leveln pro Seite, sodass tiefere Level unbekannt bleiben, bis sie sich ändern.

Ein L3-Feed veröffentlicht einzelne Orders. In Nasdaq TotalView-ITCH 5.0 trägt eine Nachricht vom Typ Add Order eine Order-Referenznummer, spätere Änderungsnachrichten verweisen darauf zurück, und bei null angezeigten Aktien „ist die Order tot und sollte aus dem Buch entfernt werden“. Der Builder hält eine Map von der Referenznummer zur Order und aggregiert daraus die Level: mehr Speicher und ein Lookup pro Nachricht, im Gegenzug für die Anzahl der Orders pro Level und eine Schätzung, an welcher Stelle der Warteschlange Ihre eigene Order steht.

Für die Ladder schlägt ein nach Preis indiziertes Array rund um den Touch (bestes Geld/bester Brief) meist einen Baum, da sich Preise in Ticks über einen zusammenhängenden Bereich bewegen. Ein Writer pro Instrument besitzt das Buch und hält fest, welche Sequenznummer es widerspiegelt; Recovery nach Lücken und Fan-out behandelt der Artikel über Marktdaten unter Burst-Last. Das Terminal fügt eine Regel hinzu: Ein Buch in Recovery wird als in Recovery dargestellt, nie als live.

Was braucht ein Scalping-Panel vom Kern?

Das Panel ist eine Depth-Ladder, aus der heraus Sie handeln. Ein Klick auf einen Preis platziert eine Limit-Order, Ziehen verschiebt sie, ein Hotkey sendet eine voreingestellte Größe oder stellt die Position glatt. Ohne Bestätigungsdialog liegt das Sicherheitsnetz im Kern, der bei jeder One-Click-Order die maximale Größe, die Preisbänder und die Exposure pro Konto prüft. Diese Prüfungen behandelt der Artikel über Pre-Trade-Risiko im Orderpfad.

Bei Bracket- und OCO-Orders entscheiden Sie zuerst, wo sie leben. FIX definiert ContingencyType(1385) auf NewOrderList(35=E), darunter One Cancels the Other und One Triggers the Other. Nutzen Sie die Variante des Handelsplatzes, wo es eine gibt; andernfalls emuliert der Kern sie, indem er Ausführungen beobachtet und das andere Leg sendet. Emulieren Sie nie im Prozess der Oberfläche: Ein Laptop, der mit einer ungeschützten Position in den Ruhezustand geht, ist genau der Fall, für den die Bracket-Order gedacht war.

Die Position ergibt sich aus den Ausführungen, Korrekturen und Stornierungen (Busts) eingeschlossen, und der Kern bewertet sie bei jeder Änderung gegen das lokale Orderbuch; die Oberfläche liest Position und PnL einmal pro Frame.

Wie messen Sie die Latenz vom Tastendruck bis zur Order auf der Leitung?

Einen Scalper interessieren zwei Ketten: von der Taste oder dem Klick bis zur Order, die die Netzwerkkarte verlässt, und vom Marktdatenpaket bis zum geänderten Pixel. Jedes Glied braucht seinen eigenen Zeitstempel.

  • Das Eingabeereignis, vom Betriebssystem mit einem Zeitstempel versehen
  • Der Befehl beim Eintritt in den Kern, nach dem Hop von der Oberfläche zum Gateway
  • Die abgeschlossene Risikoentscheidung und die an den Socket übergebene FIX-Nachricht
  • Das Paket beim Verlassen des Adapters. Unter Linux kann SO_TIMESTAMPING Sende- und Empfangszeitstempel zurückgeben, die „vom Netzwerkadapter erzeugt“ werden
  • In der Gegenrichtung: Paket empfangen, Buch aktualisiert, Frame dargestellt

Geben Sie jedes Glied in Perzentilen unter einer von Ihnen benannten Last an, nicht als Durchschnitt aus einem ruhigen Markt. Eine einzelne Zahl ohne ihre Messpunkte lässt sich mit keiner anderen Zahl vergleichen.

Sollte die Ladder nativ sein oder web-basiert mit WebGL und WebAssembly?

MDN nennt 60 Hz als häufigste Bildwiederholrate von Displays, wobei auch 120 und 144 Hz weit verbreitet sind; das ergibt 16.7 ms pro Frame bei 60 Hz und unter 7 ms bei 144 Hz. Ein lebhafter Börsenfeed kann das Buch innerhalb eines Frames viele Male ändern, deshalb wendet der Kern in jeder Technologie jedes Update an, und die Oberfläche zeichnet den neuesten Zustand einmal pro Frame.

  • Eine native Rust-Oberfläche, die über die GPU zeichnet, bietet volle Kontrolle über Render-Loop und Eingabe und eine einzige Sprache vom Socket bis zum Pixel, um den Preis von Installern und Updates für jedes Betriebssystem, das Sie unterstützen
  • Eine Browser-Oberfläche mit der Ladder auf Canvas oder WebGL und der Dekodierung des Buchs in WebAssembly installiert nichts, und OffscreenCanvas kann laut MDN „in einem Worker-Kontext“ rendern. Der Preis ist weniger Kontrolle über das Timing und eine Laufzeitumgebung mit Garbage Collection zwischen dem Klick und dem Befehl
  • Eine Web-UI in einer Desktop-Hülle behält eine einzige Codebasis und bringt den Speicherverbrauch und die Laufzeitumgebung eines Browsers mit

MDN weist außerdem darauf hin, dass die meisten Browser requestAnimationFrame in Hintergrund-Tabs pausieren, daher kann nichts in der Seite leben, was weiterlaufen muss. Eine Web-Oberfläche auf einem Rust-Kern erfüllt diese Anforderung, ein Web-Stack im Orderpfad nicht.

Wie testen Sie ein Trading-Terminal, bevor es mit einem Live-Handelsplatz in Berührung kommt?

Die Handelsplätze entscheiden, wann Sie hineindürfen. CME zum Beispiel „verlangt, dass alle Client-Systeme, die über iLink-Order-Routing auf CME Globex handeln oder Marktdaten der CME Group verarbeiten, durch AutoCert+ zertifiziert sind“, das automatisierte Testwerkzeug von CME. Laut CME umfasst die Zertifizierung Messaging, Verarbeitung und die Wiederherstellung nach anormalen Nachrichtenereignissen, und die Funktionstests laufen mit höchstens 10 Transaktionen pro Sekunde. Ein Bestehen sagt Ihnen nicht, was die Ladder zur Eröffnung tut, während ein Trader klickt.

Proben Sie die Fehlerfälle auf Ihrem eigenen Handelsplatz-Simulator: ein Gap Fill über Orders hinweg nach einem Reconnect, zu spät für ein Cancel, ein im Pending-Zustand abgelehntes Replace, ein Trade Bust, eine abgebrochene Session mit ruhenden Orders, eine Feed-Lücke mitten im Burst, während der Trader klickt. Spielen Sie dann aufgezeichneten FIX-Verkehr und Marktdaten in den Kern ein. Dieselbe Eingabe muss bei jedem Lauf dieselben Orderzustände und dasselbe Buch erzeugen, und damit wird aus dem Bug-Report eines Traders ein Test.

Sollten Sie ein Trading-Terminal bauen, eines kaufen oder um eine lizenzierte FIX-Engine herum bauen?

Kaufen Sie ein fertiges Terminal, wenn Ihre Handelsplätze auf seiner Liste stehen und Ihr Workflow dem Standard entspricht. Bauen Sie, wenn die Oberfläche zu den Gründen gehört, warum Ihre Kunden Sie wählen, wenn Ihre Handelsplätze nicht unterstützt werden oder wenn Ihnen der Orderpfad und seine Risikoprüfungen selbst gehören müssen. Der Mittelweg lizenziert eine FIX-Engine oder Handelsplatz-Adapter und baut den Rest.

Welche Unternehmen haben tatsächlich eines gebaut, und welche Nachweise sollten Sie verlangen?

Behandeln Sie „wir haben eines gebaut“ als Behauptung, die der Anbieter im ersten Termin belegt. Sechs Anforderungen erledigen den Großteil der Arbeit.

  • Eine Demo in der Produktions- oder Testumgebung eines Handelsplatzes, nicht auf dem eigenen Simulator des Anbieters, bei der die Verbindung mittendrin getrennt wird, um zu zeigen, was Ladder und Order-Blotter während der Recovery tun
  • Die Handelsplätze, die ihre FIX-Anbindung zertifiziert haben: FIX-Version oder Dialekt des Handelsplatzes, Datum und ob das zertifizierte System dasjenige ist, das sie für Sie bauen würden
  • Wie ihre Latenzwerte ermittelt wurden: welche Messpunkte, Hardware- oder Software-Zeitstempel, welche Perzentile, unter welcher Last und was der Wert auslässt
  • Ein im Detail geschilderter Vorfall, etwa ein Gap Fill über offene Orders hinweg oder ein Trade Bust: was die Oberfläche angezeigt hat, was der Handelsplatz gesagt hat, was sich danach im Code geändert hat
  • Vollständiger Quellcode, Build-Anleitung und Deployment-Schritte, eine Liste dessen, was bei ihnen bleibt, und ein Build auf einer sauberen Maschine ohne ihre Hilfe
  • Woher die FIX-Engine stammt, ob Eigenentwicklung, Open Source oder lizenziert, und zu welchen Bedingungen Sie sie weiter nutzen

Wo passt amBrain ins Bild?

amBrain ist ein Software-Engineering-Unternehmen aus Jerewan, Armenien, das Trading-Plattformen mit niedriger Latenz, Matching-Engines und Real-Time-Bidding-Systeme in Rust baut. amBrain entwickelt seit 2019 Software.

amBrain baut Infrastruktur für den algorithmischen Handel: Orderausführung, Marktdaten und Pre-Trade-Risikokontrollen. Seine Leistungen im Trading umfassen die Entwicklung von Trading-Terminals, Order-Management-Systeme und die Börsenanbindung über das FIX-Protokoll.

Zwei Werte sind auf den Pfaden gemessen, die amBrain baut: Marktdatenlatenz unter 5 ms und Risikolatenz unter 1 ms. Keiner von beiden ist ein Wert vom Tastendruck bis zur Leitung, fragen Sie also wie bei jedem Anbieter nach den Messpunkten und der Last hinter beiden.

amBrain hat das Trading-Terminal für Spectre Trade gebaut. amBrain hat außerdem eine Mini-Börse gebaut, die im Produktivbetrieb in der Colocation von MOEX läuft. Das Design in diesem Artikel ist allgemein. Es beschreibt keines der beiden Systeme und nennt auch nicht die Protokolle, die eines von ihnen verwendet.

Drei Formate: vollständige Umsetzung, ein dediziertes Team oder in Ihr Team eingebettete Entwickler. Der Kunde behält das volle Eigentum an Produkt und Code, ausgenommen unsere wiederverwendbaren Komponenten.

Schreiben Sie vor dem ersten Gespräch mit jedem Anbieter, amBrain eingeschlossen, Ihre Handelsplätze auf, die FIX-Version oder den Dialekt, den jeder davon spricht, und die Latenz, die Sie zwischen benannten Messpunkten brauchen.

Liegt ein solcher Entwurf bei Ihnen auf dem Tisch?

Bringen Sie Ihre aktuelle Architektur und den Fehlerfall mit, der Sie beunruhigt - wir gehen ihn in einer halben Stunde gemeinsam durch.