اشترِ المحرك، وابنِ فرصتك: الخاصية الوحيدة التي تحسم اختيار محرك التداول الكمي
اختيار محرك للتداول الكمي ليس مقارنة سمات بين NautilusTrader وbacktrader وحلقة أحداث تُكتب منزلياً. الأمر يُحسم بخاصية واحدة، ومعيار تقييم يمكن تطبيقه على أي محرك: هل يُشغّل اختبار المحاكاة لديك الشيفرة نفسها التي يعمل بها نظامك الفعلي؟

يقف كل مطوّر كمي مبكراً أمام المفترق نفسه: على أي إطار عمل لاختبار المحاكاة يبني عمله؟ NautilusTrader؟ backtrader؟ vectorbt؟ أم أن الأبسط أن يكتب حلقة أحداث (Event Loop) خاصة به؟ يجيب الإنترنت بجداول مقارنة السمات، ونجوم GitHub، وسرعات القياس المرجعي، وهذا بالضبط الإطار الخاطئ للسؤال. فالاختيار لا يتعلق حقاً بالسمات، بل بأي الإخفاقات أنت مستعد لتحمّل مسؤوليتها، وثمة خاصية واحدة تحسم أكثر مما تحسمه كل تلك السمات مجتمعة.
نصفا مكدس النظام يخضعان لاقتصادين متعاكسين
ينقسم نظام التداول بوضوح إلى نوعين من الشيفرة، ينبغي أن يأتي كل منهما من مصدر مختلف.
الفرصة (Edge)، أي إشاراتك وتحجيمك وسياسة إدارة المخاطر لديك، هي حيث تعيش خصوصيتك التنافسية. لا أحد غيرك يقدر على كتابتها، وأي خلل دقيق فيها يُفسد أرباحك وخسائرك بصمت، لذا يتوجّب عليك أن تمتلك كل سطر فيها.
أما البنية التحتية، أي توجيه الأوامر، ومحاكاة التنفيذ، ومحاسبة المراكز والنقد، وإعادة الاتصال، وجدولة الأحداث، فغير متمايزة، وضبطها بدقة شاق بوحشية. لا ألفا (Alpha) فيها البتة. إنها سلبية خالصة: غير مرئية حين تكون صحيحة، وكارثية حين تكون خاطئة، وتظهر أخطاؤها في التداول الفعلي حيث تُكلّفك مالاً حقيقياً. وهذه بالتحديد الشيفرة التي ينبغي ألا تكتبها بنفسك.
فالقاعدة العملية إذن: ابنِ ما يُجسّد فرصتك؛ واشترِ (أو تبنَّ) ما يكفيه أن يكون صحيحاً فحسب، خصوصاً كل ما يتحدث مع الوسيط أو يحاسب النقد والمراكز. فالمحرك الناضج يكون قد استوعب فعلاً آلاف التقارير عن أخطاء الحالات الحدّية (Edge cases) التي كنت لتكتشفها بنفسك، واحدة تلو الأخرى، كل مرة عبر نداء هامش جديد. وهذا هو المعنى الذي يحمله شعار "اشترِ المحرك وابنِ فرصتك".
الخاصية الوحيدة التي تحسم الاختيار
إليك السؤال الذي يتفوق أهمية على كل سمة أخرى: هل يُشغّل اختبار المحاكاة لديك الشيفرة نفسها التي يعمل بها نظامك الفعلي؟ فإن لم يكن كذلك، فأنت تتحقق من برنامج وتُطلق للتداول برنامجاً آخر مختلفاً، والفجوة بينهما هي بالضبط حيث يعيش التحيز التطلعي (Look-ahead bias)، ووهم نموذج التنفيذات، وأخطاء المناطق الزمنية. وهذا ما يفصل فعلياً بين عائلات أطر العمل هذه.
Figure
Two backtests, two different programs
The choice is not which is faster. It is whether the program you validate is the program you deploy.
Vectorised
for finding candidates
- – Whole-series array maths: years of data in seconds
- – Idealised fills: you get the price you saw
- – No order lifecycle; a position is just a number
- – Live is a full rewrite, so backtest-to-live parity is zero
Event-driven
for trusting them
- – One event at a time, exactly as in live
- – Models rejection, partial fills and latency
- – Full order state machine and cash accounting
- – The same strategy class drives backtest and live
Buy the plumbing that merely has to be correct; build only the edge.
يحسب اختبار المحاكاة المُتّجه (Vectorised) سلسلة الإشارات والأرباح والخسائر كاملةً دفعة واحدة عبر عمليات على المصفوفات، مثل returns = asset_returns * position.shift(1). وهو سريع إلى حدّ رائع، سنوات من البيانات في ثوانٍ معدودة، وهذا بالضبط ما تريده حين تجرّب مسحاً واسعاً للمعاملات. لكنه يُصمّم عالماً بلا احتكاك: لا يُرفض فيه أي أمر، ولا يحدث تنفيذ جزئي (Partial Fill) لأي صفقة، ولا تُرفض أي ساق من أمر مركّب (Bracket Order)، ويفترض أنك نفّذت الصفقة عند السعر ذاته الذي رأيته. ونظيره في التداول الفعلي إعادة كتابة كاملة، فما اختبرته وما تُطلقه للتداول برنامجان مختلفان.
أما المحرك القائم على الأحداث (Event-driven) فيعالج حدثاً واحداً في كل مرة، شمعة، أو تِك (Tick)، أو قبول أمر، أو تنفيذ، أو تغيّر مركز، تماماً بالترتيب الذي تصل به في التداول الفعلي. وهو أبطأ، لكنه يُحاكي ما يتعطّل فعلاً: أمر يظل في حالة "مُرسَل" حتى تقبله المنصة، وتنفيذ يصل متأخراً، وإعادة اتصال تكتشف مركزاً لم تكن تعلم أنك تحمله. والأهم أن محركاً ناضجاً قائماً على الأحداث يتيح لفئة الاستراتيجية نفسها أن تُشغّل اختباراً تاريخياً وجلسة تداول فعلية على حدٍ سواء. فأنت تُبدّل عميلي البيانات والتنفيذ فقط، لا المنطق نفسه. وبهذا تصف عبارتا "اختبرنا هذا" و"أطلقنا هذا للتداول" البرنامج ذاته أخيراً.
قصة حرب: الفرصة التي كانت تعيش في التنفيذات
Chart
The edge that lived in the fills
A candidate that looked excellent in a vectorised backtest lost most of its return once an event engine modelled real order handling, because a vectorised 'fill' is an assumption, not an execution. Illustrative and sanitised.
بدت استراتيجية مرشحة ممتازة في اختبارها المُتّجه: منحنى رأس مال نظيف، ونسبة شارب (Sharpe Ratio) تتجاوز كل بوابة ترقية بمسافة واضحة. فلمّا انتقلت إلى محرك قائم على الأحداث بمعالجة واقعية للأوامر، تبخّر معظم العائد ببساطة. كانت النسخة المُتّجهة تتداول عند أسعار ما كانت الاستراتيجية لتحصل عليها فعلياً بأي حال: فقد حجّمت المركز بناءً على إغلاق الشمعة، ثم نفّذت ضمنياً عند الإغلاق ذاته، دون فارق سعر (Spread)، ودون انزلاق (Slippage)، ودون أي ساق مرفوضة.
شكل هذا الخلل عام ويستحق أن يُسمّى: "تنفيذ" اختبار المحاكاة المُتّجه افتراض، لا تنفيذ فعلي. ولم يكن العلاج تعديل معامل ما، بل معاملة نتيجة الاختبار المُتّجه بوصفها إشارة ترتيب أولويات (Triage) فحسب، لا حكماً نهائياً بالإطلاق للتداول. فكل ما هو متجه إلى رأس مال حقيقي عليه أن يجتاز محركاً يُحاكي كيف تتصرف الأوامر فعلاً.
"حلقة الأحداث ما هي إلا حلقة for على الشموع"
هذه هي الجملة التي أطلقت آلاف أطر العمل المبنية منزلياً، وهي خاطئة. فالجزء السهل هو التكرار فوق الشموع. أما الجزء الصعب فهو كل ما يجب أن تؤديه الحلقة بشكل صحيح بين شمعة وأخرى: آلة حالة الأمر (Order State Machine)، وسجلات النقد والمراكز التي تصمد أمام التنفيذات الجزئية، وإعادة الاتصال التي تستعيد مراكز فُتحت قبل إعادة التشغيل، والمعالجة المتّسقة عند التكرار (Idempotent) لأحداث الوسيط المكرَّرة. أخطئ في هذه المحاسبة خطأً دقيقاً، وسيظل اختبار المحاكاة لديك يبدو مثالياً بينما ينجرف حسابك الفعلي بهدوء بعيداً عمّا تظن أنك تملكه. وهذا الانجراف أخطر أنواع الأخطاء وأكثرها كلفة، لأنه لا يتسبب في أي انهيار يُنبّهك إليه.
بناء محرك تنفيذ خاص بك بنفسك يعني الالتزام بصيانته كاملاً، إلى الأبد، مقابل صفر ألفا. وأحياناً يكون هذا هو القرار الصحيح، ويستحق الأمر أن نكون صادقين بشأن متى: استراتيجية بأداة واحدة ومنخفضة التواتر يفوق فيها منحنى تعلّم المحرك فائدته بكثير؛ أو فئة أصول غريبة لا يُحاكيها أي إطار عمل؛ أو جهة تدير أصلاً بنية تنفيذ أثبتت جدارتها ميدانياً. وخارج هذه الحالات، تبنّي الآلية الجاهزة أفضل من صيانتها بنفسك.
اختر الخاصية لا الشعار
ولأن الدرس هنا هو الخاصية لا العلامة التجارية، فلا تختر NautilusTrader أو backtrader أو أي بديل آخر بناءً على مسابقة شعبية. بل قيّم المرشحين وفق معيار تقييم واحد، فيصبح الاسم تفصيلاً عارضاً لا أكثر:
- التكافؤ (Parity). هل تُشغَّل فئة الاستراتيجية نفسها في كل من اختبار المحاكاة والتداول الفعلي، مع تبديل عميلي البيانات والتنفيذ فقط؟ هذه هي الخاصية الأهم على الإطلاق.
- الواقعية (Realism). هل يُحاكي المحرك رفض الأوامر، والتنفيذ الجزئي، والكمون (Latency)، أم أنه يمنحك فقط السعر الذي تمنّيته؟
- محاسبة قابلة للتدقيق. هل يمكنك فحص سجل النقد والمراكز فيه والوثوق به عبر التنفيذات الجزئية، وعمليات إعادة الاتصال، والأحداث المكرَّرة؟
- الصيانة. هل المشروع تحت صيانة نشطة فعلاً، بحيث تتبنّى مشروعاً حياً لا ترث مشروعاً مهجوراً؟
هذه الخصائص الأربع هي ما يشتريه شعار "اشترِ المحرك" فعلياً. وزِن أيضاً التكلفة الحقيقية للشراء بصدق: ليست فقط "إطار عمل عليك تعلّمه" و"أبطأ"، بل أيضاً ضريبة التجريد (Abstraction Tax) المتمثلة في: مصارعة نموذج المحرك للبيانات والزمن حين لا يناسب احتياجك مستوى تفصيله، ودورة ترقيات متلاحقة على تبعية سريعة التغيّر، وتتبّع الأخطاء داخل حلقة أحداث كتبها غيرك، والارتهان لمشروع قد يتوقف عن التطور. قدّر ثمن هذه التكاليف كلها قبل أن تتبنّى أي محرك.
أبقِ الطبقة المُتّجهة، لكن قيّد دورها
لا يعني أي من هذا التخلي عن أداة اختبارك السريعة الخالية من الاحتكاك. إنه فقط يمنحها مهمة واحدة. فأدوات الاختبار المُتّجهة (pandas وnumpy وvectorbt) هي حيث تُولَد الأفكار، وحيث ينبغي أن يموت معظمها: اختبر آلاف توليفات المعاملات في دقائق معدودة، وتخلَّص من التسعين في المائة تقريباً التي تفشل حتى في عالم بلا احتكاك. واقعية التنفيذ لا تهم بعد في هذه المرحلة، لأن استراتيجية تفشل بلا تكاليف لن تفشل إلا بشكل أقسى حين تُضاف التكاليف.
الانضباط هنا هو في نقطة التسليم بين الاثنين. فالرياضيات المُتّجهة لإيجاد المرشحين؛ والمحرك القائم على الأحداث للوثوق بهم. لا تدع أبداً رقماً سريعاً يجمّل الصورة وخالياً من الاحتكاك يحل محل قرار الإطلاق للتداول. أنفق ثوانٍ رخيصة من الحساب المُتّجه في إيجاد المرشحين القلائل الذين يستحقون ساعات المحرك المكلفة، ولا تدع غير الناجين من ذلك التمحيص الثاني يقترب من رأس المال.
الخلاصة
إن لم تحمل من هذا المقال سوى شيء واحد، فليكن معيار التقييم، لا العلامة التجارية. فسؤال اختيار إطار العمل الذي تصوغه المنتديات بعبارة "NautilusTrader مقابل backtrader مقابل بناء محرك خاص" هو في الحقيقة: أيّ من هذه الخيارات يُشغّل شيفرة الاستراتيجية نفسها في اختبار المحاكاة والتداول الفعلي، ويُحاكي معالجة حقيقية للأوامر، ويحتفظ بسجل قابل للتدقيق، وما زال تحت صيانة نشطة؟ أجب عن هذا السؤال، ويحسم الاختيار نفسه. ابنِ الفرصة، فهي وحدك من يملكها؛ واشترِ البنية التحتية، التي يكفيها أن تكون صحيحة فحسب.
وهذا واحد من خمسة قرارات تتعلق بالمكدس التقني في أساسيات النظام الذي تنبع منه هذه المقالات. والفصل الكامل، خيارات المكدس التقني وأسبابها، متاح للقراءة مجاناً، ويستعرض اختيار المحرك إلى جانب طبقة البحث، وملف القفل (Lockfile)، وحقائق الوسيط المالي، وحدود الحاوية (Container). وإن أردت أن ترى فئة استراتيجية حقيقية قائمة على الأحداث، فإطار العمل المرافق المُنقَّح على GitHub مرخّص بموجب Apache-2.0: خطافات دورة الحياة (Lifecycle Hooks)، واستدعاء التحجيم، وفحص المخاطر، جميعها موجودة هناك للقراءة. وهذا الفصل جزء من كتاب Building a Production Quant Trading System، نسخة رقمية حيّة على Leanpub ونسخة ورقية مطبوعة على Amazon إن أردت البناء كاملاً في مكان واحد.
هذا مقال هندسي، وليس نصيحة استثمارية، ولا يحتوي على أي استراتيجية قابلة للتداول. جميع الأرقام توضيحية ومُنقّحة.
Figure
Two backtests, two different programs
The choice is not which is faster. It is whether the program you validate is the program you deploy.
Vectorised
for finding candidates
- – Whole-series array maths: years of data in seconds
- – Idealised fills: you get the price you saw
- – No order lifecycle; a position is just a number
- – Live is a full rewrite, so backtest-to-live parity is zero
Event-driven
for trusting them
- – One event at a time, exactly as in live
- – Models rejection, partial fills and latency
- – Full order state machine and cash accounting
- – The same strategy class drives backtest and live
Buy the plumbing that merely has to be correct; build only the edge.
Chart
The edge that lived in the fills
A candidate that looked excellent in a vectorised backtest lost most of its return once an event engine modelled real order handling, because a vectorised 'fill' is an assumption, not an execution. Illustrative and sanitised.
قراءات إضافية
- اختبارك التاريخي ليس دليلاً: لماذا تموت أنظمة التداول الكمي قبل أن تتداول
منحنى الأسهم الجميل هو النتيجة الافتراضية لأي اختبار محاكاة تاريخية، وليس إنجازاً. إليك لماذا تنحاز كل أنماط الفشل في التداول الكمي نحو التفاؤل، والعادة الوحيدة التي تصمد أمام السوق الحقيقي: الشك قبل الاحتفال.
- الشك قبل الاحتفال: قراءة في كتاب "بناء بيئة برمجية للتداول الكمي الإنتاجي"
مقدمة لكتابي "بناء بيئة برمجية للتداول الكمي الإنتاجي"، وهو دليل عملي لنسبة الـ 90% غير البراقة من التداول المنهجي: لماذا كتبته، وماذا تتوقع، وماذا لا تتوقع.
مقالات ذات صلة
لا تستخدم رقماً عائماً للمال أبداً: الخلل الصامت الذي يُسيء تحجيم صفقاتك الفعلية
استخدام رقم الفاصلة العائمة لتمثيل المال خطأ برمجي كلاسيكي، لكنه في نظام تداول لا يكتفي بتقريب بنس تقريباً خاطئاً، بل يُحرّف حجم مركز فعلي بصمت تام. يشرح هذا المقال لماذا يحدث ذلك، ولماذا لا يكفي نوع Money وحده حلاً كما قد تتخيل.
دليل شامل للهجرة من ووردبريس إلى Next.js
دليل عملي شامل للانتقال بموقع محتوى من ووردبريس إلى Next.js دون فقدان ترتيبك في محركات البحث: قاعدة الحفاظ على الروابط التي تحكم كل شيء، وبنية محتوى قادرة على الصمود أثناء الانتقال، والتعامل مع اللغتين العربية والإنجليزية، ومتطلبات السيو والأمان، وعملية الانتقال التي يمكنك التراجع عنها في أي وقت.
لقد توقفت عن الدفع مقابل استضافة ووردبريس
استضافة ووردبريس المُدارة ضريبة تدفعها مالاً وأداءً وقلقاً أمنياً. إليك كيف احتفظت بمحرّر ووردبريس الذي أحبّه، وشغّلته محلياً مجاناً، ونشرت الموقع كملفات HTML ساكنة على شبكة الحافة: زاحف بلغة Node بلا اعتمادات خارجية جعلته مفتوح المصدر.