انزلاق التنفيذ (Implementation Shortfall) وتحليل تكلفة الصفقات الذاتي: قياس ما تكلفك عملية التنفيذ فعلًا
كل مكتب تداول مؤسسي لديه خط أنابيب لتحليل تكلفة المعاملات (TCA). أما من يشغّل بوت تداول عملات رقمية، فنادرًا ما يملك ذلك. الإعداد النمطي يسجل التنفيذات، يجمع الرسوم، ويسمي الفرق بين ربح/خسارة الباكتست وربح/خسارة التداول الحي "slippage" — رقم متبقٍ واحد غير مفسَّر يبتلع زمن الاستجابة (latency) والسبريد والتأثير (impact) والاختيار المعاكس (adverse selection) وكل أمر لم يُنفَّذ وهرب السعر منه. لا يمكنك إصلاح تكلفة تقيسها كرقم واحد. الآلية اللازمة لقياسها بشكل صحيح موجودة منذ عام 1988، وهي ليست ملكية خاصة، وفوق سجلات تنفيذاتك الخاصة تحتاج نحو 200 سطر من بايثون. هذا المقال يبنيها.
المكسب هنا ليس لوحة بيانات أجمل. الباكتست الخاص بك يحتوي على نموذج تكلفة — ثابت انزلاق، احتمال تنفيذ، معامل تأثير — وكل معامل فيه حاليًا مجرد تخمين. تحليل TCA فوق تنفيذات حقيقية هو الحقيقة الأرضية الوحيدة التي يمكن معايرة هذه المعاملات عليها. لقد بنينا جانب المحاكاة من هذه الحلقة في محاكاة التنفيذ: السلّم من خيال سعر الإغلاق إلى واقع مدرك للطابور؛ هذا المقال يبني جانب القياس.
الورقي مقابل الواقعي: ما قاسه بيرولد فعليًا
الحيلة الأساسية تعود لأندريه بيرولد (André Perold، 1988، "The Implementation Shortfall: Paper Versus Reality"، Journal of Portfolio Management 14(3)، 4–9). شغّل محفظتين بالتوازي. المحفظة الورقية (paper portfolio) تنفذ كل قرار فورًا، بحجم غير محدود، بتكلفة صفرية، بالسعر السائد لحظة القرار. المحفظة الحقيقية هي ما فعله بوتك فعليًا: تنفيذات جزئية، ملاحقة أسعار، إلغاء المتبقي، رسوم. انزلاق التنفيذ هو الفرق بين عائديهما.
هذا التعريف مهم بسبب ما يرفض إخفاءه. بيان الرسوم يُظهر العمولات فقط. تقرير التنفيذ مقابل سعر الحد لا يُظهر شيئًا على الإطلاق (أنت لا تُنفَّذ أبدًا بسعر أسوأ من حدك — بحكم البنية). المحفظة الورقية تحاسبك على كل شيء: الانجراف بين القرار والوصول، السبريد الذي عبرته، التأثير الذي سببته، والأهم — الأوامر التي لم تُنفَّذ أبدًا بينما هرب السعر. وصف واغنر وإدواردز (Wagner & Edwards، 1993، "Best Execution"، Financial Analysts Journal 49(1)، 65–71) الرسوم الظاهرة بأنها قمة جبل الجليد؛ فبالنسبة لأي شيء له دوران (turnover)، الجزء المغمور هو المهيمن.
لنثبّت الترميز. أمر أب (parent order): جهة (شراء/بيع)، حجم . سعر القرار هو منتصف السعر (mid) الذي رأته استراتيجيتك لحظة إطلاق الإشارة. التنفيذات تصل كأزواج بكمية منفَّذة إجمالية . عند الأفق الزمني (اكتمال الأمر الأب، إلغاؤه، أو انتهاء مهلته)، يكون المنتصف . الرسوم الصريحة . انزلاق التنفيذ بالقيمة النقدية:
وتُطبَّع إلى نقاط أساس (basis points) بالقسمة على القيمة الاسمية الورقية . القيمة الموجبة تعني أنك دفعت. الحد الأول هو ما كلّفتك تنفيذاتك مقارنة بالمحفظة الورقية؛ الثاني هو تكلفة الفرصة الضائعة عند بيرولد — المتبقي غير المنفَّذ مُقيَّمًا بالسعر الذي هرب إليه؛ الثالث هو الجزء الوحيد الذي يعترف به كشف حساب منصتك.
ملاحظة اصطلاحية: يستخدم القطاع مصطلح "سعر الوصول" (arrival price)، وفي معظم تحليلات TCA لأسواق الأسهم يعني سعر الوصول المنتصف لحظة وصول الأمر إلى السوق. أما بالنسبة للبوت، فوقت القرار ووقت الوصول يختلفان بمقدار زمن الاستجابة الداخلي الخاص بك بالإضافة إلى انتظار حدود المعدل (rate-limit) — تكلفة حقيقية وقابلة للقياس. لذا نحتفظ بكلا الطابعين الزمنيين وكلا السعرين، ونترك التفكيك يفصل بينهما.
التفكيك: التأخير، التأثير، التوقيت، الفرصة الضائعة، الرسوم
رقم IS واحد يخبرك أن التنفيذ مكلف. لكنه لا يخبرك لماذا، وحلول المكونات المختلفة مختلفة تمامًا — لا يمكنك حل تكلفة التأخير وتكلفة التأثير بنفس التعديل. تفكيك انزلاق التنفيذ الموسّع لروبرت كيسل (Robert Kissell) (Kissell، 2006، "The Expanded Implementation Shortfall: Understanding Transaction Cost Components"، Journal of Trading 1(3)، 6–16؛ طُوِّر بتفصيل في كتاب The Science of Algorithmic Trading and Portfolio Management، Academic Press، 2013) يفكك الإجمالي إلى مكونات، كل منها منسوب إلى مرحلة مميزة من دورة حياة الأمر. النسخة العملية، باستخدام منتصف الوصول (المنتصف عند أول تأكيد استلام من المنصة):
هذه المتطابقة تنحلّ تمامًا إلى تعريف بيرولد — وسّع الحدود ويُلغى . كل جزء له مالك مختلف:
تكلفة التأخير : انجراف السعر بين إطلاق الإشارة وأول أمر فرعي (child order) يصبح حيًا على المنصة. هذا يخص بنيتك التحتية — التسلسل (serialization)، الشبكة، طوابير حدود المعدل، فحوصات المخاطر. إذا كانت إشارتك تملك ألفا حقيقية قصيرة الأفق، فتكلفة التأخير هي المكان الذي تتسرب منه أولًا؛ متوسط موجب باستمرار يعني أن السوق يتحرك في صالحك قبل أن تصل — ألفا زخم متضائل، أو منافس أسرع يتداول نفس الإشارة.
تكلفة التداول : ما دفعته تنفيذاتك نسبة إلى الوصول — السبريد المعبور زائد تأثير السوق زائد الانجراف داخل الجدولة. هذا هو تقرير أداء خوارزمية التنفيذ، والكمية التي يُنمذجها بحث التنفيذ فعليًا. قاس ألمغرين وثوم وهاوبتمان ولي (Almgren, Thum, Hauptmann & Li، 2005، "Direct Estimation of Equity Market Impact"، Risk 18(7)، 58–62) هذا عبر نحو 700,000 أمر في أسهم أمريكية من مكاتب سيتي غروب (ديسمبر 2001–يونيو 2003) ووجدوا أن تكلفة التداول تتناسب مع التقلب اليومي ونسبة المشاركة — التأثير المؤقت يتبع قانون قوة (power law) في معدل التداول بأس قريب من 3/5، والتأثير الدائم قريب من الخطي بالنسبة للحجم. سنعيد استخدام صيغتهم الدالية عند المعايرة.
مخاطرة التوقيت: ليست حدًا في تفكيك المتوسط بل التباين حوله. توزيع الأمر الأب عبر الزمن يقلل التأثير المتوقع ويعرّضك للتقلب؛ لجدولة ذات مركز متبقٍ ، ينمو الانحراف المعياري للتكلفة كـ . هذا بالضبط المفاضلة التي يُحسِّنها إطار ألمغرين-كريس (Almgren–Chriss). في تقرير TCA الخاص بك، يظهر هذا كـ تشتت IS عبر الأوامر الأب — أبلغ عن الانحراف المعياري بجانب كل متوسط، وإلا سيحظى المتوسط بكل الاهتمام وستحظى الأطراف الذيلية (tails) بكل أموالك.
تكلفة الفرصة الضائعة : الكمية غير المنفَّذة مُقيَّمة بالسعر النهائي. بالنسبة للاستراتيجيات السلبية، هذا عادة أكبر مكون وأقله فحصًا، وهو الحد الذي يجعل الإطار بأكمله صادقًا — مزيد عن هذا في قسم الفخاخ، لأن حذفه هو الطريقة الأكثر شيوعًا التي يخدع بها الناس أنفسهم عبر TCA.
الرسوم : الجزء الصريح. في العملات الرقمية، سجّل الرسوم بعد الخصومات (مستويات VIP، حسميات الرموز محوَّلة بسعر لحظة التنفيذ) واحتفظ بإشارة رسوم صانع السوق (maker rebates) — الرسم السالب بيانات، لا ضجيج.
مثال محسوب
شراء بيتكوين. الإشارة تُطلق بـ ؛ القيمة الاسمية الورقية 600,000 دولار. أول أمر فرعي يُؤكَّد بمنتصف . خلال الدقيقتين التاليتين، يُنفَّذ 8 بيتكوين بمتوسط VWAP قدره 60,072؛ السعر يتجه بعيدًا، الخوارزمية تحترم حدها، ويُلغى المتبقي 2 بيتكوين بمنتصف . رسوم مدمجة 2.5 نقطة أساس على القيمة الاسمية المنفَّذة.
| المكون | الصيغة | دولار أمريكي | نقاط أساس من الورقي |
|---|---|---|---|
| التأخير | 120 | 2.0 | |
| تكلفة التداول | 480 | 8.0 | |
| الفرصة الضائعة | 456 | 7.6 | |
| الرسوم | 120 | 2.0 | |
| إجمالي IS | 1,176 | 19.6 |
بيان المنصة يُظهر 120 دولارًا. التكلفة الحقيقية لتنفيذ القرار كانت 1,176 دولارًا — بعامل عشرة، مع أكبر مكونين غير مرئيين في المحاسبة القائمة على الرسوم. نحو 40% منها جاء من كمية لم تُتداول أبدًا. تقرير TCA يحلل التنفيذات فقط كان سيقيّم هذا الأمر الأب بـ 8 نقاط أساس ويعتبره جيدًا.

Markouts: تسعير الاختيار المعاكس
انزلاق التنفيذ يقيّم الأمر الأب. لكنه لا يقول شيئًا عن جودة التنفيذات الفردية — تحديدًا، ما إذا كنت تتداول بشكل منهجي مع أطراف مقابلة تعرف شيئًا لا تعرفه أنت. هذا يُقاس بـ markouts: قيّم كل تنفيذ بمنتصف السعر عند أفق ثابت بعد حدوثه.
حيث هو سعر التنفيذ عند الزمن و هو المنتصف عند الزمن . هذا ربح/خسارة السوق للتنفيذ لكل وحدة عند الأفق ، وله بنية نظيفة عند : تنفيذ الصانع (maker) يبدأ عند نصف السبريد (اشتريت عند العرض، والمنتصف فوقك)؛ تنفيذ الآخذ (taker) يبدأ عند نصف السبريد. ما يحدث مع نمو هو المحتوى المعلوماتي للصفقة:
- ثانية يعزل القنص (sniping) واستغلال الأسعار المتقادمة (stale-quote pickoff). إذا كانت تنفيذات الصانع لديك بالفعل خاسرة بعد ثانية واحدة من التنفيذ، فإن مشاركين أسرع يضربون عروضك لحظة أن تصبح مسعّرة بشكل خاطئ — حلقة تحديث عروضك أبطأ من حلقة الزناد الخاصة بهم. هذا markout هو تشخيص لزمن الاستجابة، لا تشخيص للاستراتيجية.
- ثوانٍ يقيس الاختيار المعاكس الكلاسيكي: تنفيذات يتبعها استمرار الحركة عبر سعرك. بالنسبة لصانع السوق، هذه هي التكلفة التي يجب أن يتغلب عليها التقاط السبريد؛ البنية الجزئية للأسهم تسمي الكمية ذات الصلة "السبريد المُحقَّق" (realized spread)، المؤسَّس في تقارير قاعدة SEC رقم 605 عند أفق 5 دقائق. العملات الرقمية تتحرك أسرع؛ نطاق 10-60 ثانية هو المكافئ.
- ثانية يخبرك ما إذا كانت التنفيذات تحمل زخمًا ضدك بعد أفق البنية الجزئية — بالنسبة لاستراتيجيات الآخذ (taker)، ما إذا كانت ألفا إشارتك عند 60 ثانية تتجاوز السبريد زائد التأثير الذي دفعته للدخول. منحنى markout لآخذ يبدأ عند نقاط أساس ولا يعبر الصفر أبدًا هو استراتيجية تدفع مقابل دخولات لا تستطيع ألفاها تمويلها.
عدم التماثل بين الصانع والآخذ هو كامل اقتصاديات التداول السلبي في منحنيين. منحنى صانع يبدأ عند نقطة أساس (نصف السبريد) ويتضاءل إلى نقطة أساس بحلول 60 ثانية يقول: أنت تلتقط السبريد وتعيد أكثر منه، ولا يصلح ذلك أي مستوى رسوم مخفَّضة (rebate). المنحنى ذاته يستقر عند نقطة أساس يعني أن محرك عرض الأسعار يكسب أجره. هذا أيضًا بالضبط ما تفترضه بعيدًا محاكيات التنفيذ الساذجة (touch-fill) — محاكٍ ينفذك كلما لمس السعر حدك يتجاهل أن كونك مُنفَّذًا مرتبط بكونك مخطئًا، ولهذا السبب تحتاج درجة محاكاة الطابور المدركة في سلّم محاكاة التنفيذ إلى markouts مقاسة كمدخل، لا كافتراض.

الحساب هو merge_asof فوق دفق المنتصف الخاص بك:
import pandas as pd
def markouts(fills: pd.DataFrame, mids: pd.DataFrame,
horizons=("1s", "10s", "60s")) -> pd.DataFrame:
"""fills: [ts, price, qty, side, liquidity]; mids: [ts, mid].
Both UTC-indexed and sorted. Mid stream must be from YOUR captured
feed, not candles reconstructed later."""
fills = fills.sort_values("ts").reset_index(drop=True)
mids = mids.sort_values("ts")
out = fills.copy()
for h in horizons:
probe = fills[["ts"]].copy()
probe["ts"] = probe["ts"] + pd.Timedelta(h)
m = pd.merge_asof(probe, mids, on="ts", direction="backward")
out[f"mo_{h}"] = (fills["side"] * (m["mid"].values - fills["price"])
/ fills["price"] * 1e4)
return out
def markout_report(mo: pd.DataFrame) -> pd.DataFrame:
"""Qty-weighted markouts by liquidity flag. Weighting matters:
a 0.001 BTC fill and a 2 BTC fill are not equal evidence."""
cols = [c for c in mo.columns if c.startswith("mo_")]
def agg(g):
w = g["qty"] / g["qty"].sum()
return pd.Series({c: (g[c] * w).sum() for c in cols}
| {"n": len(g), "qty": g["qty"].sum()})
return mo.groupby("liquidity").apply(agg)
قسّم التقرير أكثر حسب الرمز، ساعة اليوم، ومسافة عرض السعر من المنتصف. أكثر التقسيمات قابلية للتنفيذ لاستراتيجية صانع هو markout حسب موضع الطابور عند التنفيذ: تنفيذات في مقدمة طابور جديد تتسعّر بشكل مختلف تمامًا عن تنفيذات حيث اجتيح المستوى بالكامل من خلالك.
خط الأنابيب: ما الذي يجب تسجيله
TCA يموت عند طبقة التسجيل، لا طبقة الرياضيات. الرياضيات أعلاه تحتاج أرقامًا يتخلص منها معظم البوتات، ولا يمكن إعادة بناء أي منها لاحقًا من سجل المنصة. غير القابلة للتفاوض:
- منتصف القرار، من دفقك الخاص، لحظة القرار. ليس إغلاق شمعة المنصة، ولا إعادة بناء لاحقة. المعيار المرجعي هو "السعر الذي اعتقدته استراتيجيتي عند اتخاذ القرار" — فقط عمليتك في تلك اللحظة تعرفه.
- كلا الطابعين الزمنيين: وقت القرار ووقت أول تأكيد استلام، وإلا فتكلفة التأخير غير قابلة للقياس وتندمج بصمت في تكلفة التداول.
- كل تنفيذ مع الطابع الزمني للمنصة، الرسم، وعلامة الصانع/الآخذ — وقت الاستلام المحلي لديك ملوَّث بزمن الاستجابة الوارد الخاص بك.
- الأوامر الأب الملغاة والمنتهية الصلاحية، مسجَّلة مثل كل شيء آخر. الأوامر الأب ذات التنفيذ الصفري هي أغلى الصفوف في الجدول.
- دفق منتصف مستمر (أو دفق L1) بدقة 100-250 ميلي ثانية، محتفَظ به لفترة كافية لحساب الـ markouts. إذا كنت تسجل بالفعل دفاتر الأوامر لمحاكي التنفيذ، فهذا مجاني.
جدولان مسطحان كافيان:
PARENTS = {
"parent_id": "str",
"strategy": "str",
"symbol": "str",
"venue": "str",
"algo": "str", # twap | pov | sniper | quote | ...
"side": "int8", # +1 buy, -1 sell
"qty": "float64", # parent size, base units
"limit_px": "float64", # NaN for unconstrained
"decision_ts": "datetime64[ns, UTC]",
"decision_mid": "float64", # mid your feed showed at decision_ts
"arrival_ts": "datetime64[ns, UTC]", # first exchange ack
"arrival_mid": "float64",
"end_ts": "datetime64[ns, UTC]", # filled / cancelled / expired
"terminal_mid": "float64",
"mkt_volume": "float64", # market volume over [arrival_ts, end_ts]
"sigma_bps": "float64", # realized vol estimate at decision time
}
FILLS = {
"parent_id": "str",
"ts": "datetime64[ns, UTC]", # exchange timestamp
"price": "float64",
"qty": "float64",
"fee": "float64", # quote ccy, post-discount, signed
"liquidity": "str", # maker | taker
"venue": "str",
}
دالة النسب هي نسخ مباشر للتفكيك:
import numpy as np
def is_decomposition(p: pd.Series, fills: pd.DataFrame) -> dict:
"""Expanded implementation shortfall for one parent, bps of paper
notional. Sign convention: positive = cost."""
s, X = p["side"], p["qty"]
paper = X * p["decision_mid"]
x = fills["qty"].sum()
delay = s * X * (p["arrival_mid"] - p["decision_mid"])
trade = s * ((fills["price"] - p["arrival_mid"]) * fills["qty"]).sum()
oppty = s * (X - x) * (p["terminal_mid"] - p["arrival_mid"])
fees = fills["fee"].sum()
bps = lambda v: 1e4 * v / paper
return {
"parent_id": p["parent_id"],
"delay_bps": bps(delay), "trade_bps": bps(trade),
"oppty_bps": bps(oppty), "fees_bps": bps(fees),
"is_bps": bps(delay + trade + oppty + fees),
"fill_ratio": x / X,
"participation": x / max(p["mkt_volume"], x),
}
def tca_table(parents: pd.DataFrame, fills: pd.DataFrame) -> pd.DataFrame:
fg = dict(tuple(fills.groupby("parent_id")))
empty = fills.iloc[0:0]
rows = [is_decomposition(p, fg.get(p["parent_id"], empty))
for _, p in parents.iterrows()]
return parents.merge(pd.DataFrame(rows), on="parent_id")
واستعلامات النسب، حيث يتوقف TCA عن كونه محاسبة ويبدأ في كونه بحثًا:
tca = tca_table(parents, fills)
def wavg(g: pd.DataFrame, col: str) -> float:
w = g["qty"] * g["decision_mid"] # notional weights
return (g[col] * w).sum() / w.sum()
comp = ["delay_bps", "trade_bps", "oppty_bps", "fees_bps", "is_bps"]
by_strat = tca.groupby("strategy").apply(
lambda g: pd.Series({c: wavg(g, c) for c in comp}
| {"is_std": g["is_bps"].std(), "n": len(g)}))
done = tca[tca["fill_ratio"] > 0.99]
done["pov_bin"] = pd.qcut(done["participation"], 6)
impact_curve = done.groupby("pov_bin").apply(lambda g: wavg(g, "trade_bps"))
tca["hour"] = tca["arrival_ts"].dt.hour
by_hour = tca.groupby("hour").apply(lambda g: wavg(g, "is_bps"))
by_venue = tca.groupby("venue").apply(
lambda g: pd.Series({"is_bps": wavg(g, "is_bps"),
"is_std": g["is_bps"].std(),
"fill_ratio": g["fill_ratio"].mean(), "n": len(g)}))
الاستعلام 4 هو جدول المدخلات الذي يُحسِّنه موجّه الأوامر الذكي (smart order router) — التوجيه بدون TCA لكل منصة هو توجيه حسب جدول الرسوم، أي حسب أصغر مكون تكلفة (توجيه الأوامر الذكي في العملات الرقمية يأخذ هذا الجدول كنقطة انطلاقه). مع وحدة الـ markout، هذا هو الـ 200 سطر الموعودة تقريبًا.
إغلاق الحلقة: معايرة نموذج تكلفة الباكتست
هنا يُثبت خط الأنابيب جدواه. الباكتست الخاص بك يفترض أرقامًا: slippage_bps = 5، منحنى احتمال تنفيذ، معامل تأثير. كل واحد منها ادعاء بشأن التنفيذ الحي، وجدول TCA هو التنفيذ الحي. الحلقة: قِس بواسطة TCA، لائم نموذج التكلفة، شغّل الباكتست بالنموذج الملائَم، تداول، أعد القياس.

بالنسبة لتكلفة الآخذ، استعِر الصيغة الدالية من ألمغرين وزملائه (2005) بدلًا من اختراع واحدة. نتيجتهم — التكلفة تتناسب مع التقلب اليومي مضروبًا في أس نسبة المشاركة — تعطي نموذجًا بمعاملين:
مع تقدير الأسهم كقيمة أولية (prior). لائمه على متوسطات مجمّعة في حاويات (binned means)، لا على الأوامر الأب الخام — تكاليف الأوامر الأب الفردية يهيمن عليها الضجيج (وهذا حد مخاطرة التوقيت)، وانحدار log-log على البيانات الخام سيلائم الضجيج بكل سرور:
done = tca[(tca["fill_ratio"] > 0.99) & (tca["participation"] > 0)]
done["norm_cost"] = done["trade_bps"] / done["sigma_bps"]
bins = done.groupby(pd.qcut(done["participation"], 8)).agg(
pov=("participation", "mean"), cost=("norm_cost", "mean"))
bins = bins[bins["cost"] > 0] # can't log a negative bin
b, log_a = np.polyfit(np.log(bins["pov"]), np.log(bins["cost"]), 1)
def taker_cost_bps(participation, sigma_bps, a=np.exp(log_a), b=b):
return a * sigma_bps * participation ** b
ثم كن صادقًا بشأن هوامش الخطأ. فريق ألمغرين امتلك 700,000 أمر وما زال يُبلغ عن أس التأثير المؤقت بقيمة ؛ بوت لديه 2,000 أمر أب لا يملك رفاهية تقدير بحرية لكل رمز. النظام العملي: اجمع عبر الرموز بعد التطبيع بـ ، اسحب بقوة نحو 0.6 (أو ثبّته وقم بملاءمة فقط)، وأعد الملاءمة شهريًا. إذا انجرف الملائَم لديك للأعلى، فإما أن بصمتك في السوق (footprint) نمت أو أن السوق أصبح أرق — في كلتا الحالتين كان على الباكتست أن يعرف ذلك.
بالنسبة لاستراتيجيات الصانع، أهداف المعايرة مختلفة وتأتي من الوحدتين الأخريين:
- احتمال التنفيذ: نموذج الطابور الخاص بمحاكي التنفيذ يتنبأ بـ لكل خلية (مسافة السبريد، موضع الطابور)؛ سجل الأوامر الأب الخاص بك يوفر نسب التنفيذ المحقَّقة لكل خلية. الاختلاف هو خطأ محاكاة مرفَق بمرجع شبكي.
- الاختيار المعاكس: استبدل افتراض المحاكي الضمني "التنفيذات قابلة للتبديل" بجدول markout المقاس — تنفيذ صانع محاكى عند مسافة في الساعة يحمل المقاسة كخصم تسعير فوري بالسوق. هذا التغيير الوحيد هو الفرق بين باكتست صانع يهلوس وآخر يتتبع الواقع؛ كان هو مدخل المعايرة المفقود المذكور في مقال محاكاة التنفيذ.
- تشتت التكلفة: أطعم الباكتست توزيع IS، لا متوسطه فقط. نموذج تكلفة يُزيح المتوسط فقط لا يمكنه إعادة إنتاج التراجعات (drawdowns) التي تخلقها مخاطرة التوقيت؛ حتى توزيع لوغاريتمي طبيعي (lognormal) ملائَم لـ IS لكل أمر أب يتفوق على ثابت.
المعالجة الكاملة لمنحنى الانزلاق — الصيغ الدالية، اشتراط النظام (regime conditioning)، متى ينهار قانون القوة — هي مقال قائم بذاته: منحنيات الانزلاق ونماذج التكلفة للباكتست. النقطة هنا معمارية: نماذج ذلك المقال غير قابلة للملاءمة بدون جداول هذا المقال.
الفخاخ
أدبيات TCA عمرها عقود، وكذلك طرق التلاعب بها. ثلاثة أنماط فشل تفسر معظم الخداع الذاتي.
التلاعب بالمعيار المرجعي (benchmark gaming). أي معيار مرجعي غير سعر الوصول يمكن "احتضانه" (hugged). المثال الكلاسيكي هو VWAP: خوارزمية تُقيَّم مقابل VWAP الفاصل الزمني يمكنها تتبعه ضمن نقطة أساس واحدة بينما ينزف المركز عشرين نقطة أساس مقابل الوصول، لأن المعيار المرجعي ينجرف مع السعر الذي تدفعه أنت — وعند نسبة مشاركة معتبرة، تنفيذاتك الخاصة هي الـ VWAP، لذا تتبعه هو واجب منزلي يُقيِّم نفسه بنفسه. لقد شرّحنا سياسات المعيار المرجعي في TWAP مقابل VWAP مقابل POV؛ القاعدة من جهة TCA أبسط: تُختار المعايير المرجعية قبل التداول، ويُحسَب دائمًا IS مقابل الوصول حتى عندما يُقيَّم جدولة ما مقابل معيارها الجدولي الخاص. المتغير الأدق هو التلاعب بالوصول: إذا كان المكون الذي يحدد decision_ts يستطيع رؤية الزخم قصير المدى، فيمكنه توقيت "القرارات" لتجميل حد التأخير. الطوابع الزمنية للقرار تنتمي إلى طبقة الإشارة، وتُسجَّل قبل تشغيل أي منطق تنفيذ.
تحيز البقاء (survivorship bias) في تحليل التنفيذات فقط. اشترط تحليل التكلفة على التنفيذات ويبدو التنفيذ السلبي مجانيًا. بشكل ملموس: 100 أمر أب شراء سلبي، عند تيك واحد تحت المنتصف. ستون منها ينفَّذ، و— كونها سلبية — تُنفَّذ بأسعار تتوسط 3 نقاط أساس أفضل من الوصول: "تكلفة" مقاسة نقاط أساس، تقرير يُفخَر به. الأربعون التي لم تُنفَّذ أبدًا كانت بالضبط تلك التي ارتفع السعر بعيدًا عنها؛ ضع علامة عليها بـ 25 نقطة أساس عكسية عند الإلغاء والرقم الصادق هو نقطة أساس. التقرير القائم على التنفيذات فقط والتقرير الصادق يختلفان بـ 11 نقطة أساس وبالإشارة. هذه ليست حالة حافة (corner case) — إنها آلية التداول السلبي ذاتها: كونك مُنفَّذًا مرتبط بمرور السعر عبرك، وهو نفس الاشتراط الذي يجعل باكتستات touch-fill خيالًا. تكلفة الفرصة الضائعة ليست تحسينًا اختياريًا لـ IS؛ إنها الحد الذي يدافع عن القياس بأكمله ضد التحيز الانتقائي. نفس التحيز له متغير من جهة الآخذ: أوامر IOC التي فاتت، أوامر رُفضت بسبب حدود المعدل أو فحوصات المخاطر — إذا لم تُسجَّل الفوائت، فتكلفة الفوات غير مقاسة، وهي الأكبر بالضبط في الأسواق السريعة حيث أرادت استراتيجيتك الصفقة أكثر ما أرادت.
أخطاء متنوعة، باختصار: مناصف وصول مُعاد بناؤها من شموع المنصة (دفقك والشمعة يختلفان بالضبط عندما يهم ذلك)؛ حساب متوسط نقاط الأساس لكل أمر أب بدون أوزان اسمية (ألف تنفيذ غباري يطغى تصويتًا على أمر حقيقي واحد)؛ رسوم مسجَّلة قبل الخصم؛ مناصف markout مأخوذة من منصة مختلفة عن منصة التنفيذ (فارق أساس عبر المنصات يتنكر كاختيار معاكس)؛ وفي العقود الدائمة (perps)، السماح لتراكم التمويل (funding) بالتسرب إلى نافذة التنفيذ — التمويل تكلفة، لكنه ليس تكلفة تنفيذ، ومزجهما يسمم كلا التحليلين.
ماذا تفعل هذا الأسبوع
أضف جدولي السجل إلى بوتك — المخطط أعلاه هو قائمة أعمدة، لا مشروعًا. لا تُعِد بناء أي شيء بأثر رجعي؛ أسبوعان من سجلات صادقة يتفوقان على سنة من إعادة البناء. شغّل التفكيك وآفاق الـ markout الثلاثة. ستتعلم أي مكون يهيمن (نادرًا ما تكون الرسوم)، وما إذا كانت تنفيذاتك السلبية تُختار ضدها بشكل معاكس يتجاوز التقاطها للسبريد، وإلى أي مدى يبتعد ثابت تكلفة الباكتست الخاص بك عن المنحنى المقاس. ثم أدمج المنحنى الملائَم مرة أخرى في المحاكي وأعد تشغيل الباكتست الذي أخبرك بتشغيل هذه الاستراتيجية في المقام الأول. محفظة بيرولد الورقية، بعد ثمانية وثلاثين عامًا، ما زالت الخصم الصادق الوحيد الذي تملكه محفظتك الحقيقية.
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.