amBrain
FinTechSep 28, 2026قراءة 10 دقائق

بناء طرفية تداول عبر FIX بنواة Rust: دفتر الأوامر ولوحة المضاربة السريعة وحالة الأوامر

طرفية التداولبروتوكول FIXOrder BookRust
تعذّر تحميل الصورة

كيف تُبنى طرفية تداول عبر FIX بنواة Rust، من استرداد الجلسة إلى سلّم الأسعار، والدليل الذي يُثبت أن المورّد قد بنى واحدة فعلًا.

لا يوجد دليل موردين يخبرك أي الشركات بنت فعلًا طرفية تداول عبر FIX بدفتر أوامر حي ولوحة مضاربة سريعة ومسار ساخن مكتوب بـ Rust، لأن عبارة «بنينا طرفية تداول» تشمل أي شيء، من واجهة رسوم بيانية فوق API وسيط إلى عميل FIX بآلة حالة أوامر خاصة به. والمورّد الذي بنى واحدة يستطيع إثبات ذلك: أن يشغّل الطرفية على منصة تداول حية وأنت تشاهد، وأن يسمّي منصات التداول التي اعتمدت اتصال FIX لديه، وأن يقول أين تؤخذ طوابعه الزمنية لقياس زمن الاستجابة، وأن يسلّمك كودًا تستطيع بناءه دون مساعدته.

الجواب المختصر عن البنية: نواة مكتوبة بـ Rust تملك جلسة FIX وأرقام تسلسلها، وآلة حالة الأوامر، ودفتر الأوامر المحلي، وفحوص ما قبل التداول، وحين يزيد عدد المتداولين على بضعة أفراد تعمل بوابةً قرب منصة التداول. ولا تفعل الشاشة سوى إرسال التعليمات ورسم أحدث حالة مرة واحدة في كل إطار، لذا يمكنها أن تتجمد أو تنهار دون أن يضيع أي أمر.

ما الذي ينتمي إلى نواة Rust، وما الذي تملكه الشاشة؟

كل ما يغيّر فقدانُه أو تأخرُه أمرَ تداول يسكن في النواة. وهذه القاعدة تضع فيها خمسة أجزاء.

  • محرك FIX، بطبقة جلسة لتسجيل الدخول (logon) ونبضات الـ heartbeat وأرقام التسلسل وإعادة الإرسال، وطبقة تطبيق تحوّل تعليمات المتداول إلى رسائل أوامر، ورسائل ExecutionReport إلى أحداث
  • مدير أوامر يحتفظ بآلة حالة واحدة لكل أمر، مفهرسة بمعرّف أمر العميل، ولا يغذّيها إلا ما تبلّغ عنه منصة التداول
  • مُنشئ دفتر لكل تغذية، يطوي تدفقًا مرقّمًا تسلسليًا في دفتر محلي لكل أداة
  • فحوص ما قبل التداول على الحجم ونطاقات الأسعار والانكشاف، تُجرى على الحالة في الذاكرة قبل ترميز الرسالة
  • سجل لكل رسالة ولكل تعليمة من المتداول، يُكتب قبل التصرف بناءً عليها، كي يمكن بعد إعادة الإقلاع بناء الحالة من جديد، ويمكن إعادة تشغيل تنفيذ متنازع عليه

تحتفظ الشاشة بعرض: سلّم الأسعار، والرسوم البيانية، وجدول الأوامر، والمراكز، ومفاتيح الاختصار. وإن توقفت عن العمل، تظل النواة ممسكة بالجلسة وبالأوامر العاملة وبأي أوامر إيقاف تديرها. وأكثر ما تظهر أهمية Rust في النواة. فلا يوجد جامع قمامة، ولذا لا تقع أي وقفة لجمع القمامة بين التعليمة وخروجها إلى الشبكة، ويرفض المترجم الكود الذي يكتب في دفتر واحد من خيطين ما لم يكن الدفتر مشتركًا خلف قفل.

لا تستطيع صفحة ويب عادية أن تفتح اتصال TCP الذي تعمل عليه جلسة FIX. فتوثيق Chrome يقول إن تطبيقات الويب القياسية «لا تستطيع إنشاء اتصالات TCP أو UDP خام»، وواجهة Direct Sockets API فيه لا ترفع هذا القيد إلا لتطبيقات Isolated Web Apps. والطرفية الأصلية (native) قادرة على الإمساك باتصال كهذا، لكن عندئذ يحمل كل مكتب تداول جلسته الخاصة مع منصة التداول ومساره الشبكي وحالة تسلسله. وحين يتجاوز عدد المتداولين بضعة أفراد، يكون مكان النواة في بوابة قرب منصة التداول: في الاستضافة المشتركة حين تهيمن المسافة على ميزانية زمن الاستجابة، وفي منطقة سحابية قريبة حين ينقر المتداولون يدويًا وتستغرق قراراتهم وقتًا أطول بكثير من المسار الشبكي.

ما الذي تتولاه طبقة جلسة FIX، وما الذي يُترك لك؟

تمنحك طبقة الجلسة معالجة مرتبة وطريقة لطلب الرسائل الفائتة. لكنها لا تُلزم الطرف الآخر بإعادة إرسالها كلها. والقواعد منصوص عليها في المعيار التقني FIX Session Layer (يونيو 2020).

  • تُعالَج الرسائل بترتيب MsgSeqNum(34). والرقم الأعلى من المتوقع فجوة يُرَدّ عليها بـ ResendRequest(35=2)؛ والصيغة الموصى بها تضبط EndSeqNo(16) على 0، فتطلب كل شيء بدءًا من أول رسالة مفقودة
  • لا يُعالَج أي شيء بعد الفجوة قبلها. ففي مثال المعيار، الرسائل من 3 إلى 5 «يجب ألا تُعالَج قبل الرسالة 2»
  • الرقم الأدنى من المتوقع دون PossDupFlag(43)=Y ينبغي أن ينهي الجلسة برسالة Logout، يُقطع الاتصال بعدها
  • الرسائل المعاد إرسالها تحمل PossDupFlag(43)=Y، والحكم بما إذا كانت إحداها قد عولجت من قبل مهمة المستقبِل
  • يجوز للطرف الذي يعيد الإرسال أن يتخطى رسائل التطبيق. ففي حالة الأوامر، فإن المرسل «قد يختار عدم إعادة إرسالها لأن وقتًا طويلًا جدًا قد انقضى»، ويقفز فوقها بـ SequenceReset(35=4) يكون فيه GapFillFlag(123)=Y

ومن هنا ثلاثة واجبات. احفظ أرقام التسلسل حفظًا دائمًا عند كل إرسال وكل استقبال، وإلا فإن إعادة الإقلاع إما أن تطلب اليوم كله من جديد وإما أن تنتهي بقطع اتصالك بسبب أرقام أدنى مما ينبغي. وتذكّر أي قيم ExecID(17) طُبّقت بالفعل، لأن المعيار يترك كشف التكرار للمستقبِل. واختم كل إعادة اتصال بفحص لحالة الأوامر، عبر OrderMassStatusRequest(35=AF) حيث تدعمه منصة التداول: فـ gap fill يقفز فوق أمر يعني أن صورتك عنه تنقصها واقعة.

كيف ينبغي لمدير الأوامر أن يقرأ رسالة ExecutionReport؟

تحمل رسالة ExecutionReport(35=8) حقلين يسهل الخلط بينهما. ففي تعريف FIX، الحقل ExecType(150) «يصف ExecutionRpt بعينه (مثل Pending Cancel)، بينما يحدد OrdStatus(39) دائمًا الحالة الراهنة للأمر (مثل Partially Filled)». قُد آلة الحالة بالحدث، واستخدم حالة الأمر للتحقق المتقاطع.

  • Pending New (A) وNew (0): استلمت منصة التداول الأمر، ثم قبلته
  • Trade (F): تنفيذ جزئي أو كامل. قبل FIX 4.3 كانت التنفيذات تأتي بقيمتي ExecType 1 و2، لذا فالمحوّل الخاص بطرف مقابل يعمل بـ FIX 4.2 يحوّلهما إلى Trade
  • Pending Cancel (6), Canceled (4), Pending Replace (E), Replaced (5), Rejected (8), Expired (C)
  • Trade Correct (G) وTrade Cancel (H): قد يُعدَّل التنفيذ أو يُلغى بعد وقوعه، لذا قد تنخفض حتى الكمية المنفَّذة

يعرّف قاموس FIX الحقل LeavesQty(151) بأنه OrderQty(38) ناقص CumQty(14) ما دام الأمر نشطًا، ما يجعله ثابتًا رخيصًا يمكن التحقق منه في كل تقرير عن أمر عامل. والتقرير الذي يخرقه، أو قيمة ExecType لا انتقال لها من الحالة الراهنة، ينبغي أن يجمّد الأمر ويرفع تنبيهًا. فبالتخمين تنتهي الطرفية إلى عرض مركز لا توافق عليه منصة التداول.

كيف تتعامل الطرفية مع سباقات الإلغاء والاستبدال؟

كثيرًا ما يغيّر المضارب السريع أمرًا قبل أن تردّ منصة التداول على التغيير السابق. وكل سباق أدناه هو رسالة تتقاطع مع أخرى على الشبكة.

  • يُنفَّذ الأمر بالكامل بينما طلب الإلغاء الذي أرسلته ما زال في الطريق. فتردّ منصة التداول بـ OrderCancelReject(35=9)، عادةً مع CxlRejReason(102)=0، «فات أوان الإلغاء»، وعلى الطرفية أن تُظهر التنفيذ والمركز الناتج عنه، لا المركز الصفري الذي طلبه المتداول
  • يخرج تعديل ثانٍ قبل الإقرار بالأول، وقد يعود مرفوضًا بـ CxlRejReason(102)=3، أي أن الأمر بانتظار إلغاء أو استبدال بالفعل. أبقِ استبدالًا واحدًا في الطريق لكل أمر، واطوِ الطلبات اللاحقة في أحدث سعر وحجم
  • يحمل كل استبدال ClOrdID(11) جديدًا، ويشير OrigClOrdID(41) إلى المعرّف السابق، «لا إلى الأمر الأول في اليوم». وقد يصل تنفيذ يتقاطع مع استبدال تحت معرّف أقدم من الذي أُرسل للتو، لذا يجب أن يقود كل معرّف في السلسلة إلى الأمر نفسه
  • تنقطع الجلسة والأوامر راكدة. فخاصية Cancel on Disconnect لدى CME، مثلًا، تلغي بعد الانقطاع غير الإرادي أوامر العقود الآجلة والخيارات الراكدة لجلسة iLink مفعَّل فيها COD، لكنها لا تلغي أوامر GTC وGTD. حدّد قبل الإطلاق الفعلي أي الأوامر تنجو من الانقطاع في كل منصة تداول

تمنح الـ drop copy رؤية ثانية. وتصف CME خدمتها بأنها نسخ فورية من تقارير التنفيذ والإقرارات تُرسَل «على مسار منفصل ومخصّص». طابِق المراكز معها في النواة، وعامِل أي خلاف مع جلسة الأوامر على أنه حادث.

كيف يُبنى دفتر الأوامر المحلي من تغذيات L2 وL3؟

تنشر تغذية L2 مستويات الأسعار. وتوثّق Binance إجراءً يقوم على لقطة تليها تحديثات: خزّن التدفق مؤقتًا، واجلب لقطة، وأسقط الأحداث المخزّنة التي تتضمنها اللقطة أصلًا، وطبّق الباقي بالترتيب، وابدأ من الصفر من جديد إذا تُخطّي معرّف تحديث. ولقطاتها تتوقف عند 5000 مستوى لكل جانب، لذا تبقى المستويات الأعمق مجهولة حتى تتغير.

تنشر تغذية L3 الأوامر منفردة. ففي Nasdaq TotalView-ITCH 5.0 تحمل رسالة Add Order رقمًا مرجعيًا للأمر، وتعود إليه رسائل التعديل اللاحقة، وعند بلوغ الأسهم المعروضة صفرًا «يكون الأمر ميتًا ويجب إزالته من الدفتر». ويحتفظ مُنشئ الدفتر بخريطة من الرقم المرجعي إلى الأمر ويجمّع المستويات منها: ذاكرة أكبر وعملية بحث لكل رسالة، مقابل عدد الأوامر في كل مستوى وتقدير لموقع أمرك أنت في الطابور.

في سلّم الأسعار، تتفوق عادةً على الشجرةِ مصفوفةٌ مفهرسة بالسعر حول أفضل سعري الشراء والبيع، لأن الأسعار تتحرك بالـ ticks على نطاق متصل. ويملك الدفتر كاتب واحد لكل أداة، ويسجّل رقم التسلسل الذي يعكسه الدفتر؛ أما استرداد الفجوات والـ fan-out فمشروحان في المقالة عن بيانات السوق تحت الاندفاع. وتضيف الطرفية قاعدة واحدة: الدفتر قيد الاسترداد يُرسم على أنه قيد الاسترداد، ولا يُرسم أبدًا على أنه حي.

ماذا تحتاج لوحة المضاربة السريعة من النواة؟

اللوحة سلّم أسعار يعرض عمق السوق (DOM) وتتداول منه. النقر على سعر يضع أمرًا محدد السعر، والسحب ينقله، ومفتاح اختصار يرسل حجمًا مضبوطًا مسبقًا أو يصفّي المركز. ولأنه لا توجد نافذة تأكيد، تقع شبكة الأمان في النواة، وهي تفحص الحجم الأقصى ونطاقات الأسعار والانكشاف لكل حساب في كل أمر بنقرة واحدة. وتتناول هذه الفحوصَ المقالةُ عن مخاطر ما قبل التداول في مسار الأوامر.

بالنسبة إلى أوامر bracket وOCO، قرّر أولًا أين تعيش. يعرّف FIX الحقل ContingencyType(1385) على NewOrderList(35=E)، بما في ذلك One Cancels the Other وOne Triggers the Other. استخدم نسخة منصة التداول حيث توجد؛ وإلا فالنواة تحاكيها بمراقبة التنفيذات وإرسال الساق الأخرى. ولا تحاكِها أبدًا في عملية الشاشة: فالحاسوب المحمول الذي يدخل في وضع السكون ومعه مركز غير محمي هو بالضبط الحالة التي وُجد الـ bracket من أجلها.

المركز يُستمد من التنفيذات، بما فيها التصحيحات وإلغاءات الصفقات، وتعيد النواة تقييمه مقابل الدفتر المحلي عند كل تغيير؛ وتقرأ الشاشة المركز والأرباح والخسائر (PnL) مرة واحدة في كل إطار.

كيف تقيس زمن الاستجابة من ضغطة المفتاح إلى خروج الأمر إلى الشبكة؟

يهتم المضارب السريع بسلسلتين: من المفتاح أو النقرة إلى خروج الأمر من بطاقة الشبكة، ومن حزمة بيانات السوق إلى البكسل المتغيّر. وكل حلقة تحتاج طابعها الزمني الخاص.

  • حدث الإدخال، مختومًا بطابع زمني من نظام التشغيل
  • دخول التعليمة إلى النواة، بعد القفزة من الشاشة إلى البوابة
  • اكتمال قرار المخاطر، وتسليم رسالة FIX إلى الـ socket
  • خروج الحزمة من المحوّل. ففي Linux يستطيع SO_TIMESTAMPING أن يعيد طوابع زمنية للإرسال والاستقبال «يولّدها محوّل الشبكة»
  • وفي الاتجاه الآخر: استلام الحزمة، وتحديث الدفتر، وعرض الإطار

أبلغ عن كل حلقة بالمئينات تحت حمل تسمّيه، لا بمتوسط من سوق هادئة. فالرقم المنفرد بلا نقاط قياسه لا يمكن مقارنته بأي رقم آخر.

هل ينبغي أن يكون سلّم الأسعار تطبيقًا أصليًا (native)، أم تطبيق ويب بـ WebGL وWebAssembly؟

تذكر MDN أن 60 Hz هو معدل تحديث الشاشات الأكثر شيوعًا، مع استخدام واسع لـ 120 و144 Hz أيضًا، ما يعطي 16.7 ms لكل إطار عند 60 Hz وأقل من 7 ms عند 144 Hz. وقد تغيّر تغذية بورصة مزدحمة الدفتر مرات كثيرة داخل إطار واحد، لذا ففي أي تقنية كانت تطبّق النواة كل تحديث، وترسم الشاشة أحدث حالة مرة واحدة في كل إطار.

  • شاشة أصلية مكتوبة بـ Rust ترسم عبر الـ GPU تمنح تحكمًا كاملًا في حلقة الرسم والإدخال، ولغة واحدة من الـ socket إلى البكسل، على حساب برامج التثبيت والتحديثات لكل نظام تشغيل تدعمه
  • شاشة متصفح يكون فيها سلّم الأسعار على canvas أو WebGL وفكّ ترميز الدفتر في WebAssembly لا تتطلب تثبيت أي شيء، ويستطيع OffscreenCanvas، بحسب MDN، الرسم «داخل سياق worker». والثمن تحكّم أقل في التوقيت، وبيئة تشغيل تعتمد جمع القمامة بين النقرة والتعليمة
  • واجهة ويب داخل غلاف سطح مكتب تُبقي على قاعدة كود واحدة، وتجلب معها استهلاك المتصفح للذاكرة وبيئة تشغيله

وتشير MDN أيضًا إلى أن معظم المتصفحات توقف requestAnimationFrame مؤقتًا في علامات التبويب الخلفية، لذا لا يمكن لأي شيء يجب أن يظل يعمل أن يعيش في الصفحة. فشاشة ويب فوق نواة Rust تفي بهذا المتطلب؛ أما حزمة ويب في مسار الأوامر فلا.

كيف تختبر طرفية تداول قبل أن تلامس منصة تداول حية؟

منصات التداول هي التي تقرر متى يُسمح لك بالدخول. فـ CME، مثلًا، «تشترط أن تكون جميع أنظمة العملاء التي تُجري معاملات على CME Globex عبر توجيه الأوامر في iLink أو تعالج بيانات السوق الخاصة بـ CME Group معتمدةً من AutoCert+»، وهي أداة الاختبار الآلي لديها. وبحسب CME، يغطي الاعتماد تبادل الرسائل ومعالجتها والتعافي من أحداث الرسائل غير الطبيعية، وتجري اختباراتها الوظيفية بما لا يزيد على 10 معاملات في الثانية. والنجاح في الاعتماد لا يخبرك بما يفعله سلّم الأسعار عند الافتتاح والمتداول ينقر عليه.

تدرّب على الأعطال على محاكي منصة تداول خاص بك: gap fill يقفز فوق أوامر بعد إعادة الاتصال، وإلغاء فات أوانه، واستبدال يُرفض والأمر في حالة انتظار، وإلغاء صفقة، وجلسة تنقطع وفيها أوامر راكدة، وفجوة في التغذية وسط اندفاع بينما المتداول ينقر. ثم أعد تشغيل حركة FIX وبيانات السوق المسجّلة عبر النواة. ويجب أن ينتج المدخل نفسه حالات الأوامر نفسها والدفتر نفسه في كل تشغيل، وهذا ما يحوّل بلاغ الخلل الذي يقدّمه المتداول إلى اختبار.

هل تبني طرفية تداول، أم تشتري واحدة، أم تبني حول محرك FIX مرخّص؟

اشترِ طرفية جاهزة حين تكون منصات التداول التي تعمل معها مدرجة في قائمتها ويكون سير عملك قياسيًا. وابنِ حين تكون الشاشة جزءًا من سبب اختيار عملائك لك، أو حين لا تكون منصات تداولك مدعومة، أو حين يتعين عليك أن تملك مسار الأوامر وفحوص المخاطر فيه. أما الطريق الوسط فيرخّص محرك FIX أو محوّلات منصات التداول ويبني الباقي.

أي الشركات بنت فعلًا طرفية كهذه، وما الأدلة التي ينبغي أن تطلبها؟

تعامل مع عبارة «بنينا واحدة» على أنها ادعاء يثبته المورّد في الاجتماع الأول. وستة طلبات تؤدي معظم العمل.

  • عرض توضيحي على بيئة الإنتاج أو الاختبار لدى منصة تداول، لا على محاكي المورّد نفسه، مع قطع الاتصال في منتصفه لإظهار ما يفعله سلّم الأسعار وجدول الأوامر أثناء الاسترداد
  • منصات التداول التي اعتمدت اتصال FIX لديهم: إصدار FIX أو لهجة منصة التداول، والتاريخ، وهل النظام المعتمد هو نفسه الذي سيبنونه لك
  • كيف أُخذت أرقام زمن الاستجابة لديهم: أي نقاط قياس، وهل الطوابع الزمنية من العتاد أم من البرمجيات، وأي مئينات، وتحت أي حمل، وما الذي يُغفله الرقم
  • حادثة واحدة تُروى بالتفصيل، مثل gap fill يقفز فوق أوامر عاملة أو إلغاء صفقة: ماذا أظهرت الشاشة، وماذا قالت منصة التداول، وما الذي تغيّر في الكود بعد ذلك
  • الكود المصدري كاملًا، وتعليمات البناء وخطوات النشر، وقائمة بما يبقى ملكًا لهم، وبناء على جهاز نظيف دون مساعدتهم
  • من أين يأتي محرك FIX، سواء أكان مطوَّرًا داخليًا أم مفتوح المصدر أم مرخّصًا، وبأي شروط تواصل استخدامه

أين موقع amBrain من ذلك؟

amBrain شركة هندسة برمجيات في يريفان، أرمينيا، تبني منصات تداول منخفضة زمن الاستجابة ومحركات مطابقة وأنظمة مزايدة فورية بـ Rust. وتبني amBrain البرمجيات منذ عام 2019.

تبني amBrain بنية تحتية للتداول الخوارزمي: تنفيذ الأوامر، وبيانات السوق، وضوابط المخاطر قبل التداول. وتشمل خدماتها في التداول تطوير طرفيات التداول، وأنظمة إدارة الأوامر، وتكامل البورصات عبر بروتوكول FIX.

يُقاس رقمان على المسارات التي تبنيها amBrain: زمن استجابة بيانات السوق أقل من 5 ms، وزمن استجابة المخاطر أقل من 1 ms. وليس أيٌّ منهما رقمًا يقيس المسار من ضغطة المفتاح إلى الشبكة، لذا اطلب نقاط القياس والحمل وراء كليهما، كما تفعل مع أي مورّد.

بنت amBrain طرفية التداول لـ Spectre Trade. كما بنت amBrain بورصة مصغّرة تعمل في بيئة الإنتاج على استضافة MOEX المشتركة. والتصميم في هذه المقالة عام. فهو لا يصف أيًّا من النظامين، ولا يسمّي البروتوكولات التي يستخدمها أيٌّ منهما.

ثلاث صيغ: تنفيذ كامل، أو فريق مخصّص، أو مهندسون مدمجون في فريقك. ويحتفظ العميل بالملكية الكاملة للمنتج وللكود، باستثناء مكوّناتنا القابلة لإعادة الاستخدام.

قبل المكالمة الأولى مع أي مورّد، بما في ذلك amBrain، دوّن منصات التداول التي تعمل معها، وإصدار FIX أو اللهجة التي تتحدث بها كل منها، وزمن الاستجابة الذي تحتاجه بين نقاط قياس مسمّاة.

هل لديك تصميم مشابه على الطاولة؟

أحضر بنيتك الحالية وسيناريو الفشل الذي يقلقك، وسنراجعه معًا خلال نصف ساعة.