Polymarket Bot Tutorial · Chapter 22 of 32
بوتات NegRisk متعددة النتائج على Polymarket: آليات sum-to-1، ومراجحة الأطراف عندما لا يتجمع YES legs إلى 1، والتحوّط عبر الأطراف، ومشكلات التنفيذ الخاصة بأسواق متعددة النتائج.
ما الذي يغطيه هذا الفصل
أسواق NegRisk متعددة النتائج هي نتائج متبادلة الإقصاء - أي إن نتيجة واحدة فقط تُحسم YES. هذا الفصل هو طبقة الاستراتيجية فوق آليات التنفيذ في الفصل 11: كيف تتحوط عبر الأطراف، ومتى تكون مراجحة sum-to-1 حقيقية، وما الأخطاء التي يقع فيها معظم بوتات NegRisk عند أول نشر.
- مراجعة NegRisk مقابل binary
- ثابتة sum-to-1 والمراجحة
- بناء التحوط طرفًا بطرف
- التنفيذ: علم neg_risk في الأوامر
- الأخطاء الشائعة في بوتات NegRisk
- كود: أخذ snapshot لكل الأطراف واكتشاف مجموع أقل من 1.00
مراجعة NegRisk مقابل binary
binary: سوق واحد yes/no، ورمزان، والمجموع يساوي 1.0. NegRisk: عدد N من النتائج المتبادلة الإقصاء، ورموز N، وجميع YES legs يجب أن تجمع تقريبًا إلى 1.0 عبر الحدث.
من ناحية التنفيذ، يتطلب NegRisk تعيين negRisk: true على كل أمر (الفصل 11) ويُوجَّه عبر عقد exchange منفصل. من ناحية الاستراتيجية، يوفّر NegRisk فرصتين فريدتين لا توفرهما binary: مراجحة عبر الأطراف عندما يبتعد المجموع عن 1.0، وبناء التحوط عبر شراء عدة YES legs.
التكاليف الخاصة بـ NegRisk: كلما زاد عدد الأطراف زادت ضريبة السبريد (كل طرف تتداوله يكلف تقريبًا 0.5-1c سبريد)، وزادت انحرافات sum-to-1 في الأحداث منخفضة السيولة (المراجحة تكون متاحة أكثر غالبًا لكنها أصغر).
ثابتة sum-to-1 والمراجحة
فرضية المراجحة: إذا كانت تكلفة شراء جميع YES legs الـ N أقل من 1.00 دولار، فأنت قد قفلت ربحًا مضمونًا عند التسوية (لا بد أن يدفع طرف واحد 1.00 دولار؛ والبقية تهبط إلى 0).
في الممارسة، تكون فجوة المراجحة عادة 0-3c، وتلتهمها السبريد + الرسوم على كل طرف، وتختفي خلال دقائق من الافتتاح. والسعة محدودة بأضيق طرف من حيث السيولة.
تخضع المراجحة أيضًا لأنماط فشل محددة في التسوية: نتيجة "none of the above" التي تُحسم صراحةً YES عندما لا ينطبق أي مرشح مذكور. إذا كان الحدث يتضمن هذا الطرف ولم تشترِه، فإن "التحوط الكامل" لديك يفوّت العائد الفعلي.
بناء التحوط طرفًا بطرف
إذا كنت تحمل مركزًا على طرف واحد من أطراف NegRisk، يمكنك التحوط بشراء YES على الأطراف المنافسة بنسب متناسبة. إذا كنت تحمل Trump-YES عند 0.50 وتريد التحوط ضد خسارة Trump، فستشتري محفظة من الأطراف الأخرى المذكورة.
وزن التحوط لكل طرف ≈ الاحتمال الضمني الحالي لذلك الطرف مشروطًا بخسارة Trump. تقريبًا: weight_i = price_i / (1 - trump_price).
التحوط غير كامل لأن الأسعار المستخدمة هي لقطة زمنية، والاحتمالات الشرطية تتغير مع وصول الأخبار. أعد موازنة التحوط أسبوعيًا أو عند الأخبار الكبرى. لا تبالغ في التعقيد؛ هدف التحوط هو تقليل التباين، لا إلغاؤه تمامًا.
التنفيذ: علم neg_risk في الأوامر
أكثر خطأ شائع خاص بـ NegRisk: نسيان negRisk: true في حمولة إرسال الأمر. يقبل API الأمر، لكنه يُسوّى بشكل خاطئ لأنه يمر عبر exchange القياسي لـ CTF بدلًا من exchange الخاص بـ NegRisk.
// CORRECT for NegRisk markets:
await client.createAndPostOrder(
{ tokenID, price, size, side: Side.BUY },
{ tickSize: '0.01', negRisk: true }, // <-- REQUIRED
OrderType.FOK
);
مصدر الحقيقة: market.negRisk من Gamma API. اقرأه ومرره كما هو. لا تقم أبدًا بتثبيت العلم بشكل جامد بناءً على التخمين.
الأخطاء الشائعة في بوتات NegRisk
من سجلات تصحيح الإنتاج عبر عدة بوتات.
- غياب علم negRisk: يُقبل الأمر، وتفشل التسوية. العلاج: فرض العلم في كل wrapper.
- التحوط دون طرف "Other": في الأحداث التي تتضمن نتيجة "None of the above"، تكون محفظة التحوط التي تستثنيها غير مكتملة. العلاج: افحص دائمًا وجود Other leg عند بناء التحوط.
- تحجيم خاطئ لمراجحة sum-to-1: المراجع يلتقط فجوة 1c لكنه يتداول 5 أسهم لكل طرف؛ الربح الإجمالي 5 سنتات قبل السبريد، وصافي سلبي. العلاج: احجم المراجحة لاستخراج دولارات فعلية، لا لمطاردة النسب المئوية اللامعة.
- تسعير قديم للأطراف: البوت يجلب أسعار 3 أطراف ويستغرق 200ms إجمالًا، ثم يتغير سعر الطرف الأخير أثناء الجلب. العلاج: اجلب كل الأطراف بالتوازي + اعتبر snapshot ملاحظة واحدة.
كود: أخذ snapshot لكل الأطراف واكتشاف مجموع أقل من 1.00
مرجع: خذ snapshot لكل YES legs في حدث NegRisk بالتوازي، واكتشف المراجحة.
import asyncio, aiohttp
async def fetch_leg_ask(session, token_id):
async with session.get(f"https://clob.polymarket.com/book?token_id={token_id}") as r:
d = await r.json()
asks = d.get("asks", [])
return float(asks[0]["price"]) if asks else None
async def check_arb(event_slug):
event = await fetch_event(event_slug)
if not event["markets"][0]["negRisk"]: return None
legs = []
for m in event["markets"]:
toks = json.loads(m["clobTokenIds"])
yes_token = toks[0]
legs.append(yes_token)
async with aiohttp.ClientSession() as s:
asks = await asyncio.gather(*[fetch_leg_ask(s, t) for t in legs])
if any(a is None for a in asks): return None
total = sum(asks)
if total < 0.97:
return {"edge": 1 - total, "legs": list(zip(legs, asks))}
return None
التنفيذ الذري لجميع الأطراف هو المشكلة الأصعب ويتطلب FOK لكل طرف + rollback عند التنفيذ الجزئي (نمط مشابه لكود stat-arb في الفصل 16).





