Polymarket Bot Tutorial · Chapter 7 of 32

شرح معمّق لواجهة Polymarket Gamma API: نهايتا /events و /markets، الترقيم الصفحي pagination، معرّفات الوسوم tag IDs (864 Tennis، 745 NBA، إلخ)، التصفية حسب حجم التداول خلال 24 ساعة، حدود المعدّل rate limits، وأمثلة كود Python وNode.

ما الذي يغطيه هذا الفصل

Gamma هي واجهة API الخاصة بكتالوج Polymarket - فهي تعرض كل event، وكل market، وكل tag، والصورة، والنتيجة المحسومة التي تُظهرها الواجهة الأمامية. واجهة CLOB API مخصّصة للتداول؛ أما Gamma فتصف ما يمكن تداوله. معظم أخطاء البوتات في طبقة الاكتشاف discovery تأتي من الخلط بينهما، أو من تجاهل عقد pagination. هذا الفصل هو المرجع الميداني للنهايات الرئيسية في Gamma مع السلوك الدقيق للمعاملات التي تعتمد عليها أدوات الجلب في الإنتاج لدينا.

  • Gamma مقابل CLOB: متى تستخدم كلًا منهما
  • بنية /events
  • بنية /markets
  • الوسوم tag IDs (قائمة موثقة)
  • التصفية: active، closed، وترتيب volume24hr
  • pagination والحدود
  • Rate limits وcaching
  • Code: جلب أعلى markets من حيث حجم تداول 24 ساعة

Gamma مقابل CLOB: متى تستخدم كلًا منهما

خدمتان مختلفتان لمهمتين مختلفتين.

Gamma (gamma-api.polymarket.com): الكتالوج. تعرض الأحداث، الأسواق، الوسوم، الأوصاف، الصور، النتائج المحسومة، حجم التداول خلال 24 ساعة، الحجم الإجمالي، وتواريخ الانتهاء. HTTP للقراءة فقط. لا تتطلب مصادقة في معظم عمليات القراءة. يتم تحديثها باستمرار ولكنها eventually consistent - قد يظهر market أغلق للتو على أنه closed: false لبضع ثوانٍ.

CLOB (clob.polymarket.com): التداول + order book. تعرض أفضل bid/ask الحالي، وعمق book حتى أعلى N، وآخر الصفقات. تتطلب مصادقة لنهايات الكتابة (وضع الأوامر، الإلغاء). تتوفر قنوات WebSocket في الوقت الحقيقي لتحديثات book.

قاعدة عملية: استخدم Gamma لمعرفة ما الذي ستتداول عليه؛ واستخدم CLOB للتداول نفسه. البوت الذي يقرأ الأسعار من Gamma يستخدم بيانات متأخرة - حقول الأسعار في Gamma تُحدَّث بوتيرة أقل من order book في CLOB. والبوت الذي يقرأ بيانات تعريف السوق من CLOB ينفذ طلبات أكثر من اللازم.

بنية /events

GET /events يعيد بيانات على مستوى event. الـ "event" هو صفحة Polymarket؛ وقد يحتوي event واحد على عدة markets (مثلًا event انتخابات الرئاسة 2024 يحتوي market لكل مرشح).

الحقول الأساسية:

  • slug: معرّف صالح للـ URL، ثابت طوال عمر event.
  • title، description: للعرض البشري.
  • endDate (ISO 8601): متى يُغلق event.
  • active، closed: قيم منطقية؛ ادمجها في الاستعلام مع ?active=true&closed=false للأحداث الحية.
  • volume، volume24hr: إجماليات بالدولار الأمريكي.
  • tags: مصفوفة من كائنات الوسوم (راجع قسم الوسوم أدناه).
  • markets: مصفوفة من كائنات market التابعة (راجع بنية /markets).

أكثر نمط شائع للاكتشاف: GET /events?active=true&closed=false&order=volume24hr&ascending=false&limit=100. يعيد أعلى 100 event حي من حيث الحجم.

بنية /markets

GET /markets يعيد بيانات على مستوى market. الـ market هو عقدة Yes/No أو متعددة النتائج؛ ويعيش داخل event.

الحقول الأساسية:

  • slug: معرّف صالح للـ URL.
  • question: العنوان المعروض في صفحة التداول (مثلًا "Will Trump be president on January 1, 2027?").
  • outcomes: سلسلة JSON لأسماء النتائج، مثل '["Yes","No"]'. تكون دائمًا عنصرين في الأسواق الثنائية؛ وأكثر من ذلك في NegRisk.
  • outcomePrices: سلسلة JSON للأسعار الحالية بوصفها أعدادًا عشرية، مثل '["0.62","0.38"]'. مجموع الجانبين يساوي تقريبًا 1.0 ناقص spread.
  • clobTokenIds: سلسلة JSON لمعرّفات ERC-1155 المرتبطة بالنتائج. هذه هي الرموز التي تشتريها/تبيعها فعليًا.
  • negRisk: قيمة منطقية؛ true للأسواق متعددة النتائج التي مجموعها يساوي 1. يهم هذا عند وضع الأوامر (الفصل 11).

الحقول outcomes / outcomePrices / clobTokenIds تأتي كسلاسل JSON، وليس كمصفوفات محللة - لذا يجب فك JSON قبل استخدامها.

الوسوم وtag IDs (قائمة موثقة)

الوسوم هي تسميات تصنيفية (Sports، Crypto، Tennis، NBA، إلخ). فيما يلي tag IDs الموثقة في الإنتاج لأكثر الفئات استخدامًا:

TagIDTagID
Sports1NBA745
Crypto21NFL450
Politics2Tennis864
Bitcoin100196Esports702
Ethereum100383Soccer1059
Election3EPL739
Middle East1432UCL2186

يمكنك التصفية حسب الوسم باستخدام ?tag_id=745 لوسم محدد، أو ?tag_slug=nba باستخدام الـ slug. التصفية بالـ slug أكثر وضوحًا في الكود لكنها أبطأ قليلًا؛ أما التصفية بالـ ID فهي الافتراضية في الإنتاج.

التصفية: active، closed، وترتيب volume24hr

أبعاد التصفية الأربعة التي ستستخدمها 95% من الوقت.

  • active=true|false: القيمة true تستبعد الأسواق التي أخفاها فريق Polymarket من الواجهة.
  • closed=true|false: القيمة false تستبعد الأسواق المحسومة. الجمع active=true&closed=false هو أكثر فلتر حي شيوعًا.
  • order=volume24hr، order=volume، order=endDate: مفتاح الترتيب. الأكثر فائدة هو volume24hr للعثور على الأسواق النشطة حاليًا.
  • ascending=true|false: القيمة الافتراضية true في معظم النهايات؛ وغالبًا ما تريد false عند الترتيب حسب الحجم.

تنبيه: التصفية باستخدام tag_id مع order=volume24hr وascending=false قد تعطي أحيانًا صفحة فارغة عندما يكون للوسم عدد قليل جدًا من الأسواق الحية. لذا يجب دائمًا over-fetch (اطلب أكثر مما تعرضه) ثم قم بالتصفية اللاحقة post-filter لمعالجة ذلك.

pagination والحدود

معامل limit يقبل من 1 إلى 500 لكل طلب. القيمة الافتراضية 100 إذا لم تُحدَّد. إذا تجاوزت 500 فإن الخادم يقيّدها بصمت - ستحصل على 500 لكن الاستجابة لا تشير إلى وجود المزيد.

pagination يعتمد على offset: ?limit=500&offset=500 للصفحة الثانية. لا يوجد pagination قائم على cursor، لذا قد تؤدي الإضافات المتزامنة إلى تغيّر حدود الصفحات بين الطلبات. بالنسبة لمعظم أغراض اكتشاف البوتات فهذا مقبول؛ أما في عمليات scraping للأرشيف، فرتّب حسب حقل ثابت (endDate أو createdAt) واكشف التداخل بواسطة slug.

النمط العملي لـ "كل الأسواق الحية": اجلب limit=500&order=volume24hr&ascending=false. هذا يغطي أعلى 500 سوقًا حسب الحجم، وهو عمليًا كل سوق لديه نشاط غير هامشي. تجاوز الصفحة الأولى نادرًا ما يكون مفيدًا - فالأسواق في ذيل توزيع الحجم ليست، بحكم التعريف، حيث يوجد الزخم.

Rate limits وcaching

Gamma خلف Cloudflare ولديها rate limits مرنة لكل IP. العتبات التجريبية المرصودة تحت حمل الإنتاج:

  • حتى نحو 30 طلب/ثانية من IP واحد بشكل مستمر: جيد.
  • دفعات من 100+ طلب/ثانية: قد تظهر أحيانًا 429s، وتنجح الإعادات retries.
  • نحو 500 طلب/ثانية بشكل مستمر: صفحة rate-limit أو حظر مؤقت (10-60 ثانية).

تتضمن رؤوس الاستجابة المنشورة قيم Cache-Control من 30 إلى 60 ثانية لمعظم النهايات. التزم بها - لا توجد فائدة من إعادة جلب نفس event عشر مرات في الدقيقة. نمط caching في الإنتاج: LRU داخل العملية + TTL مفهرسة على كامل الـ URL، مع TTL لمدة 30 ثانية. هذا يوفر عدد الطلبات ويقلل زمن الاستجابة.

للاستراتيجيات عالية التردد، انسخ بيانات Gamma إلى مخزن محلي يتم تحديثه بواسطة عملية fetcher واحدة؛ ثم دع عدة مستهلكين يقرؤون من ذلك المخزن. fetcher واحد × عدة مستهلكين > عدة fetchers × Gamma.

Code: جلب أعلى markets من حيث حجم تداول 24 ساعة

مرجع fetcher بثلاث لغات، يعيد أعلى 50 market حيًا حسب حجم التداول خلال 24 ساعة.

Python:

import requests
r = requests.get("https://gamma-api.polymarket.com/events",
                 params={"active":"true","closed":"false",
                         "order":"volume24hr","ascending":"false","limit":50},
                 timeout=10)
for ev in r.json()[:50]:
    print(ev["slug"], ev.get("volume24hr"))

Node:

const url = "https://gamma-api.polymarket.com/events?active=true&closed=false" +
            "&order=volume24hr&ascending=false&limit=50";
const events = await fetch(url).then(r => r.json());
for (const ev of events) console.log(ev.slug, ev.volume24hr);

Curl:

curl -s "https://gamma-api.polymarket.com/events?active=true&closed=false&order=volume24hr&ascending=false&limit=50" \
  | jq '.[].slug'

نهاية Polymarket gamma /events لا تدعم معامل بحث نصي حر - إضافة ?q=foo أو ?search=foo تعيد بصمت الترتيب الافتراضي. استخدم slug أو tag بدلًا من ذلك.

الأسئلة الشائعة

ما هي Polymarket Gamma API؟
Gamma هي واجهة API للبيانات الوصفية والاكتشاف في Polymarket. تقدّم قوائم الأحداث والأسواق والعناوين والأوصاف وتواريخ الانتهاء والوسوم والحجم الإجمالي. لكنها لا تقدّم بيانات order book في الوقت الحقيقي - فهذه موجودة على CLOB API. بالنسبة لمعظم حالات الاكتشاف والتحليلات، تبدأ بـ Gamma.
ما الفرق بين event وmarket في Polymarket؟
الـ event يجمع واحدًا أو أكثر من الأسواق التي تشترك في موضوع سؤال واحد. أما market فهو نتيجة Yes/No محددة مع order book خاص بها ومعرّفات token الخاصة بها. event "2026 NBA Champion" يحتوي 30 market (واحدًا لكل فريق). وفي أحداث Yes/No الثنائية، يحتوي event على market أساسي واحد.
كيف أجد tag IDs الخاصة بـ Polymarket؟
تُعرَض الوسوم عبر endpoint الخاص بـ gamma /tags. المعرّفات الموثقة التي نستخدمها في الإنتاج: 864 Tennis، 745 NBA. الـ slugs في الروابط (?tag_slug=tennis) والاستعلام النصي الحر (?q=tennis) غير موثوقين - استخدم numerical tag_id فقط. راجع /tags قبل الاعتماد على slug.
كيف أرتب أحداث Polymarket حسب حجم التداول خلال 24 ساعة؟
/events?order=volume24hr&ascending=false - وهذا هو ما يشغّل معظم widgets "trending markets". ادمجه مع active=true&closed=false لاستبعاد الأسواق المنتهية أو الموقوفة. القيمة الافتراضية لـ limit هي 25؛ والحد الأقصى 500 لكل طلب.
هل توجد حدود pagination على Gamma؟
نعم. نهايتا /events و /markets تقبلان limit (بحد أقصى 500 لكل طلب) وoffset للتنقل الصفحي. معظم المكتبات لا تقوم بـ pagination تلقائيًا - إذا كنت تحتاج الكون الكامل، فكرّر مع offset حتى تحصل على صفحة تحتوي على عدد نتائج أقل من `limit`.
هل تدعم Gamma WebSocket؟
لا. Gamma تعمل عبر REST فقط. للحصول على التحديثات في الوقت الحقيقي (تغييرات الأسعار، الأسواق الجديدة، order book) استخدم CLOB WebSocket - وهو مشروح في الفصل 8 من هذه السلسلة.