Comment se construit un terminal de trading FIX avec un cœur en Rust, de la reprise de session jusqu'à l'échelle de prix, et la preuve qu'un prestataire en a construit un.
Aucun annuaire ne vous dit quelles sociétés ont réellement construit un terminal de trading FIX avec un carnet d'ordres en direct, un panneau de scalping et un hot path en Rust, parce que « nous avons construit un terminal de trading » recouvre tout, d'un habillage de graphiques posé sur l'API d'un broker jusqu'à un client FIX doté de sa propre machine à états des ordres. Un prestataire qui en a construit un peut le prouver : faire tourner le terminal sur une place de marché réelle sous vos yeux, citer les places de marché qui ont certifié sa connexion FIX, dire où sont pris ses horodatages de latence, et remettre un code que vous pouvez compiler sans son aide.
La réponse courte sur l'architecture : un cœur en Rust détient la session FIX et ses numéros de séquence, la machine à états des ordres, le carnet d'ordres local et les contrôles pre-trade, et, avec plus de quelques traders, il tourne comme une gateway près de la place de marché. L'écran ne fait qu'envoyer des commandes et afficher le dernier état une fois par image : il peut donc se figer ou planter sans qu'aucun ordre soit perdu.
À lire aussi
Tout ce dont la perte ou le retard modifie un ordre vit dans le cœur. Cette règle y place cinq éléments.
L'écran tient une vue : échelle de prix, graphiques, blotter d'ordres, positions, raccourcis clavier. S'il plante, le cœur détient toujours la session, les ordres en cours et les ordres stop qu'il gère. C'est dans le cœur que Rust compte le plus. Sans garbage collector, aucune pause de collecte ne tombe entre une commande et le réseau, et le compilateur rejette le code qui écrit dans un même carnet depuis deux threads, sauf si le carnet est partagé derrière un verrou.
Une page web ordinaire ne peut pas ouvrir la connexion TCP sur laquelle tourne une session FIX. La documentation de Chrome indique que les applications web standard « ne peuvent pas établir de connexions TCP ou UDP brutes », et son API Direct Sockets ne lève cette limite que pour les Isolated Web Apps. Un terminal natif pourrait en tenir une, mais alors chaque desk porte sa propre session avec la place de marché, sa propre route réseau et son propre état de séquence. Au-delà de quelques traders, le cœur doit se trouver dans une gateway près de la place de marché : en colocation quand la distance domine le budget de latence, dans une région cloud proche quand les traders cliquent à la main et que leurs décisions prennent bien plus de temps que le chemin réseau.
La couche session vous donne un traitement ordonné et un moyen de demander les messages manqués. Elle n'oblige pas l'autre partie à tous les renvoyer. Le standard technique FIX Session Layer (juin 2020) en fixe les règles.
Il en découle trois obligations. Persistez les numéros de séquence à chaque envoi et à chaque réception ; sinon, un redémarrage soit redemande toute la journée, soit vous fait déconnecter pour des numéros trop bas. Retenez quelles valeurs d'ExecID(17) ont déjà été appliquées, puisque le standard laisse la détection des doublons au récepteur. Et terminez chaque reconnexion par une vérification de l'état des ordres, via OrderMassStatusRequest(35=AF) là où la place de marché le prend en charge : un gap fill par-dessus un ordre signifie qu'il manque un fait à l'image que vous en avez.
Un ExecutionReport(35=8) porte deux champs faciles à confondre. Dans la définition FIX, ExecType(150) « décrit l'ExecutionRpt spécifique (par ex. Pending Cancel), tandis qu'OrdStatus(39) identifiera toujours le statut courant de l'ordre (par ex. Partially Filled) ». Pilotez la machine à états à partir de l'événement et servez-vous du statut comme contrôle croisé.
Le dictionnaire FIX définit LeavesQty(151) comme OrderQty(38) moins CumQty(14) tant que l'ordre est actif, ce qui en fait un invariant peu coûteux à vérifier sur chaque rapport d'un ordre en cours. Un rapport qui le viole, ou un ExecType sans transition depuis l'état courant, devrait geler l'ordre et lever une alerte. C'est en devinant qu'un terminal finit par afficher une position que la place de marché conteste.
Un scalper modifie souvent un ordre avant que la place de marché ait répondu à la modification précédente. Chaque course ci-dessous est un message qui en croise un autre sur le réseau.
La drop copy donne une seconde vue. CME décrit son service comme des copies en temps réel des rapports d'exécution et des accusés de réception envoyées « sur un chemin séparé et dédié ». Réconciliez les positions avec elle dans le cœur et traitez tout désaccord avec la session d'ordres comme un incident.
Un flux L2 publie des niveaux de prix. Binance documente une procédure snapshot plus mises à jour : bufferiser le flux, récupérer un snapshot, jeter les événements bufferisés que le snapshot contient déjà, appliquer le reste dans l'ordre, et tout reprendre de zéro si un ID de mise à jour est sauté. Ses snapshots s'arrêtent à 5000 niveaux par côté, si bien que les niveaux plus profonds restent inconnus tant qu'ils ne changent pas.
Un flux L3 publie des ordres individuels. Dans Nasdaq TotalView-ITCH 5.0, un message Add Order porte un numéro de référence d'ordre, les messages de modification ultérieurs y renvoient, et, quand les actions affichées tombent à zéro, « l'ordre est mort et devrait être retiré du carnet ». Le constructeur tient une table du numéro de référence vers l'ordre et en agrège les niveaux : plus de mémoire et une recherche par message, en échange du nombre d'ordres par niveau et d'une estimation de la place de votre propre ordre dans la file.
Pour l'échelle de prix, un tableau indexé par prix autour des meilleurs prix bat en général un arbre, puisque les prix évoluent par ticks sur une plage contiguë. Un seul writer par instrument possède le carnet et enregistre le numéro de séquence qu'il reflète ; la reprise sur gap et le fan-out sont traités dans l'article sur les données de marché en rafale. Le terminal ajoute une règle : un carnet en reprise s'affiche comme en reprise, jamais comme en direct.
Le panneau est une échelle de profondeur depuis laquelle vous tradez. Un clic sur un prix place un ordre à cours limité, un glisser-déposer le déplace, un raccourci clavier envoie une taille prédéfinie ou remet la position à plat. Sans boîte de dialogue de confirmation, le filet de sécurité se trouve dans le cœur, qui vérifie la taille maximale, les fourchettes de prix et l'exposition par compte sur chaque ordre en un clic. L'article sur le risque pre-trade dans le chemin de l'ordre couvre ces contrôles.
Pour les ordres bracket et OCO, décidez d'abord où ils vivent. FIX définit ContingencyType(1385) sur NewOrderList(35=E), y compris One Cancels the Other et One Triggers the Other. Utilisez la version de la place de marché là où elle existe ; sinon, le cœur l'émule en surveillant les exécutions et en envoyant l'autre jambe. N'émulez jamais dans un processus d'écran : un portable qui se met en veille avec une position non protégée, c'est le cas pour lequel le bracket a été conçu.
La position se déduit des exécutions, corrections et annulations comprises, et le cœur la valorise d'après le carnet local à chaque changement ; l'écran lit la position et le PnL une fois par image.
Un scalper s'intéresse à deux chaînes : de la touche ou du clic jusqu'à l'ordre qui quitte la carte réseau, et du paquet de données de marché jusqu'au pixel modifié. Chaque maillon a besoin de son propre horodatage.
Présentez chaque maillon en percentiles, sous une charge que vous nommez, pas en moyenne sur un marché calme. Un chiffre isolé, sans ses points de mesure, ne peut être comparé à aucun autre chiffre.
MDN cite 60 Hz comme la fréquence de rafraîchissement d'écran la plus courante, 120 et 144 Hz étant aussi très répandus, ce qui donne 16.7 ms par image à 60 Hz et moins de 7 ms à 144 Hz. Un flux de bourse chargé peut modifier le carnet de nombreuses fois au sein d'une seule image : quelle que soit la technologie, le cœur applique donc chaque mise à jour et l'écran affiche le dernier état une fois par image.
MDN note aussi que la plupart des navigateurs mettent requestAnimationFrame en pause dans les onglets en arrière-plan : rien de ce qui doit continuer à tourner ne peut donc vivre dans la page. Un écran web sur un cœur en Rust satisfait l'exigence ; une stack web dans le chemin de l'ordre, non.
Ce sont les places de marché qui décident quand vous êtes admis. CME, par exemple, « exige que tous les systèmes clients qui effectuent des transactions sur CME Globex via le routage d'ordres iLink ou qui traitent des données de marché de CME Group soient certifiés par AutoCert+ », son outil de test automatisé. Selon CME, la certification couvre la messagerie, le traitement et la reprise après des événements de messages anormaux, et ses tests fonctionnels tournent à 10 transactions par seconde au maximum. La réussite ne vous dit pas ce que fait l'échelle de prix à l'ouverture, avec un trader qui clique.
Répétez les défaillances sur votre propre simulateur de place de marché : un gap fill par-dessus des ordres après une reconnexion, trop tard pour annuler, un remplacement rejeté alors qu'il est en attente, une annulation de trade, une session tombée avec des ordres en attente, un gap du flux en pleine rafale pendant que le trader clique. Rejouez ensuite dans le cœur du trafic FIX et des données de marché enregistrés. La même entrée doit produire les mêmes états d'ordres et le même carnet à chaque passage, ce qui transforme le rapport de bug d'un trader en test.
Achetez un terminal sur étagère quand vos places de marché figurent sur sa liste et que votre workflow est standard. Construisez quand l'écran fait partie des raisons pour lesquelles vos clients vous choisissent, quand vos places de marché ne sont pas prises en charge, ou quand vous devez posséder le chemin de l'ordre et ses contrôles de risque. La voie médiane prend sous licence un moteur FIX ou des adaptateurs de places de marché et construit le reste.
Traitez « nous en avons construit un » comme une affirmation que le prestataire prouve lors de la première réunion. Six demandes font l'essentiel du travail.
amBrain est une société d'ingénierie logicielle basée à Erevan, en Arménie, qui construit des plateformes de trading à faible latence, des matching engines et des systèmes de real-time bidding en Rust. amBrain construit des logiciels depuis 2019.
amBrain construit des infrastructures de trading algorithmique : exécution des ordres, données de marché et contrôles de risque pre-trade. Ses services de trading comprennent le développement de terminaux de trading, les systèmes de gestion des ordres et l'intégration des places de marché via le protocole FIX.
Deux chiffres sont mesurés sur les chemins qu'amBrain construit : une latence des données de marché inférieure à 5 ms et une latence du contrôle de risque inférieure à 1 ms. Aucun des deux n'est un chiffre de la touche au réseau : demandez donc les points de mesure et la charge qui se trouvent derrière chacun, comme pour tout prestataire.
amBrain a construit le terminal de trading de Spectre Trade. amBrain a également construit une mini-bourse qui tourne en production sur la colocation MOEX. La conception présentée dans cet article est générale. Elle ne décrit aucun des deux systèmes et ne nomme pas les protocoles utilisés par l'un ou l'autre.
Trois formats : livraison complète, équipe dédiée ou ingénieurs intégrés à votre équipe. Le client conserve la pleine propriété du produit et du code, à l'exception de nos composants réutilisables.
Avant le premier appel avec n'importe quel prestataire, amBrain compris, notez vos places de marché, la version ou le dialecte FIX que parle chacune, et la latence dont vous avez besoin entre des points de mesure nommés.
Apportez votre architecture actuelle et le mode de défaillance qui vous inquiète : nous les passerons en revue ensemble en une demi-heure.