מדריך בוט Polymarket · פרק 17 מתוך 32
השתמשו בחוסר האיזון של ספר הפקודות של Polymarket כאות מחיר לטווח קצר: יחס נפח bid-ask, חישוב microprice, חצי־חיים של האות, ומתי בוטים שמבוססים על חוסר איזון מנצחים ביצוע אקראי.
מה הפרק הזה מכסה
חוסר איזון בספר הפקודות הוא היחס בין עומק צד הקנייה לעומק צד המכירה ב-limit order book. ב-Polymarket יש לו יתרון חיזוי אמיתי אך קצר־מועד - בדרך כלל 5-30 שניות לפני שה-mid זז. הפרק הזה עוסק בתבנית החישוב ובתנאים שבהם האות מטעה.
- מהו חוסר איזון בספר הפקודות
- חישוב microprice
- חוסר איזון כאות כיווני
- חצי־חיים של האות ב-Polymarket
- מתי אותות חוסר איזון מטעות
- קוד: חישוב חוסר איזון בכל WS tick
מהו חוסר איזון בספר הפקודות
חוסר איזון בספר הפקודות הוא היחס בין סך העומק בצד הקנייה לבין סך העומק בצד המכירה ב-limit order book. כשהוא מחושב ברמות top-N (בדרך כלל N=5), הוא לוכד את הלחץ המצטבר של הסוחרים שה-mid-price עדיין לא שיקף.
נוסחה: imbalance = (Σ bid[i].price × bid[i].size for i in [0..N]) − (Σ ask[i].price × ask[i].size) / (Σ both). הטווח הוא מ-1- עד +1; ערך חיובי פירושו יותר לחץ קנייה, וערך שלילי פירושו יותר לחץ מכירה.
האות הזה אכן קיים אמפירית ב-Polymarket, אבל הוא רועש. לווייתן יחיד יכול לייצר חוסר איזון מדומה למשך 30-60 שניות לפני ש-arb יאזן אותו החוצה. זה שימושי כאחד מכמה features, אך מסוכן כאות יחיד.
חישוב microprice
microprice הוא שכלול של ה-mid הפשוט: ממוצע משוקלל של best bid ו-best ask, לפי הגדלים היחסיים שלהם.
microprice = (best_bid × ask_size + best_ask × bid_size) / (bid_size + ask_size)
כאשר התור בצד ה-bid גדול בהרבה מהצד של ה-ask, ה-microprice יושב קרוב יותר ל-ask. ההיגיון: יותר קונים שממתינים פירושו שהעסקה הבאה תיטה יותר להרים את ה-ask, ולכן השווי ההוגן קרוב יותר ל-ask.
microprice הוא אינדיקטור מוביל של 5-30 שניות לפני שה-mid בפועל זז. בוטים בייצור משתמשים בו כ-price reference להחלטות take-profit במקום ה-mid הנאיבי.
חוסר איזון כאות כיווני
מתצפית בייצור: כאשר חוסר האיזון מתהפך מ--0.3 ל-+0.5 בתוך 10 שניות בלי אירוע חדשותי נלווה, ה-mid עולה ב-1-2 סנט בתוך 30-60 השניות הבאות בכ-65% מהמקרים.
זהו יתרון אמיתי, אבל הוא מתאדה ב-position sizes קטנים אחרי עמלות. כדי לממש אותו, הבוט חייב להיות גדול מספיק כדי לתפוס את המהלך פחות העמלות, אבל קטן מספיק כדי לא להזיז את הספר בעצמו. ספרי ה-Polymarket בדרך כלל דקים מספיק כך שכל דבר מעל 50 shares מזיז את השוק.
שלבו חוסר איזון עם features נוספים: מהירות עסקאות (יותר עסקאות = אות אמיתי), best-bid שבאמת עולה (ולא רק עומק שזז), ושוק שאינו במצב מונע-חדשות.
חצי־חיים של האות ב-Polymarket
אות חוסר האיזון דועך. נתוני ייצור מה-trader שלנו: חוסר איזון > 0.6 → תזוזת mid צפויה של 1.2c בתוך 60 שניות, חצי־חיים של ~30 שניות. אחרי 90 שניות הערך החיזויי ירד לאפס.
המשמעות לעיצוב הבוט: להגיב מהר או לדלג. בוט שלוקח 15 שניות כדי להחליט צורך כבר חצי מהיתרון לפני שליחת ההזמנה. תקציב ה-latency לאסטרטגיות חוסר איזון צריך להיות מתחת ל-5 שניות מהאות ועד שליחת FOK.
אסטרטגיות שמחזיקות פוזיציות יותר מאשר חצי־החיים (1-2 דקות) בעצם מהמרות על האות הבא, לא על הנוכחי. חשוב להיות מפורשים לגבי זה; אל תחזיקו בטעות פוזיציות שמונעות מחוסר איזון עד להכרעה.
מתי אותות חוסר איזון מטעות
האות מטעה כאשר מתקיים אחד משלושה תנאים.
- תנועה מונעת-חדשות: חוסר האיזון הוא תוצאה של חדשות שלא ראיתם. מסחר נגדו מפסיד; מסחר איתו הוא news arbitrage, אסטרטגיה אחרת.
- Spoofing של whale: הזמנה גדולה שמונחת ומבוטלת במהירות יוצרת חוסר איזון מדומה למשך הזמן הזה. סננו על ידי בדיקה שחוסר האיזון נמשך 10+ שניות לפני טריגר.
- איזון מחדש בסוף התקופה: market makers מושכים quotes מסיבות של inventory ולא מסיבות של מידע. חוסר האיזון מתהפך דקות לאחר מכן כשה-MM מצטט מחדש.
הפילטר המשולב הוא: חוסר איזון > threshold AND מהירות עסקאות > baseline AND אין אירוע חדשותי ב-5 הדקות האחרונות. לכל פילטר בנפרד יש יותר מדי false positives.
קוד: חישוב חוסר איזון בכל WS tick
הפניה: מתחברים לעדכוני WebSocket של הספר, ומחשבים חוסר איזון מחדש בכל tick.
def on_book_message(msg):
bids = msg.get("bids", [])[:5]
asks = msg.get("asks", [])[:5]
bid_usd = sum(float(b["price"]) * float(b["size"]) for b in bids)
ask_usd = sum(float(a["price"]) * float(a["size"]) for a in asks)
total = bid_usd + ask_usd
if total < 100: return # illiquid
imb = (bid_usd - ask_usd) / total
state[msg["asset_id"]] = {
"imb": imb,
"best_bid": float(bids[0]["price"]) if bids else 0,
"best_ask": float(asks[0]["price"]) if asks else 1,
"ts": time.time()
}
# decision logic with cooldown + filters
if imb > 0.6 and time.time() - last_fired.get(msg["asset_id"], 0) > 60:
check_filters_and_maybe_fire(msg["asset_id"])
ה-state הוא לפי token. ה-cooldown מונע הפעלות יתר על אותו אות. ה-filters (בדיקת חדשות, מהירות עסקאות) שומרים את העסקה האמיתית.





