تحيز النظر المستقبلي: كيف يُلفّق خطأ بفارق شمعة واحدة نسبة Sharpe تبلغ 15 من ضوضاء خالصة
مقال من سلسلة "اختبارات رجعية بلا أوهام".
📄 تطورت هذه المقالة إلى ورقة بحثية. خضعت ثلاثة تسريبات دقيقة من نوع النظر المستقبلي لاختبار مضبوط مقابل حقيقة أرضية معروفة (4,000 تاريخ محاكى). اقرأ الورقة على الإنترنت (نسخة تفاعلية + PDF) على lookahead.marketmaker.cc، والكود والبيانات على github.com/suenot/lookahead-inflation.
قبل بضعة أسابيع، كان مِعيار المقارنة الخاص بنا للبحث عن المعلمات يكذب علينا، وكدنا لا نلاحظ ذلك.
بدا المحرك نظيفاً: منطق الشمعة المغلقة، تقسيم متدحرج صادق للمشي للأمام (walk-forward)، بحث Sobol/QMC عبر فضاء المعلمات، ونافذة اختبار محجوزة جانباً. وجد البحث تهيئات بدت جيدة داخل العينة. المشكلة الوحيدة: خارج العينة، كانت كل النتائج تقريباً سلبية. افترضنا أن الاستراتيجية ضعيفة، لا أكثر.
ثم وجدنا سطراً واحداً. كانت الإشارة تُقرر عند إغلاق الشمعة i، لكن التنفيذ كان يُسجَّل على نفس الشمعة i بدلاً من افتتاح الشمعة التالية. خطأ إزاحة واحد (off-by-one) في مؤشر التنفيذ. نقلنا التنفيذ إلى open[i+1] — وهو السعر الوحيد الذي يمكنك التداول عنده فعلياً بعد رؤية إغلاق الشمعة i — فانقلبت إشارة نتيجة خارج العينة. تحول بحث Sobol من خسارة إلى ربح. لم يتغير شيء في الاستراتيجية نفسها. كل ما فعلناه هو أننا توقفنا عن التداول في الماضي.
هذا هو تحيز النظر المستقبلي، والجزء المقلق هو مدى صِغر الخطأ ومدى ضخامة نتيجته. هذا المقال تدقيق ذاتي مضبوط: نبني محاكياً تكون فيه الحقيقة الأساسية معروفة بحكم البناء، نُدخل التسريبات الدقيقة واحداً تلو الآخر، ونقيس بالضبط مقدار تضخيم كل منها للاختبار الرجعي. الخلاصة الرئيسية: بدون أي ميزة حقيقية على الإطلاق، يُنتج التنفيذ على نفس الشمعة نسبة Sharpe سنوية تبلغ +14.8 من ضوضاء خالصة.
ما هو تحيز النظر المستقبلي فعلياً

تحيز النظر المستقبلي هو أي نقطة في خط أنابيبك يستخدم فيها قرار أو قياس معلومات لم تكن لتكون متاحة، في الزمن الفعلي، لحظة استخدامها. الأمثلة المدرسية فجّة — استخدام أرباح السهم السنوية الكاملة في يناير، أو إعادة بيان لم تُنشر بعد. هذه سهلة الرصد. أما التي تنجو من مراجعة الكود فهي دقيقة، وتختبئ في ثلاثة أماكن:
- التنفيذ — تقرر عند الشمعة
iوتُنفِّذ على الشمعةiنفسها (أو تستخدم أعلى/أدنى سعر للشمعةiلأوامر الوقف على نفس الشمعة التي ولّدت الإشارة). أنت تتداول عند سعر مرتبط بالشيء الذي حفّز قرارك. - التطبيع — تُطبّق z-score أو min-max أو أي تحجيم آخر على ميزة باستخدام إحصاءات محسوبة عبر السلسلة كاملة، بما فيها المستقبل. أداة التحجيم "تعرف" مجموعة الاختبار.
- المؤشرات / الميزات — تُنعّم أو تُرشّح بنافذة مُتمركزة (أو تنظر إلى الأمام بطريقة أخرى)، بحيث تحتوي القيمة عند الشمعة
iبالفعل على جزء من الشمعةi+1.
الأشكال الثلاثة كلها صور مما تسميه أدبيات تعلّم الآلة التسرب (leakage): تلوث التدريب/التقييم بمعلومات من مستقبل الهدف (Kaufman et al., 2012؛ Kapoor & Narayanan, 2023). في التمويل، المرجع الكلاسيكي هو كتاب López de Prado Advances in Financial Machine Learning (2018) — التحقق المتقاطع المُنقّى، الحظر، ومخاطر الاختبار الرجعي. وانضباط التوقيت الحقيقي (point-in-time) يعود على الأقل إلى Fama & French (1992)، اللذين أخّرا عمداً بيانات المحاسبة بستة أشهر لكي تكون المتغيرة معروفة قبل العائد الذي تفسره.
السؤال الذي يجيب عنه هذا المقال كمّي: ليس "هل التسرب سيئ" (الجميع متفق على ذلك)، بل "كم نقطة Sharpe يمنحك كل شكل منها، وأيها الأخطر؟" بدون رقم، لا يمكنك التفكير في الأمر منطقياً. لا يمكنك معرفة ما إذا كان تضخّم بمقدار +0.3 مجرد ضوضاء، أم أن تضخّماً بمقدار +14 دليل إدانة قاطع.
محاكٍ بحقيقة أساسية معروفة

لقياس التضخّم تحتاج إلى معرفة الحقيقة. البيانات الحقيقية لا تخبرك بالحقيقة أبداً — فهي تمنحك تحققاً واحداً وليس عرّافاً. لذلك نبني سوقاً اصطناعياً نحن من يحدد فيه الميزة.
عملية توليد البيانات سببية بشكل صارم وغير متفجرة:
هنا هو انجراف كامن خارجي (exogenous) ومستمر (عملية AR(1) بمعامل )، وعائد الشمعة يحمل انجرافاً صغيراً معروفاً مسبقاً بشمعة واحدة. ولأن لا يعتمد على العوائد الماضية، لا توجد تغذية راجعة ولا شيء ينفجر. المعامل هو المقياس الذي يحدد مقدار الميزة الحقيقية الموجودة:
- — الحالة الصفرية (null): لا توجد ميزة على الإطلاق. أي نسبة Sharpe موجبة في الاختبار الرجعي هي 100% مصنوعة.
- — ميزة حقيقية وقابلة للتداول: قاعدة زخم صادقة تربح مالاً فعلياً.
الاستراتيجية بسيطة عن قصد — قاعدة إشارة زخم. الميزة هي مجموع العوائد المتأخرة على مدى ( شمعة)، والمركز هو إشارة هذا المجموع:
csum = np.concatenate(([0.0], np.cumsum(r))) # csum[k] = sum r[0..k-1]
mom = np.full(n, np.nan)
tt = np.arange(L - 1, n)
mom[tt] = csum[tt + 1] - csum[tt - L + 1]
signal = np.sign(mom) # position for the next bar
ميزة الزخم هذه هي الأداة المثالية لدراسة تسريب نفس الشمعة، لأنها تمتلك خاصية تشترك فيها المؤشرات الحقيقية: إنها تحتوي ميكانيكياً على الشمعة الحالية. mom[t] يتضمن r[t]. فإذا سجّلت r[t] كصفقتك، فأنت تراهن جزئياً على كمية موجودة بالفعل داخل إشارتك نفسها. هذا هو التسريب، بشكل ملموس.
الإعداد: (تقلب 1% لكل شمعة)، رسوم اتجاه واحد قدرها 0.00045 (ذهاب وإياب 0.09%، مطابقة لمحركنا)، Sharpe مُسنّن سنوياً بضرب (شموع بالساعة)، 4,000 تاريخ مستقل، كل منها 4,000 شمعة. كل شيء مزروع البذرة (seeded) وحتمي.
خط الأنابيب الصادق (الوحيد القابل للتداول)
قرر عند إغلاق الشمعة t، اربح عائد الشمعة التالية، وادفع الرسوم عند تغيّر المركز:
def sharpe(sig, ret_booked):
dpos = np.abs(np.diff(np.concatenate(([0.0], sig))))
pnl = sig * ret_booked - FEE_ONEWAY * dpos
return pnl.mean() / pnl.std() * np.sqrt(8760)
honest = sharpe(signal[idx], r[idx + 1]) # earn r[t+1]: tradable
التسريبات الثلاثة، كل منها تغيير جراحي واحد
same_bar = sharpe(signal[idx], r[idx])
z_full = (mom - mom[valid].mean()) / mom[valid].std()
norm_full = sharpe(np.sign(z_full[idx]), r[idx + 1])
z_sm = (mom[:-2] + mom[1:-1] + mom[2:]) / 3.0 # uses t-1, t, t+1
indicator = sharpe(np.sign(z_sm[idx]), r[idx + 1])
كل تسريب يبعد سطراً واحداً فقط عن خط الأنابيب الصادق. هذا هو بيت القصيد: هذه ليست أخطاء غريبة، بل من النوع الذي يمر عبر المراجعة دون أن يُلاحظ.
النتائج: حجم كل تسريب

بتشغيل عبر 4,000 بذرة عشوائية، إليك نسبة Sharpe السنوية التي يُبلغ عنها كل خط أنابيب، تحت الحالة الصفرية (بلا ميزة) وتحت ميزة حقيقية (، مضبوطة بحيث يكون Sharpe الصادق رقماً معقولاً قدره +1.57):
| خط الأنابيب | الحالة الصفرية (بلا ميزة) | ميزة حقيقية |
|---|---|---|
| الصادق (الحقيقة) | −0.74 | +1.57 |
| التنفيذ على نفس الشمعة | +14.79 | +15.85 |
| نظرة مؤشر مستقبلية (شمعة واحدة) | +4.76 | +6.62 |
| التطبيع على كامل السلسلة | −0.84 | +1.46 |
فترات الثقة 95% عبر البذور العشوائية هي ±0.05 أو أضيق في كل خلية؛ واختبارات t المزدوجة على التضخّم دالة إحصائياً بشكل فلكي حيث يكون التأثير حقيقياً (t > 400, p ≈ 0).
اقرأ عمود الحالة الصفرية أولاً، لأنه أنظف تجربة ممكنة: لا توجد ميزة على الإطلاق، لذا يخسر خط الأنابيب الصادق المال بشكل صحيح (−0.74، وهو عبء دفع الرسوم مقابل تداول الضوضاء). والآن انظر ماذا تفعل التسريبات بهذا العدم نفسه:
- التنفيذ على نفس الشمعة: −0.74 ← +14.79. استراتيجية بلا أي قدرة تنبؤية، تتداول ضوضاء عشوائية بحتة، تُبلغ عن نسبة Sharpe سنوية تقارب 15. هذا ليس تحيزاً دقيقاً؛ إنه تلفيق كامل. الآلية هي بالضبط ما بنيناه عمداً: ميزة الزخم تحتوي على
r[t]، فتسجيلr[t]هو رهان على إشارتك أنت نفسها. - نظرة المؤشر المستقبلية: −0.74 ← +4.76. السماح للمُنعِّم برؤية شمعة واحدة في المستقبل يُلفّق نسبة Sharpe تقارب 5 من الضوضاء، لأن القيمة المُنعّمة عند
tتصبح الآن مرتبطة بـr[t+1]الذي أنت على وشك ربحه. - التطبيع على كامل السلسلة: −0.74 ← −0.84. لا يوجد تضخّم فعلياً. هذه هي النتيجة الصادقة وغير البديهية (المزيد عنها أدناه).
عمود الميزة يحمل الرسالة الأخطر. فعندما توجد ميزة حقيقية فعلاً (Sharpe صادق +1.57)، لا تكتفي التسريبات بإضافة ثابت — بل تدفع Sharpe المقاس إلى +15.85 و+6.62، أعلى بكثير من +1.57 التي كان بإمكانك تداولها فعلياً. إذن الرقم المقاس لا يستطيع التمييز بين المهارة والتسريب. رقم +6 مُسرَّب ورقم +6 صادق يبدوان متطابقين في التقرير. لن تعرف أيهما كان لديك إلا بعد أن تكون قد نشرت رأس المال فعلياً.
التسريب تدرّج، لا مفتاح تبديل

اعتراض طبيعي: "تسجيل شمعة الإشارة بأكملها خطأ متطرف وغير واقعي." لذا مسحنا الجرعة — النسبة من شمعة الإشارة التي يلتقطها التسريب، من 0 (صادق) إلى 1 (تسريب كامل على نفس الشمعة):
| نسبة الالتقاط | Sharpe الحالة الصفرية | Sharpe الميزة |
|---|---|---|
| 0.00 (صادق) | −0.74 | +1.57 |
| 0.25 | +3.90 | +6.41 |
| 0.50 | +9.86 | +12.20 |
| 1.00 (تسريب كامل) | +14.79 | +15.85 |
التقاط ربع شمعة الإشارة فقط ينقل استراتيجية بلا ميزة من −0.74 إلى +3.90. لست بحاجة إلى خطأ الإزاحة الكامل لتنخدع؛ تنفيذ مُغرٍ قليلاً أكثر من اللازم — لمسة من الانزلاق السعري المتفائل على شمعة الإشارة، أو وقف داخل الشمعة يُتحقق منه مقابل نفس الشمعة التي حفّزته — كافٍ لتجاوز معظم عتبات "قابلية النشر". التضخّم سلس ورتيب بمقدار ما تسمح لنفسك بتداوله من الحاضر.
كم مرة يضع هذا استراتيجية خاسرة في الإنتاج؟
الرقم الذي يجب أن يُقلق أي ممارس هو معدل النشر الخاطئ: عدد المرات التي يجعل فيها التسريب تهيئة خاسرة للمال فعلياً تتجاوز الحد الذي كنت ستستخدمه للموافقة عليها. باستخدام "Sharpe سنوي ≥ 1.0" كمعيار للنشر، تحت الحالة الصفرية:
- التنفيذ على نفس الشمعة: 68% من الاستراتيجيات بلا ميزة تبدو قابلة للنشر وخاسرة للمال فعلياً في آن واحد. اثنتان من كل ثلاث تهيئات ضوضاء خالصة كانتا ستجتازان بوابة Sharpe ≥ 1 وتخسران المال في التداول الحي. (هذا المعدل مُعرَّف بوضوح هنا لأن التسريب يقع بالكامل في التنفيذ — والنظير الصادق هو نفس الإشارة مع تنفيذ صادق.)
- نظرة المؤشر المستقبلية: تدفع عملياً كل تهيئة بلا ميزة فوق حد النشر أيضاً (99.9% تتجاوز Sharpe ≥ 1) — إنها تُمرّر الضوضاء مباشرة إلى الإنتاج.
- التطبيع على كامل السلسلة: 12% فقط تتجاوز الحد — وهو أساساً معدل الضوضاء الأساسي، بلا أي علاوة ناتجة عن التسريب.
التصنيف، وكيفية اكتشاف كل نوع
التسريبات الثلاثة ليست متساوية في الخطورة، والفروق بينها مفيدة.
1. تسرب التنفيذ (المُكلف)

العرض: سعر التنفيذ مرتبط بالإشارة لأنهما يأتيان من نفس الشمعة. الحجم: هائل (+15 من الضوضاء عند الجرعة الكاملة، +3.9 عند ربع الجرعة). لماذا هو الأسوأ: إشارتك، تقريباً بالتعريف، مبنية من حركة السعر الأخيرة، لذا فإن عائد شمعة الإشارة هو بالضبط الشيء الأكثر ارتباطاً بميزتك. تسجيله أشبه بالاطلاع على الإجابة سلفاً.
الاكتشاف — اختبار إزاحة الشمعة الواحدة. هذا هو التشخيص الأكثر قيمة في هذا المقال بأكمله. خذ اختبارك الرجعي وأزح كل تنفيذ شمعة واحدة إلى الأمام (قرر عند i، ونفّذ عند open[i+1]). إذا بالكاد تحركت النتيجة، فتنفيذك كان صادقاً. إذا انهارت النتيجة أو انقلبت إشارتها، فأنت كنت تتداول في الماضي. هذا بالضبط ما حدث لبحث Sobol لدينا: أزح التنفيذات، واتضح أن نتيجة OOS "الرابحة" كانت في الواقع خسارة — أو بالأحرى، ظهرت العلاقة الحقيقية بمجرد إزالة التسريب.
entry_price = open_[i + 1] # NOT close[i], NOT open[i]
2. تسرب المؤشر / الميزة (الهادئ)
العرض: مؤشر عند الشمعة i يعتمد على بيانات من i+1 أو ما بعدها — متوسط متحرك مُتمركز، مرشّح بلا تأخير سببي، تصنيف قمة/قاع يحتاج إلى شموع مستقبلية لتأكيده، أو تحويل بأسلوب Heikin-Ashi يُغذَّى بشموع مستقبلية. الحجم: كبير (+4.8 من الضوضاء). لماذا يختبئ: التسريب مدفون داخل استدعاء مكتبة. scipy.signal.filtfilt عديم الطور (zero-phase) — وعديم الطور يعني غير سببي. ميزة من نوع "هذه الشمعة قمة محلية" غير معروفة حتى تُطبع الشمعة التالية.
الاكتشاف: لكل مؤشر، اسأل ما هو أعلى مؤشر (index) يقرأه؟ إذا كان حساب القيمة عند t يلمس t+1 في أي وقت، فهو غير سببي. احسب المؤشرات على نافذة سببية متوسعة/متدحرجة وتحقق من أن القيمة عند الشمعة t متطابقة سواء وُجدت شموع بعد t في المصفوفة أم لم توجد. (تطبيقاتنا لـ HMA/ADX تجتاز هذا الاختبار: كل مُخرَج عند t يقرأ فقط مدخلات عند ≤ t.)
3. تسرب التطبيع (المرتبط بالقناة)
العرض: أداة تحجيم (StandardScaler، min-max، أو z-score عام) تُدرَّب على مجموعة البيانات كاملةً، بما فيها مجموعة الاختبار. تحذيرات تعلّم الآلة الكلاسيكية صريحة بشأن هذا — كتاب Hastie وTibshirani وFriedman Elements of Statistical Learning §7.10.2 ("الطريقة الخاطئة والطريقة الصحيحة لإجراء التحقق المتقاطع")، ودليل common-pitfalls الخاص بـ scikit-learn نفسه: "يجب أن يكون المتوسط هو متوسط مجموعة التدريب الفرعية، لا متوسط كل البيانات."
الحجم في اختبارنا: ≈ صفر (−0.74 ← −0.84). هذه هي النتيجة المفاجئة والصادقة، وتستحق أن تُفهم لا أن تُحفظ.
لماذا لم يحدث تضخّم؟ لأن استراتيجيتنا تستخدم الميزة فقط من خلال إشارتها (عتبة صفرية). تحجيم الانحراف المعياري لا يغيّر الإشارة أبداً، وتمركز المتوسط العام لا يزيح نقطة عبور الصفر إلا بشكل طفيف. لذا فإن التوحيد القياسي على كامل السلسلة لقاعدة إشارة صرفة يكاد يكون غير ضار.
لا تُعمِّم هذا بشكل مفرط. تسرب التطبيع مرتبط بالقناة التي يمر عبرها. فبمجرد أن تستخدم استراتيجيتك حجم الميزة — تحديد حجم المركز بما يتناسب مع z-score، أو عتبة دخول غير صفرية تُختار بالنظر إلى التوزيع المُحجَّم، أو شبكة عصبية تستهلك مدخلات مُوحَّدة قياسياً — تبدأ أداة التحجيم المُطّلعة على المستقبل بالأهمية، وتزداد أهميتها كلما اختلفت الإحصاءات العامة عن السببية منها. نتيجتنا ليست "تسرب التطبيع آمن." بل هي "حجم التسرب يعتمد على القناة التي تدخل عبرها الكمية المُسرَّبة إلى القرار، وعليك أن تقيسه بدلاً من افتراضه." قاعدة الإشارة هي الحالة الوحيدة التي يكون فيها هذا التسريب بالذات رخيصاً.
أين يتقاطع هذا مع غيره
تحيز النظر المستقبلي هو الحلقة الأولى في سلسلة كانت هذه المجموعة من المقالات توثقها:
- إنه يُفسد المُدخَل الذي يُغذّى إلى التحقق. اختبار رجعي مُسرَّب سيمرّ بسلاسة عبر تقسيم walk-forward وسيبدو مثل هضبة عريضة بدلاً من قمة مُفرطة في التخصيص — لأن التسريب ثابت عبر جميع الطيات (folds)، فلا يستطيع التحقق المتقاطع رصده. التسرب هو نمط الفشل الواقع قبل الإفراط في التخصيص، ولن ينقذك أي قدر من التحقق الصادق اللاحق.
- يتفاعل مع البحث عن المعلمات: بحث عبر آلاف المحاولات على بيانات مُسرَّبة سيجد التهيئة التي تستغل التسريب بأكبر قدر من العدوانية. "الفائز" هو أسوأ المتجاوزين.
- إنه السبب في تباعد التطابق بين الاختبار الرجعي والتداول الحي. التسريب هو التفسير الأنظف لفجوة 30–50% بين الاختبار الرجعي والبوت، لأن التداول الحي هو، ميكانيكياً، المكان الوحيد الذي لا يمكنك فيه النظر إلى الأمام.
الانضباط الذي يرصد كل هذا هو نفسه الذي ما فتئت الأدبيات الأكاديمية تحث عليه منذ سنوات: عامِل الاختبار الرجعي كتجربة إحصائية ذات حدود معلوماتية صارمة. أظهر Bailey وBorwein وLópez de Prado وZhu مدى سهولة أن يُلفّق الإفراط في التخصيص أداءً مزيفاً (2014)؛ وبروتوكول الاختبار الرجعي لـ Arnott وHarvey وMarkowitz (2019) يُقنِّن قواعد النظافة هذه. تحيز النظر المستقبلي هو أبسط حد من كل الحدود — الحد في الزمن — والأرخص انتهاكاً عن طريق الخطأ.
الخلاصات

- تحيز النظر المستقبلي ضخم كمّياً وغير مرئي نوعياً. خطأ تنفيذ واحد بفارق شمعة واحدة حوّل Sharpe من −0.74 (ضوضاء خالصة، تخسر بشكل صحيح) إلى +14.79. الخطأ سطر واحد؛ والنتيجة سجل أداء مُلفّق بالكامل.
- إنه تدرّج. التقاط حتى 25% فقط من شمعة الإشارة يُنتج +3.90 من العدم. لست بحاجة إلى خطأ فاضح — قليل من التفاؤل الزائد في تنفيذاتك كافٍ.
- الرقم المقاس لا يستطيع التمييز بين المهارة والتسريب. عندما توجد ميزة حقيقية، تُضخّم التسريبات التقرير إلى ما هو أبعد بكثير من الحقيقة القابلة للتداول. الدفاع الوحيد هو العملية، لا المقياس.
- اختبار إزاحة الشمعة الواحدة هو أسرع تشخيص لديك. حرّك كل تنفيذ شمعة واحدة إلى الأمام. إذا انهار الأداء، فأنت كنت تتداول في الماضي.
- حجم التسرب مرتبط بالقناة. التنفيذ ونظرات المؤشر المستقبلية مدمّرة؛ بينما التطبيع على كامل السلسلة لقاعدة إشارة يكاد يكون مجانياً. قِس التسريب عبر القناة التي يدخل منها فعلياً — لا تفترض.
الدراسة الكاملة المضبوطة — التسريبات الثلاثة كلها، ومسح الجرعة، وتحليل النشر الخاطئ، والطرائق الصورية، وكل رقم قابل لإعادة الإنتاج من سكربت حتمي واحد — موجودة في الورقة المرافقة على lookahead.marketmaker.cc، مع الكود والبيانات على github.com/suenot/lookahead-inflation.
الاستراتيجية في تجربتنا الصفرية لم تكن تملك أي ميزة على الإطلاق. ومع ذلك أظهرت Sharpe بقيمة 15. إذا بدا اختبارك الرجعي جيداً أكثر مما ينبغي، فأول ما يجب أن تشك فيه ليس عبقريتك — بل ساعتك.
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.