محاكاة التنفيذ: السلم من وهم سعر الإغلاق إلى واقع يراعي موقع الطابور
يحتوي الباكتيست الخاص بك على نموذجين: نموذج للألفا ونموذج للتنفيذ. معظم الناس ينفقون 95% من جهدهم على الأول ويرثون الثاني من أي إطار عمل يستخدمونه بالصدفة. هذا معكوس. إشارة متوسطة مع نموذج تنفيذ صادق تنتج تقديرًا متوسطًا لكن حقيقيًا للربح والخسارة. إشارة رائعة مع fill_price = candle.close تنتج رقمًا لا يقدّر أي شيء — إنه ناتج افتراض لم تفحصه قط.
بالنسبة لاستراتيجيات الـ taker على أدوات سائلة، نموذج التنفيذ هو حد تصحيحي. أما بالنسبة لأي شيء يتضمن أوامر حد معلقة — صناعة السوق، الدخول السلبي، جني خصومات post-only — فإن نموذج التنفيذ هو الاستراتيجية. سواء تم تنفيذ أمرك، ومتى، وبأي كمية، ومشروطًا بأي حركة سعر لاحقة، كل ذلك يحدد إشارة الربح والخسارة، لا حجمها فقط.
في مقالة التطابق بين الباكتيست والتداول الحي رسمنا التصنيف الكامل للفجوات بين الباكتيست والتداول الحي، وصنّفنا فجوة التنفيذ بدرجة خطورة 5/5 — الأسوأ في الفئة. أعطت تلك المقالة محاكاة التنفيذ ثلاثة مستويات دقة تقريبية ثم انتقلت لموضوع آخر. هذه المقالة هي رفيقة التعمق: السلم الكامل، درجة بدرجة، مع دورة حياة الأمر كآلة حالات، وحدود احتمال تنفيذ يمكنك فعليًا حسابها، وتجربة مقاسة توضح بدقة أين على السلم تموت استراتيجية "ماركت ميكينج" "مربحة".
السلم

كل درجة تتطلب بيانات وشفرة أكثر، وكل درجة تزيل تحيزًا منهجيًا محددًا. الدرجات مرتبة بحسب ما تخطئ فيه، لا بحسب التكلفة فقط.
الدرجة 0: التنفيذ عند سعر الإغلاق
fill_price = bar.close
يُنفَّذ الأمر فورًا وبالكامل عند إغلاق الشمعة التي ولّدت الإشارة. الإشارة حُسبت من نفس ذلك الإغلاق، فأنت تتداول على بيانات لم تكن موجودة عندما طُبع السعر: تحيز الاستباق (look-ahead bias) متنكرًا في زي تنفيذ. أي استراتيجية ذات معدل دوران تبدو جيدة هنا.
الدرجة 1: افتتاح الشمعة التالية
fill_price = next_bar.open
الحد الأدنى من الصدق لمنطق الـ taker على الشموع. تُحسب الإشارة على الشمعة ، ويحدث التنفيذ عند أول سعر يمكن رصده في الشمعة . هذا يقضي على الاستباق لكنه ما يزال يفترض سبريد صفري، وأثرًا سعريًا صفريًا، وسيولة لا نهائية عند سعر الافتتاح، ويقينًا كاملًا بالتنفيذ 100%. بالنسبة لأوامر الحد، يتدهور هذا إلى منطق "التنفيذ عند اللمس" (touch-fill) — وسنوضح لاحقًا لماذا هذا سُم.
الدرجة 2: السبريد + انزلاق ثابت
half_spread = mid * spread_bps / 2e4
slip = mid * slippage_bps / 1e4
fill_price = mid + side * (half_spread + slip) # side: +1 شراء، -1 بيع
الآن تدفع كل صفقة taker نصف السبريد بالإضافة إلى ثابت معايَر. هذه هي أول درجة يمكن أن تموت فيها استراتيجية عالية الدوران في الباكتيست — وهذا هو الهدف. الخطأ المتبقي: الانزلاق ليس ثابتًا. إنه يتناسب مع حجم الأمر نسبةً إلى العمق المعروض، وينفجر بالضبط عندما تريد استراتيجيتك التداول أكثر ما تريد. قيمة 5 نقاط أساس ثابتة هي متوسط عبر الأنظمة السوقية؛ استراتيجيتك لا تتداول النظام المتوسط.
الدرجة 3: مسح عمق L2 لأوامر السوق
مع لقطات دفتر الأوامر (order book snapshots)، تتوقف عن تخمين الانزلاق وتحسبه فعليًا. أمر شراء بالسوق بحجم يمشي عبر جانب البيع (ask) مستوى تلو الآخر؛ سعر التنفيذ هو المتوسط المرجح بالحجم عبر المستويات المستهلَكة:
def depth_walk(levels: list[tuple[float, float]], qty: float) -> tuple[float, float]:
"""levels: [(price, size), ...] sorted best-first. Returns (vwap, filled_qty)."""
remaining, cost = qty, 0.0
for price, size in levels:
take = min(size, remaining)
cost += take * price
remaining -= take
if remaining <= 0:
break
filled = qty - remaining
return (cost / filled if filled > 0 else float("nan"), filled)
تصحيحان يجعلان هذا أكثر صدقًا بشكل جوهري. أولًا، زمن الاستجابة (latency): امشِ عبر الدفتر كما كان قائمًا بعد بعد طابع زمن قرارك، حيث هو زمن الاستجابة المقاس من الإشارة إلى المنصة — الدفتر الذي رأيته ليس الدفتر الذي أصبته. ثانيًا، التنفيذ الجزئي القابل للتسويق: إذا كان العمق المعروض ضمن سعر الحد الأقصى لديك أقل من ، يجب على النموذج أن يُرجع تنفيذًا جزئيًا ويترك باقي الكمية معلقة، وهو ما يسلّم المشكلة إلى آلة الحالات أدناه.
الخطأ المتبقي عند الدرجة 3 هو الأثر السعري وإعادة التعبئة: أنت تستهلك الدفتر كأنه كائن ثابت، لكن الدفاتر الحقيقية تُعاد تعبئتها جزئيًا (والأطراف المقابلة الحقيقية تتفاعل). بالنسبة لأحجام صفقات أقل من بضع نقاط مئوية من عمق أفضل سعر، هذا الخطأ صغير؛ للأحجام الأكبر تحتاج نموذج أثر سعري (Almgren-Chriss 2001) يُبنى فوق هذا.
الدرجة 4: تنفيذ احتمالي مبني على موقع الطابور لأوامر الحد
الدرجات 0-3 تجيب عن "بأي سعر يُنفَّذ أمري العدواني". الدرجة 4 تجيب عن السؤال الأصعب: هل يُنفَّذ أمري السلبي أصلًا — وهي الدرجة الوحيدة القادرة على تسعير استراتيجية ماركت ميكينج. الأمر المعلق عند سعر يُنفَّذ عندما يتجاوز الحجم المتداول التراكمي عند حجم الطابور الذي كان أمامه. وهذا يتطلب تتبع موقعك في طابور FIFO لا يمكنك رصده مباشرة.
آلية تقدير موقع الطابور — الموقع الأولي، وقواعد التحديث عند الصفقات مقابل الإلغاءات، وعائلة الاحتمال لتوزيع الإلغاءات غير المرصودة — هي البدائية التي بنيناها في الطابور داخل الجدار. لن أعيد اشتقاقها هنا؛ المحاكي يستهلكها. ما تضيفه الدرجة 4 هو قاعدة قرار التنفيذ فوق هذا التقدير، وهو ما نغطيه في قسم احتمال التنفيذ أدناه.
أهمية هذه الدرجة مقدَّرة كميًا في الأدبيات: يُظهر Moallemi و Yuan (2016)، في "A Model for Queue Position Valuation in a Limit Order Book"، أنه بالنسبة للأدوات ذات الخطوة السعرية الكبيرة (large-tick)، فإن القيمة الاقتصادية لموقع في مقدمة الطابور مقابل مؤخرته تُضاهي نصف السبريد — نفس رتبة الحجم الخاصة بكامل الميزة النظرية لاستراتيجية صناعة السوق. نموذج تنفيذ يتجاهل موقع الطابور لا يخطئ في تقدير ربح وخسارة صانع السوق فحسب؛ بل يقدّر ربح وخسارة استراتيجية مختلفة تمامًا.
توجد درجة 5 — محاكاة كاملة قائمة على الوكلاء (agent-based) حيث يتفاعل السوق مع أوامرك (نماذج queue-reactive بمعنى Huang وLehalle وRosenbaum 2015؛ أطر متعددة الوكلاء مثل ABIDES، Byrd وآخرون 2020). إعادة التشغيل التاريخي، حتى مع مراعاة الطابور، تفترض أن أمرك لا يغيّر شيئًا من سلوك الآخرين. هذا الافتراض مقبول بحجم تداول التجزئة، ويصبح خاطئًا تدريجيًا كلما أصبحت أسعارك المعروضة نسبة ظاهرة من المستوى. الدرجة 5 خارج نطاق هذه المقالة؛ لكن اعلم أن السلم لا ينتهي عند 4.
التنفيذ الجزئي كآلة حالات
يمكن للدرجات 0-2 أن تتظاهر بأن الأمر مجرد استدعاء دالة: أرسل، احصل على سعر، انتهى. من الدرجة 3 فصاعدًا، الأمر هو عملية لها دورة حياة، ويجب على المحاكي أن يمثّلها كآلة حالات وإلا سيتعامل بصمت وبشكل خاطئ مع الحالات الأكثر أهمية.

enum OrderState {
PendingNew, // sent, not yet acked (latency window)
Resting { remaining: f64, q_ahead: f64 }, // in book, queue position estimated
PartialFill { remaining: f64, q_ahead: f64 }, // some qty done, rest still queued
PendingAmend, // amend in flight
PendingCancel, // cancel in flight
Filled,
Canceled { filled_qty: f64 }, // may be partially filled at cancel time
Rejected,
}
الانتقالات تحمل الاقتصاد الفعلي:
PendingNew→Resting: ينضم الأمر إلى الطابور خلف كل ما كان موجودًا عند لحظة التأكيد (ack)، لا عند لحظة القرار. يُزرع موقعك في الطابور بحجم المستوى كما كان عند . المحاكيات التي تزرع الموقع عند لحظة القرار تُبالغ بشكل منهجي في تقدير أولوية الطابور — بالضبط بمقدار الحجم الذي وصل خلال نافذة زمن الاستجابة لديك، وهو أكبر ما يكون خلال الاندفاعات (bursts).Resting→PartialFill: صفقة عند مستواك أكبر من الطابور الذي أمامك تنفّذك جزئيًا. الباقي يحتفظ بموقعه (الذي أصبح الآن في مقدمة الطابور). التنفيذات الجزئية ليست ضجيجًا — إنها معلومات: أن تُنفَّذ بنسبة 0.3 من 1.0 وتشاهد السعر يرتد بعيدًا هو حدث ربح وخسارة مختلف عن تنفيذ كامل، وعملية مخزون صانع السوق تُبنى من هذه الشظايا.Resting→PendingAmend→Resting: الفخ. في كل منصة تشفير تقريبًا، التعديل هو إلغاء/استبدال —cancelReplaceفي Binance ذري ضد التنفيذ المزدوج لكنه يُرجع معرّف أمر جديد في مؤخرة الطابور. حتى المنصات ذات دلالات التعديل الأصلية (CME Globex) تحافظ على أولوية الوقت فقط في حالة تخفيض الكمية؛ أما تغيير السعر أو زيادة الكمية فيفقدان هذه الأولوية. لذا في المحاكي: أي تعديل سعري يعيد ضبطq_aheadإلى كامل حجم المستوى الحالي. محرك تسعير يعيد تثبيت أسعاره كل 500 مللي ثانية لا "يحافظ على عرض سعر" — بل يعيد الدخول باستمرار في مؤخرة الطابور، وملف تنفيذه الواقعي هو انتقاء سلبي شبه خالص. مقترنًا بنتيجة Moallemi-Yuan: إعادة التسعير له ثمن، والثمن هو موقعك في الطابور.PendingCancel→PartialFill→Canceled: الإلغاءات أيضًا تستغرق زمن استجابة. في النافذة الزمنية بين قرار سحب عرض السعر ووصول الإلغاء إلى محرك المطابقة، ما يزال بإمكانك أن تُنفَّذ — وتلك التنفيذات هي أسوأ تنفيذات ستحصل عليها على الإطلاق، لأن سبب سحبك للعرض هو أن السوق كان على وشك أن يدهسك. المحاكي بدون زمن استجابة للإلغاء يحذف بالضبط أكثر التنفيذات سُميّة من سجلك.
آلة الحالات هي أيضًا ما يجعل محاسبة المحاكي صادقة: الرسوم تتراكم لكل حدث تنفيذ، والمخزون يُحدَّث لكل حدث تنفيذ، وإحصاءات الزمن-في-الحالة (كم من الوقت تبقى الأوامر معلقة قبل التنفيذ مقابل الإلغاء) تصبح قابلة للمقارنة مباشرة مع السجلات الحية — وهذا ما تتغذى عليه حلقة المعايرة في نهاية المقالة.
احتمال تنفيذ أوامر الحد: ثلاثة نماذج ونطاق
بالنظر إلى أمر معلق عند سعر (لنقل عرض شراء/bid)، متى يعلن المحاكي التنفيذ؟ ثلاث قواعد قرار، بترتيب تصاعدي من حيث الصدق:
1. التنفيذ عند اللمس (touch-fill، ساذج). يُنفَّذ الأمر إذا لمس السعر مستواك: . هذه قاعدة زمن-العبور-الأول (first-passage-time)، وفشلها قُيس منذ ربع قرن: Lo وMacKinlay وZhang (2002)، في "Econometric Models of Limit-Order Executions" (Journal of Financial Economics 65)، طبّقوا نماذج البقاء (survival models) على بيانات فعلية لأوامر الحد وخلصوا إلى أن التنفيذات الافتراضية المبنية على زمن العبور الأول "بدائل رديئة جدًا للتنفيذات الفعلية لأوامر الحد". نمط الفشل بنيوي: عندما يلمس السعر مستواك ثم يرتد، فإن اللمس استهلك مقدمة الطابور — التجار الذين عرضوا أسعارهم قبلك. التنفيذ عند اللمس يمنحك تنفيذاتهم. والأسوأ أنه يمنحك بالضبط التنفيذات الجيدة (اللمس-ثم-الارتداد هو السيناريو المربح لصانع السوق)، بينما مجموعة تنفيذاتك الحقيقية منحازة نحو اللمس-ثم-الاختراق — التنفيذات ذات الانتقاء السلبي.
2. الاختراق التجاري (trade-through، حد متحفظ). يُنفَّذ الأمر فقط إذا تداول السعر عبر مستواك بشكل صارم: ، أو في بيانات التِك (tick)، إذا تجاوز الحجم المتداول التراكمي عند كامل حجم المستوى. إذا اخترق السعر، فقد استُهلك كامل الطابور عند ، فأنت مُنفَّذ بغض النظر عن موقعك. هذا لا يمنحك أبدًا تنفيذًا لم تكن لتحصل عليه. تحيزه هو الصورة المعكوسة للتنفيذ عند اللمس: إنه يحرمك من كل تنفيذ استُنفد فيه الطابور إلى موقعك دون اختراق كامل، والتنفيذات التي يمنحها منحازة بشكل غير متناسب نحو الاختراق (الانتقاء السلبي). باكتيست صانع سوق تحت قاعدة الاختراق التجاري هو اختبار إجهاد، لا تقدير.
3. تقدير استنفاد الطابور. تتبّع الحجم المتداول التراكمي عند سعرك من شريط الصفقات (trade tape) والحجم الملغى المستنتج من فروقات L2. تقديرك للطابور أمامك:
حيث هو حجم المستوى عند دخول الأمر (وقت التأكيد) و هو نسبة الإلغاءات المفترض أنها تأتي من أمامك — المتغير الذي صيغته المبدئية (عائلة ) مشتقة في مقالة موقع الطابور. يبدأ التنفيذ عندما ؛ وكميتك المنفَّذة هي الحجم المتداول الزائد عنه، مما ينتج تنفيذات جزئية بشكل طبيعي:
ضبط (كل الإلغاءات أمامك) يعطي الحد المتفائل لهذا النموذج؛ و الحد المتشائم. عندما لا يكون لديك سوى لقطات L2 متفرقة ولا شريط صفقات عند المستوى — وهو أمر شائع مع تغذيات العملات المشفرة المُقيَّدة بـ 100 مللي ثانية — يمكنك اللجوء إلى نموذج احتمالي مسبق: Cont وStoikov وTalreja (2010)، في "A Stochastic Model for Order Book Dynamics" (Operations Research 58)، يمثّلون كل مستوى سعري كطابور ولادة-موت (birth-death queue) ويحسبون، عبر تحويلات لابلاس، احتمال أن يُنفَّذ أمر عند سعر الشراء قبل أن يتحرك السعر المتوسط، بشرط أحجام الطابور الحالية. إنه عرّاف احتمال تنفيذ تحليلي: خشن نسبيًا مقارنة بإعادة تشغيل شريط الصفقات، لكنه أفضل بكثير من التنفيذ عند اللمس، ورخيص بما يكفي لتقييمه داخل حلقة باكتيست ساخنة.
انضباط النطاق
القواعد الثلاث ليست متنافسة — إنها ترتيب:
مما يحدث نطاقًا للربح والخسارة. شغّل كل باكتيست لصانع سوق ثلاث مرات وأبلغ عن الفاصل الزمني:
(المتباينة العليا تقريبية — التنفيذ عند اللمس يمكن أن يعيد ترتيب الاستراتيجيات خطأً، لا مجرد تضخيمها، لأنه يمنحك تنفيذات جيدة افتراضية معاكسة للواقع). قاعدة القرار الناتجة: استراتيجية صانع السوق قابلة للنشر فقط إذا نجت عند الحد المتحفظ من النطاق، وكان النطاق ضيقًا بما يكفي ليكون للتقدير النقطي معنى. استراتيجية تُظهر +9 آلاف دولار عند اللمس / -3 آلاف دولار عند الاختراق التجاري لديها نطاق عرضه 12 ألف دولار؛ لا تعرف شيئًا سوى أن افتراض محاكيك يهيمن على الألفا الخاصة بك. استراتيجية تُظهر +2.1 ألف / +0.4 ألف تخبرك بشيء حقيقي.
التجربة: تنزيل استراتيجية صانع سوق واحدة عبر السلم

خذ صانع سوق بسيط عمدًا — عروض أسعار متماثلة عند أفضل سعر شراء/بيع، دفعات ثابتة بحجم 0.05 BTC، مخزون محدود عند ±0.5 BTC مع تسطيح taker عند الحد الأقصى. شهر واحد من بيانات BTCUSDT الآجلة الدائمة (perpetual): شموع دقيقة واحدة للدرجات المنخفضة، وفروقات L2 كل 100 مللي ثانية بالإضافة إلى شريط الصفقات للدرجات العليا؛ رسوم صانع السوق 1.0 نقطة أساس، ورسوم الـ taker 4.0 نقاط أساس. نفس شفرة الإشارة في كل درجة (نواة مشتركة، بحيث يكون المتغير الوحيد هو نموذج التنفيذ). الأرقام أدناه من تشغيل تمثيلي واحد لدينا — أحجامك الفعلية ستختلف بحسب المنصة والشهر والحجم؛ لكن الشكل العام لن يختلف:
| الدرجة | نموذج التنفيذ | معدل تنفيذ العروض | التنفيذات | ربح/خسارة الشهر | الحكم |
|---|---|---|---|---|---|
| 0 | تنفيذ عند الإغلاق | 98% | 41,200 | +$14,800 | وهم |
| 1 | افتتاح الشمعة التالية / لمس على شموع دقيقة واحدة | 89% | 37,400 | +$9,600 | وهم مع زمن استجابة |
| 2 | لمس + سبريد وانزلاق ثابت على تسطيحات taker | 89% | 37,400 | +$7,100 | التكاليف مُنمذجة، التنفيذات ما تزال وهمية |
| 3 | + مسح عمق L2 على تسطيحات taker | 89% | 37,400 | +$6,400 | الخروج صادق، الدخول ما يزال وهميًا |
| 4a | اختراق تجاري (متحفظ) | 21% | 8,900 | -$3,900 | حد إجهاد |
| 4b | استنفاد الطابور، معايَر | 37% | 15,600 | -$700 | أفضل تقدير |
| 4c | استنفاد الطابور، (متفائل) | 44% | 18,700 | +$1,900 | الحد الأعلى |
| — | تشغيل ظِلّي حي (shadow)، نفس الشهر | 35% | 14,100 | -$1,150 | الواقع |
اقرأ الجدول من الأعلى إلى الأسفل وراقب أين تموت الاستراتيجية. ليست الدرجة 2 — الرسوم والانزلاق يحلقان 26% وما تزال الاستراتيجية تبدو مربحة بمتانة. إنها تموت بين الدرجة 3 والدرجة 4، وتموت لسبب لا يستطيع أي نموذج تكلفة التقاطه: انتقاء التنفيذ. التنفيذ عند اللمس منح 37,400 تنفيذ، معظمها لمس-ثم-ارتداد — التقاط سبريد خالص. النموذج المراعي للطابور حذف 58% من تلك التنفيذات، والتنفيذات التي حذفها كانت بشكل غير متناسب هي المربحة: عندما يُلمس المستوى بخفة، يمتص الطابور الذي أمام صانع سوق يعيد تسعير عروضه بزمن استجابة تجزئة كل شيء. التنفيذات التي تنجو إلى الدرجة 4 منحازة نحو عمليات اكتساح تُنظّف المستوى بالكامل — التنفيذات التي يكون فيها السعر يخترقك بالفعل. معدل التنفيذ انخفض 2.4 مرة؛ وانقلبت إشارة الربح والخسارة. هذا التباين — خسارة التنفيذات الجيدة والاحتفاظ بالسيئة — هو الانتقاء السلبي مُجسَّدًا بشكل ميكانيكي صريح، وهو غير مرئي في كل درجة أدنى من 4.
لاحظ أيضًا ما فعله النطاق: [-1,900] يمتد عبر الصفر مع التقدير المعايَر عند -1,150. لم يُصِب المحاكي ربح/خسارة الواقع الحي بالدولار بالضبط — لكنه أصاب الإشارة، والحجم، ومعدل التنفيذ ضمن نقطتين مئويتين. هذا هو الغرض من نموذج التنفيذ. باكتيست الدرجة 1 أخطأ في ربح وخسارة الواقع الحي بمقدار 10,750 دولار على استراتيجية كانت كامل ميزتها الإجمالية الشهرية بضعة آلاف دولار: خطأ نموذج التنفيذ كان تقريبًا 3 أضعاف حجم الألفا. من هنا الأطروحة: نموذج التنفيذ الخاص بك افتراض أكبر من الألفا الخاصة بك.
تحذير واحد للدرجات المنخفضة: إن كان لا بد لك من العيش على بيانات الشموع (الدرجات 0-2)، فعلى الأقل حلّ غموض ما-داخل-الشمعة باستخدام التنقيب التكيفي بالدقة — التنقيب من دقيقة واحدة إلى ثانية واحدة/100 مللي ثانية/الصفقات حيث يقع وقف الخسارة أو جني الربح أو مستويات عرض السعر داخل نطاق الشمعة. التنقيب يصحح أخطاء الترتيب الزمني (أي مستوى أُصيب أولًا) لكنه لا يستطيع تصحيح أخطاء الطابور؛ إنه رفيق دقة البيانات لهذه المقالة، لا بديل عن الدرجة 4.
حلقة المعايرة: الإغلاق مقابل التنفيذات الحية
محاكي الدرجة 4 لديه معاملات حرة — ، زمن الاستجابة ، زمن استجابة الإلغاء، افتراض إعادة تعبئة المستوى. بدون معايرة، إنه مجرد تخمين بشكل مختلف. الحلقة التي تحوّله إلى أداة:
1. سجّل كل شيء في التداول الحي. كل حدث أمر مع طوابع زمنية من المنصة: الإرسال، التأكيد (ack)، كل تنفيذ جزئي، تأكيدات التعديل، تأكيدات الإلغاء. بالإضافة إلى حالة L2 عند لحظة الإرسال. هذا هو نفس انضباط التسجيل الذي تتطلبه التطابق بين الباكتيست والتداول الحي لمراقب الفجوات (DivergenceMonitor) الخاص بها — معايرة نموذج التنفيذ هي الطبقة الأعمق لذلك المراقب.
2. أعد تشغيل نفس الأوامر عبر المحاكي. غذِّ بيانات السوق المسجّلة وتعليمات الأوامر المسجّلة (لا التنفيذات) إلى المحاكي. الآن لديك نتائج مزدوجة: لكل أمر حي، مصير محاكى.
3. قارن التوزيعات، لا المتوسطات، ضمن دلاء (buckets). تطابق معدل تنفيذ إجمالي واحد يمكن أن يخفي أخطاء متعاوضة (متفائل جدًا في الأنظمة الهادئة، ومتشائم جدًا في الاندفاعات — تتصافى إلى "معايَر"). صنّف حسب المحركات:
import numpy as np
from scipy.stats import ks_2samp
def calibration_report(pairs, bucket_key):
"""pairs: [{'bucket':…, 'live_filled':bool, 'sim_filled':bool,
'live_ttf':float|None, 'sim_ttf':float|None}, …]"""
out = {}
for b in sorted({p['bucket'] for p in pairs}):
grp = [p for p in pairs if p['bucket'] == b]
live_fr = np.mean([p['live_filled'] for p in grp])
sim_fr = np.mean([p['sim_filled'] for p in grp])
live_ttf = [p['live_ttf'] for p in grp if p['live_ttf'] is not None]
sim_ttf = [p['sim_ttf'] for p in grp if p['sim_ttf'] is not None]
ks = ks_2samp(live_ttf, sim_ttf) if len(live_ttf) > 20 and len(sim_ttf) > 20 else None
out[b] = {
'n': len(grp),
'fill_rate_live': live_fr,
'fill_rate_sim': sim_fr,
'fill_rate_gap': sim_fr - live_fr, # signed: + means sim optimistic
'ttf_ks_pvalue': ks.pvalue if ks else None,
}
return out
إحصاءتان لكل دلو: فجوة معدل التنفيذ الموقّعة (المحاكي ناقص الحي) واختبار KS على توزيعات الزمن-حتى-التنفيذ بين الأوامر المنفَّذة. مقارنة الزمن-حتى-التنفيذ هي الأدق — يمكن لمحاكي أن يطابق معدلات التنفيذ بينما يُنفّذ عند أوقات خاطئة بشكل منهجي، مما يفسد كل إحصاء لاحق للمخزون والانتقاء السلبي. هذا بالضبط درس صياغة تحليل البقاء (survival-analysis) عند Lo-MacKinlay-Zhang: التنفيذ هو مشكلة زمن-حتى-الحدث، فتحقق منه على هذا الأساس.
4. عايِر المتغيرات، بترتيب قابلية التحديد. زمن الاستجابة أولًا (يُقاس مباشرة من طوابع زمن التأكيد — لا يُلائَم إحصائيًا). ثم بتصغير فجوة معدل التنفيذ عبر دلاء عمق الطابور. ثم تحقق من دلاء نظام التقلب: فجوة تفاؤل مستمرة متركزة في دلاء الاندفاعات عادة تعني أن محاكيك يُقصّر في نمذجة تنفيذات زمن استجابة الإلغاء السامة أو إعادة تعبئة المستوى، لا .
5. أعد تشغيل النطاق. بعد المعايرة، يجب أن يستقر تقدير استنفاد الطابور داخل النطاق قرب الواقع الحي، و— اختبار القبول الحقيقي — ترتيب بدائل الاستراتيجية تحت المحاكي يجب أن يطابق ترتيبها في وضع الظل (shadow mode). ثم جمّد المعاملات وأعد المعايرة على جدول زمني؛ ديناميكيات التنفيذ تنجرف مع فئات رسوم المنصة، وتغييرات حجم الخطوة السعرية، وتركيبة تجار التردد العالي، و المعايَر في مارس هو مجرد فرضية بحلول يوليو.
توقعات التقارب من تشغيلاتنا: محاكي الدرجة 4 غير المعايَر عادة ما يقع ضمن ±10-15 نقطة من معدل التنفيذ الحي؛ بعد جولة معايرة واحدة، ±3-5 نقاط، مع قيم p لاختبار KS للزمن-حتى-التنفيذ لم تعد ترفض بشكل موحّد. لن تحقق أفضل من ذلك بإعادة التشغيل التاريخي — الباقي هو رد فعل السوق تجاهك، وهذه مشكلة الدرجة 5.
ما يجب أخذه معك
- سمِّ درجتك. كل باكتيست يقع على هذا السلم سواء اخترت الدرجة أنت أم اختارها إطار العمل الخاص بك نيابة عنك. إن لم تستطع تسمية درجة نموذج التنفيذ الخاص بك وتحيزاته المعروفة، فرقم ربحك وخسارتك له أشرطة خطأ لم ترها بعد.
- يمكن للـ takers أن يتوقفوا عند الدرجة 3. مسح العمق بالإضافة إلى زمن الاستجابة المقاس يسعّر التنفيذ العدواني بصدق بحجم التجزئة. أنفق الجهد الموفَّر على جودة البيانات.
- يبدأ صناع السوق عند الدرجة 4. دون ذلك، منطق تنفيذ أوامر الحد ليس تقريبيًا فحسب — إنه ينتقي مجموعة تنفيذات مضادة للواقع بانحراف انتقاء سلبي معاكس. باكتيستات التنفيذ عند اللمس لاستراتيجيات صناعة السوق هي المولّد الأكثر موثوقية على الإطلاق لاستراتيجيات تموت عند أول تماس مع الإنتاج.
- انمذج دورة الحياة، لا التنفيذ. التنفيذات الجزئية، وإعادة ضبط الطابور عند التعديل، وزمن استجابة الإلغاء — آلة الحالات هي حيث تعيش التنفيذات السامة، والتنفيذات السامة هي حيث يموت ربح وخسارة صانع السوق.
- أبلغ عن النطاق. الحدود المتحفظة والمتفائلة تكلف تشغيلَي باكتيست إضافيين وتحوّل "باكتيستي يقول +7 آلاف دولار" إلى "الواقع في مكان ما ضمن [-1.9k]" — وهو قرار مختلف، وأفضل.
- عايِر مقابل التنفيذات الحية ضمن دلاء. نموذج تنفيذ مُتحقَّق منه إجماليًا فقط هو نموذج تنفيذ ذو أخطاء متعاوضة خفية. فجوات معدل التنفيذ المصنَّفة بالإضافة إلى اختبارات KS للزمن-حتى-التنفيذ، معايَرة كل ربع سنة.
درجات السلم ليست تمايزات أكاديمية — كل واحدة منها كذبة محددة يتوقف باكتيستك عن إخبارك بها. تسلّق حتى تصبح الأكاذيب أصغر من ميزتك.
روابط مفيدة
- Moallemi, C., Yuan, K. — A Model for Queue Position Valuation in a Limit Order Book (2016)
- Cont, R., Stoikov, S., Talreja, R. — A Stochastic Model for Order Book Dynamics, Operations Research 58(3), 549-563 (2010)
- Lo, A., MacKinlay, C., Zhang, J. — Econometric Models of Limit-Order Executions, Journal of Financial Economics 65(1), 31-71 (2002)
- Huang, W., Lehalle, C.-A., Rosenbaum, M. — Simulating and Analyzing Order Book Data: The Queue-Reactive Model, JASA 110(509), 107-122 (2015)
- Almgren, R., Chriss, N. — Optimal Execution of Portfolio Transactions (2001)
- Byrd, D., Hybinette, M., Balch, T. — ABIDES: Towards High-Fidelity Multi-Agent Market Simulation (2020)
- Binance API — Cancel-Replace order semantics
- CME Globex — Order modification and time priority rules
الاستشهاد
@article{soloviov2026fillsimulation,
author = {Soloviov, Eugen},
title = {Fill simulation: the ladder from close-price fantasy to queue-aware reality},
year = {2026},
url = {https://marketmaker.cc/blog/fill-simulation-partial-fills-backtest},
description = {Five rungs of fill simulation fidelity — from close-price fills to probabilistic queue-position models. Partial fills as a state machine, limit-fill probability bounds as a PnL bracket, and a calibration loop against live fills.}
}
Authors
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.