⚠ ينطوي التداول على مخاطر كبيرة بالخسارة. كل ما في هذا الموقع لأغراض تعليمية فقط وليس نصيحة مالية.
الدرس 3 من 13 · مجاني

أساسيات pandas: السلاسل (Series) وإطارات البيانات (DataFrames) وفهرس التواريخ DatetimeIndex والتحديد والتصفية وإعادة تشكيل الشموع اليومية إلى أسبوعية

افهم Series وDataFrames، وفهرِس بيانات الأسعار بالتاريخ، وحدّد الصفوف باستخدام loc وiloc، وصفِّها بأقنعة منطقية، واجمع الشموع اليومية في شموع أسبوعية.

المؤلف: Moustafa Hijaziتمت مراجعة المحتوى: 2026-10-305 دقائق قراءةدورة للتعلّم الذاتي

ما الذي ستتعلمه

  • ما المقصود بـ Series وDataFrame، ولماذا يُعدّ DatetimeIndex العمود الفقري لتحليل الأسعار.
  • الفرق بين loc القائم على التسميات وiloc القائم على المواضع، وكيف تصفّي الأقنعة المنطقية الصفوف.
  • كيف تبني شموعًا أسبوعية أو شهرية من الشموع اليومية باستخدام resample مع طريقة التجميع الصحيحة لكل عمود.
  • أي الإعدادات الافتراضية في pandas تغيّرت في الإصدار 3.0، وكيف تكتب كودًا يتصرّف بالطريقة نفسها على 2.2 و3.x.

الشرح

السلسلة (Series) مصفوفة أحادية البعد ذات تسميات: عمود من أسعار الإغلاق يرتبط بكل قيمة فيه تاريخ. أما إطار البيانات (DataFrame) فهو جدول من السلاسل التي تتشارك فهرسًا واحدًا: الافتتاح والأعلى والأدنى والإغلاق والحجم جنبًا إلى جنب. يحمل الفهرس تسميات الصفوف؛ وفي بيانات الأسعار ينبغي أن يكون DatetimeIndex، وهو فهرس متخصص من الطوابع الزمنية يتيح التقطيع بالتاريخ وإعادة التشكيل والتعامل مع المناطق الزمنية. العُرف المتّبع: import pandas as pd.

أنشئ إطارًا من قاموس للأعمدة وفهرس للتواريخ:

idx = pd.bdate_range("2025-03-03", periods=10)

df = pd.DataFrame({"open": [...], "high": [...], "low": [...], "close": [...], "volume": [...]}, index=idx)

تُنتج bdate_range أيام العمل فقط ولا تعرف شيئًا عن عطلات البورصة؛ فالبيانات الحقيقية تأتي من الملفات (الدرس 4). افحص الإطار باستخدام df.head() وdf.info() (الأنواع والقيم المفقودة) وdf.describe(). يجب أن يُظهر df.index.dtype القيمة datetime64؛ فإذا أظهر object فهذا يعني أن التواريخ لا تزال نصًا.

التحديد. يعيد df["close"] سلسلة Series؛ ويعيد df[["open", "close"]] (قائمة) إطار DataFrame. يحدّد df.loc[row_labels, columns] حسب التسمية: يعطي df.loc["2025-03-05":"2025-03-07", "close"] أسعار الإغلاق لتلك التواريخ الثلاثة، ومع loc يُضمَّن طرفا الشريحة كلاهما، خلافًا لقوائم بايثون. أما df.iloc[0:3] فيحدّد حسب الموضع الرقمي (الصفوف الثلاثة الأولى، مع استبعاد النهاية)، وdf.iloc[-1] هو آخر شمعة.

التصفية. تُنتج المقارنة على سلسلة Series سلسلةً من القيم المنطقية تُسمّى قناعًا: up = df["close"] > df["open"]. وتمرير القناع يحدّد الصفوف المطابقة: df[up]. اجمع الأقنعة باستخدام & (و) و| (أو) و~ (ليس)، مع وضع كل شرط بين قوسين خاصين به: df[(df["close"] > df["open"]) & (df["volume"] > 1200)]. يعدّ up.sum() قيم True، وup.mean() هو نسبة الأيام الصاعدة.

إضافة الأعمدة تتم بالإسناد: df["range"] = df["high"] - df["low"]. العمليات متّجهة، أي تُطبَّق على أعمدة كاملة دفعة واحدة، ولهذا السبب يتسم pandas بالسرعة. ينقل shift(1) القيم صفًا واحدًا إلى الأسفل (إغلاق الأمس في صف اليوم)، ويعطي pct_change() التغيرات النسبية المئوية؛ وكلاهما يترك NaN (ليست رقمًا) في الصف الأول.

إعادة التشكيل. تجمّع resample الصفوف في فترات زمنية ثابتة. ويحتاج كل عمود إلى قاعدته الخاصة: الافتتاح الأسبوعي هو أول افتتاح يومي، والأعلى هو القيمة القصوى، والأدنى هو القيمة الدنيا، والإغلاق هو الأخير، والحجم هو المجموع:

rules = {"open": "first", "high": "max", "low": "min", "close": "last", "volume": "sum"}

weekly = df.resample("W-FRI").agg(rules)

الرمز "W-FRI" يسمّي كل أسبوع بيوم الجمعة فيه. وتستخدم الشموع الشهرية "ME" (نهاية الشهر). تكتب الدروس التعليمية القديمة "M"؛ وقد أوقف pandas 2.2 هذا الاسم المستعار لصالح "ME" (وكذلك "QE" و"YE")، والكود المكتوب بالأسماء المستعارة الجديدة يعمل على 2.2 و3.x كليهما.

تغييرات pandas 3.0 الجديرة بالمعرفة. أصبح النسخ عند الكتابة (Copy-on-Write) هو الوضع الوحيد: فالإطار المصفّى نسخة مستقلة، ولذلك لا يعدّل df[mask]["close"] = 0 الإطار df أبدًا؛ اكتب بدلًا من ذلك df.loc[mask, "close"] = 0. وصار نوع أعمدة النصوص str بدلًا من object.

مثال محلول

مثال افتراضي: عشر شموع يومية من الاثنين 3 مارس إلى الجمعة 14 مارس 2025، والأسعار باليورو، دون عطلات.

التاريخ الافتتاح الأعلى الأدنى الإغلاق الحجم
03 مارس 100 102 99 101 1,000
04 مارس 101 104 100 103 1,200
05 مارس 103 104 101 102 900
06 مارس 102 105 101 104 1,100
07 مارس 104 106 103 105 1,500
10 مارس 105 106 103 104 1,300
11 مارس 104 107 103 106 1,000
12 مارس 106 108 105 107 1,400
13 مارس 107 109 106 108 1,200
14 مارس 108 110 106 107 1,600

تعطي إعادة التشكيل صفّين. الأسبوع المنتهي في 7 مارس: الافتتاح = أول افتتاح = 100؛ الأعلى = max(102, 104, 104, 105, 106) = 106؛ الأدنى = min(99, 100, 101, 101, 103) = 99؛ الإغلاق = آخر إغلاق = 105؛ الحجم = 1,000 + 1,200 + 900 + 1,100 + 1,500 = 5,700. الأسبوع المنتهي في 14 مارس: الافتتاح 105، والأعلى 110، والأدنى 103، والإغلاق 107، والحجم = 1,300 + 1,000 + 1,400 + 1,200 + 1,600 = 6,500.

التصفية: يعيد (df["close"] > df["open"]).sum() القيمة 7، لأن أيام 5 و10 و14 مارس وحدها أغلقت دون سعر افتتاحها. ويعيد df.loc["2025-03-05":"2025-03-07", "close"] القيم 102 و104 و105.

خطأ شائع

الخلط بين loc وiloc، ونسيان أن loc يشمل النهايةيعيد df.iloc[0:5] خمسة صفوف (المواضع من 0 إلى 4)، لكن df.loc["2025-03-03":"2025-03-07"] يعيد كل الصفوف حتى 7 مارس ضمنًا. استخدم iloc لـ «أول N صف» أو «آخر شمعة»، واستخدم loc مع تواريخ صريحة للفترات.

نشاط تطبيقي

باستخدام جدول الشموع العشر أعلاه والعمل على الورق: (أ) اكتب تعبير pandas الذي يحدّد الشموع من 10 إلى 12 مارس ضمنًا؛ (ب) اذكر ما يعيده df.iloc[-3:]["close"].tolist()؛ (ج) احسب الشمعة الشهرية الوحيدة التي سيُنتجها df.resample("ME").agg(rules)؛ (د) اشرح ما الخطأ الذي يحدث إذا كتب أحدهم df.resample("ME").last() لجميع الأعمدة.

عرض الحل

(أ) df.loc["2025-03-10":"2025-03-12"]، ثلاثة صفوف مع تضمين الطرفين.

(ب) آخر ثلاثة أسعار إغلاق: [107, 108, 107].

(ج) صف واحد مسمّى بتاريخ 31 مارس 2025 (نهاية الشهر): الافتتاح 100 (الأول)، والأعلى 110 (الأقصى)، والأدنى 99 (الأدنى)، والإغلاق 107 (الأخير)، والحجم 12,200 (5,700 + 6,500).

(د) يأخذ .last() القيمة الأخيرة لكل عمود: فيصبح الأدنى الشهري 106 بدلًا من 99، والافتتاح 108 بدلًا من 100، والحجم 1,600 بدلًا من 12,200. مرّر دائمًا القواعد الخاصة بكل عمود.

القيود: لا يتضمن المثال عطلات أو أيامًا مفقودة؛ ومع البيانات الحقيقية، فإن الأسبوع الذي يتضمن عطلة يجمّع ببساطة أربع شموع، وتظهر تسمية الشهر «31 مارس» حتى لو كان آخر يوم تداول هو 28 مارس.

أهم النقاط

  • تعيش بيانات الأسعار في إطار DataFrame ذي فهرس DatetimeIndex؛ تحقّق من df.index.dtype قبل أي شيء آخر.
  • يحدّد loc حسب التسمية ويشمل نهاية الشريحة؛ ويحدّد iloc حسب الموضع ويستبعدها.
  • تحلّ الأقنعة المنطقية المجمّعة باستخدام & و| و~ محلّ الحلقات في التصفية، ويعدّ .sum() على القناع الحالات المطابقة.
  • أعِد تشكيل بيانات OHLCV باستخدام first/max/min/last/sum، واستخدم الاسمين المستعارين "W-FRI" و"ME"، وتذكّر آلية النسخ عند الكتابة في pandas 3.0 عند الإسناد.

الخطوة التالية

يقدّم الدرس 4 بيانات حقيقية: قراءة ملفات CSV وواجهات API المجانية، وفهم الأسعار المعدّلة مقابل غير المعدّلة، والتعامل مع القيم المفقودة والمناطق الزمنية.

تقييم ذاتي

أجب عن الأسئلة، ثم تحقّق من إجاباتك. يمكنك إعادة المحاولة بقدر ما تشاء.

1. أي قاموس تجميع يحوّل الشموع اليومية OHLCV إلى شموع أسبوعية بشكل صحيح؟

2. يحتوي إطار DataFrame على 250 صفًا يوميًا. كم صفًا يعيده كل من df.iloc[0:10] وdf.loc['2025-01-02':'2025-01-15']، إذا كان النطاق الثاني يحتوي على 10 أيام تداول بالضبط بما في ذلك تاريخَي الطرفين؟

3. في pandas 3.0 نفّذتَ df[df['volume'] > 1000]['close'] = 0 فوجدت أن df لم يتغيّر. لماذا؟

تقييم ذاتي تلقائي لمراجعتك الشخصية. تُفحَص إجاباتك في متصفحك ولا نطّلع عليها ولا نقيّمها. هذا ليس امتحانًا ولا مؤهّلًا.

تقدّمك

«مكتمل» يعني فقط أنك علّمت الدرس كمنتهٍ. وهو ليس اختبارًا لفهمك. يُحفظ التقدّم والملاحظات فقط في هذا المتصفح على هذا الجهاز — وليس في حساب.