قيمة لا يمكن أن تكون صحيحة
عائد يومي +30% في سهم كبير إما استحواذ وإما خطأ في البيانات كتقسيم منسي أو فاصلة عشرية في غير موضعها. القيمة الشاذة بعيدة عن غيرها بما يستدعي قرارًا: الإبقاء أو التصحيح أو الإزالة. لا تحذفها لمجرد أنها مزعجة فالصدمات الحقيقية هي بالضبط ما يجب أن تراه نماذج المخاطر. والخطوة الأولى دائمًا إظهارها بقاعدة صريحة قابلة للتكرار.
قاعدة المعيار z ولماذا قد تفشل
تُعلّم القاعدة الكلاسيكية القيم التي تبعد أكثر من 2 أو 3 انحرافات معيارية عن المتوسط: z = (x - mean) / std. وهي بسيطة وتنجح مع البيانات النظيفة. لكن القيمة الشاذة نفسها تضخّم المتوسط وخصوصًا الانحراف المعياري، فـتختبئ من القاعدة. في المثال أدناه ينال يوم +30% معيار z قدره 2.85 فقط، وبعتبة 3 لن يُعلَّم. وكلما زاد تطرف الخطأ زادت حمايته لنفسه.
import pandas as pd
returns = pd.Series([0.004, -0.002, 0.001, 0.003, -0.004, 0.002, 0.30, -0.001, 0.0, 0.002])
z = (returns - returns.mean()) / returns.std()
print(z.round(2).tolist())
# [-0.28, -0.34, -0.31, -0.29, -0.36, -0.3, 2.85, -0.33, -0.32, -0.3]
print(returns.mean().round(4), returns.std().round(4)) # 0.0305 0.0947 one day moved the mean tenfold
print(returns.drop(6).std().round(4)) # 0.0026 the std without that dayقواعد متينة: IQR وMAD
الإحصاءات المتينة لا تكاد تتأثر بالقيم الشاذة التي تطاردها. يقيس المدى الربيعي IQR = Q3 - Q1 تشتت النصف الأوسط من البيانات، وتقع القيم التي تتجاوز Q1 - 1.5 * IQR أو Q3 + 1.5 * IQR خارج حدود مخطط الصندوق. ويستبدل MAD (الانحراف المطلق الوسيط) بالانحراف المعياري وسيطًا، ويُقرأ المعيار z المعدّل 0.6745 * (x - median) / MAD كالمعيار z العادي (3.5 عتبة شائعة). وكلاهما يعلّم يوم +30% بلا عناء.
# The fences of a box plot
q1, q3 = returns.quantile(0.25), returns.quantile(0.75)
spread = q3 - q1
lower, upper = q1 - 1.5 * spread, q3 + 1.5 * spread
print(round(lower, 4), round(upper, 4)) # -0.006 0.008
print(returns[(returns < lower) | (returns > upper)].to_dict()) # {6: 0.3}
# The modified z-score, built on the median
median = returns.median()
mad = (returns - median).abs().median()
modified_z = 0.6745 * (returns - median) / mad
print(modified_z.round(1).tolist()) # [0.8, -1.2, -0.2, 0.5, -1.9, 0.2, 100.7, -0.8, -0.5, 0.2]الاقتطاع: قصّ بدل الحذف
حذف صف يحذف أيضًا معلومات أعمدته الأخرى ويكسر المسافات بين التواريخ. أما الاقتطاع (winsorizing) فيُبقي كل الصفوف ويسحب القيم المتطرفة إلى كمّيات مختارة مثل 1% و99%: أي قيمة دون الكمّي 1% تصبح ذلك الكمّي، وأي قيمة فوق الكمّي 99% تصبح هو. وفي pandas ذلك هو clip(lower, upper) بحدود مأخوذة من quantile. يبقى شكل السلسلة وتفقد القيم المتطرفة تأثيرها على المتوسطات والانحدارات.
low, high = returns.quantile(0.1), returns.quantile(0.9)
print(round(low, 4), round(high, 4)) # -0.0022 0.0336
clipped = returns.clip(lower=low, upper=high)
print(clipped.round(4).tolist())
# [0.004, -0.002, 0.001, 0.003, -0.0022, 0.002, 0.0336, -0.001, 0.0, 0.002]
# ^ raised ^ the 30% day pulled back to the 90% quantile# Flag with a rule, then look at what is flagged before deciding anything
mask = z.abs() > 2
print(returns[mask].to_dict()) # {6: 0.3} the +30% day
print(returns[~mask].std().round(4)) # 0.0026 the volatility of the remaining days- قاعدة المعيار z
abs((x - mean) / std) > kبسيطة، لكن القيم الشاذة تضخّم المتوسط والانحراف وقد تختبئ. - القواعد المتينة تستخدم الكمّيات والوسائط: حدود IQR (
Q1 - 1.5 IQRوQ3 + 1.5 IQR) والمعيار z المعدّل القائم على MAD. clip(lower, upper)بحدود الكمّيات (الاقتطاع) تُبقي الصفوف؛ ولا تحذف صدمة دون معرفة ماهيتها.
التالي: الإجراءات المؤسسية، أي التقسيمات والأرباح الموزعة التي تجعل السعر القديم غير قابل للمقارنة بسعر اليوم.
المختبر: ما الذي يُقيَّم
- ضع علامة على العوائد البعيدة باستخدام
zscore_outliers25 نقطة - احسب حدود مخطط الصندوق باستخدام
iqr_bounds25 نقطة - ضع علامة على القيم الشاذة بدرجة متينة باستخدام
mad_outliers25 نقطة - روّض القيم المتطرفة باستخدام
winsorize25 نقطة