Bir spot matching engine, sert kısıtlarla çevrili küçük bir durum makinesidir: price-time priority, kısmi gerçekleşmeler, ani yük altında kıpırdamayan bir latency kuyruğu. Order book, eşleştirme döngüsü, journal ve replay düzeneği böyle kurulur - ve dilin yardımı burada biter.
Bir spot borsa matching engine'inin işi dardır. Sıralı bir komut akışını - yeni emir, iptal, değiştirme - alır, bunları price-time priority altında bir order book'a uygular ve sıralı bir olay akışı yayar: işlemler, defter güncellemeleri, retler, onaylar.
Zor olan her şey bu işin üstüne yığılmış üç kısıttan gelir: sonuç, aynı girdinin her replay'inde birebir aynı olmalı; kısmen gerçekleşen bir emrin kalanı kuyruktaki yerini korumalı; ve ani bir yük geldiğinde latency kuyruğu kıpırdamamalı.
Defter iki taraftır; her biri fiyata göre sıralanmış bir seviye koleksiyonudur. Bir seviye bir sayı değildir - o fiyattaki bekleyen emirlerin geliş sırasına göre dizilmiş bir kuyruğudur. Eşleştirme en iyi seviyeye sürekli, derin seviyelere ise nadiren dokunur; bu yüzden yapı zarafete göre değil, bu erişim örüntüsüne göre seçilir.
Intrusive kuyrukların ve indeks handle'larının sonucu şudur: bekleyen bir emir yaşadığı sürece bellekte hiç yer değiştirmez. Kuyruktaki konumu, nerede durduğunun değil bağlantılarının bir özelliğidir; ilerleyen aşamada kısmi gerçekleşmeleri ucuz kılan da budur.
Gelen agresif bir emir, karşı tarafı en iyi fiyattan içeriye doğru dolaşır. Her seviyede FIFO kuyruğunu baştan itibaren dolaşır. Seviye fiyatı gelen emir için artık kabul edilebilir olmadığında ya da gelen miktar sıfıra ulaştığında durur.
Kısmen gerçekleşen bekleyen bir emir yerini korur. Kalanı, özgün geliş sırasıyla kuyruğunun başında kalır; çünkü bir gerçekleşme yalnızca miktarı değiştirir, başka bir şeyi değil. Kısmen gerçekleşen ve düz bir limit olan agresif bir emir ise kendi fiyat seviyesinin sonunda, yeni bir geliş sırasıyla bekleyen emre dönüşür - şimdi geldi, daha önce değil.
Emir tipi semantiği, bu döngünün içinde değil sınırında alınan kararlardır. Immediate-or-cancel kalanı deftere koymak yerine düşürür. Fill-or-kill önce kuru bir geçiş yapar ve ya bütünüyle icra eder ya da reddeder. Post-only, emir gelişinde kesişecekse reddeder. Bunları döngünün dışında tutmak, döngünün defter durumunun değiştiği tek yer olarak kalması demektir.
Kendi kendine işlem engelleme, asgari miktarlar ve tick ile lot doğrulaması da döngüden önceye aittir. Eşleştirmeye ulaşan bir emrin düzgün biçimlendirildiği zaten kanıtlanmıştır; böylece döngüde onu yavaşlatacak ya da üzerinde anlaşmazlığa düşülecek hata dalları bulunmaz.
Ortalama latency nadiren sorundur. Sorun, ani yük anındaki en kötü ölçümdür - motorun en çok önem taşıdığı ve bir stop-the-world duraklamasının düşmesinin en muhtemel olduğu an. Garbage collector'lı yönetilen bir çalışma zamanında bu duraklamayı siz değil collector planlar ve tam da çöpü üreten yoğunluğun ortasına düşer.
Elle bellek ayırma, aynı sorunun daha küçük bir sürümüdür. Genel amaçlı bir ayırıcı free list'leri dolaşabilir, bir kilit alabilir ya da çekirdekten daha fazla bellek isteyebilir; bunu yapan çağrı da kuyrukta görünen çağrıdır. Çözüm her iki durumda da aynı: sıcak yolda hiç bellek ayırmayın.
Bir motor, aynı girdi dizisi farklı bir makinede ve bir yıl sonra bayt bayt aynı çıktı dizisini ürettiğinde deterministiktir. Eşleştirme yolu içinde duvar saatini, iş parçacığı zamanlamasını veya hash yineleme sırasını okuyan her şey bu özelliği bozar.
Bu yüzden zaman damgaları bir girdidir, motorun kendisi için okuduğu bir şey değil. Sequencer bir komutu kabul ederken damgalar ve eşleştirme döngüsü damgayı veri olarak ele alır. Rastgelelik gerekiyorsa, tohumu journal'ın parçası olan tohumlanmış bir üreteçten gelir.
Kurtarma, eşleştirme çalıştıktan sonra üstüne eklenen bir özellik değildir. Motor, kabul edilen komutları sıra düzeninde yalnızca ekleme yapılan bir journal'a yazar ve bellekteki defter, o journal'ın katlanmasının sonucundan başka bir şey değildir. Bir çökmeden sonra yeniden kurmak, onu replay etmek demektir.
Journal'ı motor yazar, ama kalıcılık depolama yolunun ve onay çıkmadan önce kaydın kaç makinede bulunduğunun bir özelliğidir. Bu bir replikasyon ve donanım kararıdır; kurtarma süresi de asıl orada kazanılır ya da kaybedilir.
Motoru test edilebilir kılan şey determinizmdir. Aynı girdi aynı çıktıyı verdiği için kaydedilmiş bir oturum bir regresyon testidir ve bir kez bulunan bir hata, peşinden koşulmak yerine birebir yeniden üretilebilir.
Bir referans model göründüğünden daha değerlidir. Aynı şartnameden yazılmış iki uygulama, tam da şartnamenin belirsiz kaldığı yerlerde ayrışır ve eşleştirme kuralları sınır durumlarda belirsizlikle doludur - kesişen limitler, sıfır kalanlar, gerçekleşmelerle yarışan iptaller.
Rust, döngüyü kendi başına hızlandırmaktan çok bir sorun sınıfını ortadan kaldırır. Garbage collector yoktur, dolayısıyla arkanızdan planlanan bir duraklama da yoktur. Ownership sayesinde tek yazıcı disiplini, bir kod incelemesinin fark etmesi gereken bir şey olmaktan çıkıp derleyicinin dayattığı bir şeye dönüşür. Lifetime'ı olmayan bir dilde hataya açık olan slab handle'ları ve intrusive bağlantılar burada denetlenebilir. Debug derlemelerinde tam sayı taşmasında oluşan panic'ler, bir defteri sessizce bozan bir hata sınıfını yakalar.
Dürüst sınır şu: kuyruk latency'sini belirleyen şeylerin çoğu dil değildir:
Rust'ın da bir bedeli var. Borrow checker, hâlâ oturmamış bir tasarımın ilk haftalarını yavaşlatır; borsaya özgü protokoller için ekosistem eski dillerdekinden daha incedir ve lock-free yapıların etrafındaki unsafe bloklar, başka her yerdeki eşdeğer kod kadar inceleme disiplini ister. Onu seçmek, geliştirici konforuyla ilgili değil, latency kuyruğu ve tek yazıcılı bir çekirdekte bellek güvenliğiyle ilgili bir karardır.
amBrain 2019'dan beri Erivan, Ermenistan'da trading altyapısı kuruyor; sıcak yollar Rust ile yazılıyor - piyasa verisi 5 ms altında, işlem öncesi risk kontrolleri 1 ms altında. Bir matching engine tasarlıyorsanız ve defter yapısını, journal formatını ya da replay düzeneğini birlikte gözden geçirmek istiyorsanız, bu konuşmayı sıcak yolun ilk satırı yazılmadan önce yapmaya değer.
Mühendislik ekibimiz FinTech çözümlerinde uzmanlaşmıştır. Projenizi nasıl hayata geçirebileceğimizi konuşalım.