σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
σμimplied vol · KKmax(S−K,0)udβρᵢⱼfat tailsPnL · drawdownyield · TdSₜ = μSₜ dt + σSₜ dWₜC = S·N(d₁) − K·e⁻ʳᵀ·N(d₂)σₚ² = wᵀΣwd₁ = [ln(S/K) + (r + σ²⁄2)T] ⁄ σ√T∂V/∂t + ½σ²S²·∂²V/∂S² + rS·∂V/∂S − rV = 0Sharpe = (Rₚ − R_f) ⁄ σₚVaR₉₉ = μ − 2.33σρ = Cov(X,Y) ⁄ σₓσᵧE[Rₚ] = Σ wᵢ·E[Rᵢ]φ(x) = e^(−x²/2) ⁄ √2πE[Rᵢ] = R_f + βᵢ(E[Rₘ] − R_f)dXₜ = θ(μ − Xₜ)dt + σ dWₜσ²ₜ = ω + α·ε²ₜ₋₁ + β·σ²ₜ₋₁C − P = S − K·e⁻ʳᵀΔ = ∂V/∂S Γ = ∂²V/∂S²p = (e^(rΔt) − d) ⁄ (u − d)rₜ = ln(Pₜ ⁄ Pₜ₋₁)E[Xₜ₊₁ | ℱₜ] = Xₜf* = (bp − q) ⁄ bz = (x − μ) ⁄ σP(N=k) = λᵏe^(−λ) ⁄ k!Θ = −∂V/∂Tν = S·φ(d₁)·√Tmin wᵀΣw s.t. wᵀμ = μ*∫Σ∂∞λ
uantCraft Academyالمسارات
Ctrl K
AO
+1.2k متعلّم
تسجيل الدخولانضم ↗
المسارات
AO
+1.2k متعلّم
تسجيل الدخول
  • English
  • Français
  • Español
  • العربية
  • Português
  • Deutsch
  • 日本語
  • 中文
مسار Python›الوحدة 2 · NumPy وpandas لبيانات السوق›الموضوع 2.15·~40 دمتوسط

التعامل مع البيانات المفقودة

الموضع في المسارالوحدة 2 من 11 · الموضوع 15 من 20
2.15 التعامل مع البيانات المفقودة
—درجة المختبر— / 100إجمالي XP—التتابع—

فجوات في البيانات

تحتوي جداول الأسعار الحقيقية على فجوات: سهم لم يُتداول ذلك اليوم، أو مصدر بيانات أسقط سعرًا، أو سوق في عطلة. تشير pandas إليها بـ NaN («ليس رقمًا»). قبل اختيار ما تفعله، انظر: يعطي df.isna() جدول صح/خطأ، ويعدّ .sum() الفجوات لكل عمود، ويعطي .mean() نسبتها. عمود فارغ بنسبة 40% مشكلة تختلف عن عمود ينقصه قيمة واحدة.

import pandas as pd

nan = float("nan")
df = pd.DataFrame(
    {"AAPL": [184.0, nan, 186.5, 187.0, nan], "MSFT": [410.0, 411.0, nan, nan, 415.0]},
    index=pd.bdate_range("2026-03-02", periods=5),
)

print(df.isna().sum().to_dict())           # {'AAPL': 2, 'MSFT': 2}   holes per column
print(df.isna().mean().round(2).to_dict())   # {'AAPL': 0.4, 'MSFT': 0.4}   share of holes

الترحيل أو الحذف

الملء الطبيعي للأسعار هو آخر سعر معروف: إلى أن يصل سعر جديد يبقى السوق عند السعر القديم. وهذا هو ffill() (الملء الأمامي). والفجوة الطويلة تعني غالبًا بيانات قديمة، لذا يملأ ffill(limit=2) يومين متتاليين على الأكثر. وتبقى قيم NaN في أول السلسلة تمامًا كما هي لعدم وجود سعر سابق يُرحَّل. والبديل هو الحذف: يزيل dropna() كل صف فيه فجوة، ولا ينظر dropna(subset=["AAPL"]) إلا إلى الأعمدة التي تهمك. الحذف آمن لكنه يقلل البيانات ويغيّر المسافات بين التواريخ.

msft = df["MSFT"]
print(msft.ffill().tolist())           # [410.0, 411.0, 411.0, 411.0, 415.0]
print(msft.ffill(limit=1).tolist())    # [410.0, 411.0, 411.0, nan, 415.0]   only one day carried

print(len(df.dropna()))                          # 1   only one row is complete
print(len(df.dropna(subset=["AAPL"])))           # 3   rows where AAPL is known

الاستيفاء وما لا يجوز ملؤه أبدًا

يملأ interpolate() الفجوة بخط مستقيم بين القيمتين المعروفتين على جانبيها. يناسب الكميات الملساء (منحنى العائد أو مستوى التقلب) ونادرًا الأسعار التي تقفز. احذر عند الأطراف: افتراضيًا ينسخ interpolate() آخر قيمة في قيم NaN الأخيرة، وهذا اختلاق للبيانات. ويقيّده limit_area="inside" بالفجوات بين قيمتين معروفتين. ولا تملأ بـ 0 عشوائيًا: سعر 0 انهيار، وعائد 0 يوم ثابت، وتغيّر fillna(0) في الجدول الخطأ كل متوسط تحسبه لاحقًا بصمت.

gappy = pd.Series([nan, nan, 10.0, nan, nan, 16.0, nan])

print(gappy.interpolate().tolist())
# [nan, nan, 10.0, 12.0, 14.0, 16.0, 16.0]   the last 16.0 is invented

print(gappy.interpolate(limit_area="inside").tolist())
# [nan, nan, 10.0, 12.0, 14.0, 16.0, nan]    only between known values
# Filling with 0 is a decision, not a default: it changes the statistics
print(gappy.fillna(0).tolist())   # [0.0, 0.0, 10.0, 0.0, 0.0, 16.0, 0.0]
print(gappy.mean())                # 13.0   NaN are skipped
print(gappy.fillna(0).mean())      # 3.7142857142857144   the zeros drag the average down
املأ من الماضي لا من المستقبليستخدم bfill() وinterpolate() قيمًا لاحقة للفجوة، فيوظفان في تاريخ الفجوة معلومة لم تكن موجودة بعد. وفي الاختبار الرجعي هذا انحياز استباقي. استخدم ffill() لكل ما تراه الاستراتيجية آنيًا، واحتفظ بالاستيفاء لتنظيف بيانات تاريخية تُحلَّل مجتمعةً.
  • df.isna().sum() تعدّ الفجوات لكل عمود؛ انظر إلى البيانات قبل أن تقرر كيف تعالجها.
  • ffill(limit=n) ترحّل آخر قيمة معروفة (الخيار الصحيح للأسعار)؛ وdropna(subset=...) تزيل الصفوف الناقصة.
  • interpolate(limit_area="inside") تسدّ الفجوات الداخلية فقط؛ ولا تملأ بـ 0 أو بالمستقبل بحكم العادة.

التالي: اكتشاف القيم الشاذة، أي إيجاد القيم الموجودة التي لا يمكن أن تكون صحيحة.

المختبر: ما الذي يُقيَّم

  • عُدّ الفجوات في كل عمود باستخدام count_missing25 نقطة
  • رحّل آخر سعر إلى الأمام باستخدام forward_fill25 نقطة
  • احتفظ بالصفوف الموثوقة فقط باستخدام complete_rows25 نقطة
  • سُدّ الفجوات داخل البيانات باستخدام fill_gaps25 نقطة
المستكشف · lab-48-1
▾ lab-48-1
…
bash · داخل المتصفح
learner@quantcraft:~/lab-48-1$
لم يتم تحميل Python بعدPythonLn 1, Col 1Spaces: 4UTF-8

هل تريد إعادة ضبط هذا الموضوع؟

سيعود كل ما في lab-48-1 إلى الملفات الابتدائية وستُمسح الطرفية. ستفقد حلّك الحالي ولا يمكن التراجع عن ذلك.

سيُعاد ضبطه
  • main.py ← الشيفرة الابتدائية
  • سجل الطرفية ومخرجات الاختبارات
  • التغييرات غير المُرسلة
سيُحتفظ به
  • أفضل درجة في المختبر
  • نقاط XP والتتابع
  • تقدّم المحاضرة والملاحظات

سجّل الدخول لتشغيل الكود الخاص بك.

قراءة كل المحاضرات مجانية. أنشئ حسابًا أو سجّل الدخول لتشغيل الكود وتنفيذ الاختبارات وتسليم هذا المختبر.

  • بيئة تطوير داخل المتصفح مع طرفية bash — لا حاجة لتثبيت أي شيء
  • تصحيح فوري ونقاط خبرة ومكانك في المسار
إنشاء حسابتسجيل الدخول
أو
المتابعة عبر GitHub