Polymarket Bot ट्यूटोरियल · अध्याय 32 of 32

असल Polymarket bot गलतियाँ और postmortems: phantom fills, sticky-fail dedup, lol-ctg-ccg whipsaw, NegRisk flag bug, premature go-live - साथ में वे commits और dates जिन्होंने हर समस्या को ठीक किया।

यह अध्याय क्या कवर करता है

यह हमारे अपने production diary का हिस्सा है - उन bugs का रिकॉर्ड जिनकी वजह से असली पैसा गया। खास details से ज्यादा pattern मायने रखता है - bots में bug की वही classes बार-बार आती हैं, और उनका इलाज आमतौर पर कोई बेहतर strategy नहीं, बल्कि कोई missing watchdog होता है। इस chapter का मकसद आपकी tuition बचाना है।

  • Phantom fills (commits e68a087, 8bb7761)
  • NegRisk flag bug (commit 06deaef)
  • Sticky-fail dedup (commit 4c0bef1)
  • Whipsaw incident: lol-ctg-ccg
  • Premature go-live: 2025 wipe
  • Sleep-through-bug: kill switch worked
  • Lessons that generalize

Phantom fills (commits e68a087, 8bb7761)

हमारे trader पर पहला बड़ा phantom-fill incident, May 2025 में हुआ। Bot ने 22 FOK buys लगाए, और सभी CLOB पर match हो गए। Bot ने तुरंत 22 GTC sells post करने की कोशिश की। उनमें से 8 “balance: 0 / sum of active orders: 0 / order amount: 10000000.” के साथ reject हो गए।

Root cause: settlement lag (chapter 12). CLOB ने 100ms में match किया, bot ने sell 200ms में post कर दी, लेकिन Polygon ERC-1155 transfer में ~2 seconds लगे। CLOB ने sell reject कर दी क्योंकि chain पर अभी भी zero balance दिख रहा था।

Fix: किसी भी successful buy और उसी token पर किसी भी GTC follow-up के बीच 5-second blocking wait डालें। Commits e68a087 और 8bb7761। तब से कोई phantom-fill incident नहीं हुआ।

Lesson: API time और chain time अलग timelines हैं। जो code इन्हें synchronous मानता है, वह इसी exact failure mode से टकराएगा।

NegRisk flag bug (commit 06deaef)

8 candidates वाले एक NegRisk multi-outcome event में momentary arb 1.8c का था (sum of YES asks = 0.982)। हमारे arber ने सभी 8 FOK buys fire कर दीं। उनमें से 6 fill हुईं; 2 गलत exchange contract में settle हो गईं।

Root cause: bot createAndPostOrder को negRisk: true flags object में set किए बिना call कर रहा था। Markets में से 2 की historical creation date अलग थी और उन्हें flag चाहिए था; 6 को इसकी जरूरत नहीं थी क्योंकि उनका underlying contract by default पहले से NegRisk route हो रहा था।

Fix: हर market के लिए Gamma से market.negRisk पढ़ें, और हर order call में pass करें। Commit 06deaef। हमने flag set करके arb फिर चलाया; बाकी 2 सही तरीके से settle हुए।

Lesson: किसी market property को कभी default मत मानो। हर बार source of truth से उसे explicitly पढ़ो।

Sticky-fail dedup (commit 4c0bef1)

Bot ने 12 seconds में failed buy को 5 बार retry किया। पहली कोशिश actually सफल हो गई थी (network timeout की वजह से bot response नहीं देख पाया); अगले 4 retries ने 4 additional positions बना दीं। Total: जब हमें 1 चाहिए था, उसी market पर 5 positions।

Root cause: कोई idempotent client-order-id नहीं था। Bot की retry logic थी: “अगर fail हुआ, तो नए salt के साथ फिर try करो।” CLOB के पास retries को duplicates की तरह पहचानने का कोई तरीका नहीं था।

Fix: पहली कोशिश से पहले intended order के लिए एक deterministic UUID generate करें। सभी retries वही client-order-id use करती हैं, जिससे CLOB dedup कर सकता है। Commit 4c0bef1।

Lesson: idempotence के बिना retries duplicates बन जाते हैं। हर order के लिए एक stable client-side identifier होना चाहिए।

Whipsaw incident: lol-ctg-ccg

एक esports match (CTG vs CCG) में imbalance positive flip होते ही bot ने 0.45 पर buy enter किया। 30 seconds के भीतर imbalance negative flip हो गया और हमारे GTC sell at 0.50 को किसी और के order ने hit कर दिया। PnL: +5c × 10 shares = +$0.50.

10 minutes बाद, उसी market का imbalance फिर से positive flip हुआ। Bot ने 0.42 पर फिर entry ली। इस बार imbalance कभी recover नहीं हुआ; mid 0.18 तक drift कर गया और position resolution तक 0 पर चली गई।

Root cause: strategy imbalance को directional signal मान रही थी, लेकिन यह track नहीं कर रही थी कि imbalance bounce हो रहा था - दोनों signals noise थे, information नहीं। Bot ने 20 minutes के भीतर उसी market पर दो failed signals के बीच whipsaw खाया।

Fix: per market cooldown - fill के बाद उसी market पर 30 minutes तक कोई नई entry नहीं। अलग-अलग markets में multiple entries allowed रहीं, लेकिन same market में back-to-back नहीं।

Lesson: जो signal bounce करता है, वह signal नहीं है। कार्रवाई से पहले persistence filter करें।

Premature go-live: 2025 wipe

एक नई market-making strategy ने 12 paper trades pass कीं। Builder ने 30 का इंतज़ार नहीं किया, “looking good” मान लिया, और $500 capital के साथ live deploy कर दिया। 18 hours के भीतर wallet $200 पर आ गया।

Root cause: 12 trades इतना sample नहीं है कि 60% WR और 35% WR में फर्क किया जा सके। असल में strategy 35% WR थी; 12-trade paper window बस एक misleading streak था।

30-trade gate एक वजह से मौजूद है। 12-trade sample की variance उसे “strategy काम नहीं करती” से अलग पहचानने नहीं देती।

Lesson: discipline, conviction से बेहतर है। 30-trade gate negotiable नहीं है।

Sleep-through-bug: kill switch worked

Bot के time-of-day filter में off-by-one bug था - उसे 02:00 UTC पर pause करना था, लेकिन वह 03:00 UTC पर pause कर रहा था। बिना pause वाले 02:00-03:00 hour के दौरान Polygon RPC हमारी requests को बहुत rate-limit कर रहा था; bot का read path stale data लौटा रहा था।

Bot stale prices पर trading करता रहा। उस hour का PnL: 22 trades में -$3.20। Daily-loss kill switch -5% पर trigger हुआ, bot halted हुआ, और 03:08 UTC पर Telegram alert भेजा गया। Builder 09:00 पर halted bot के साथ उठा; total damage kill threshold तक सीमित रहा।

Lesson: bug real था, लेकिन kill switch ने काम किया। -$3.20, बजाय -$50.00 के। Risk controls bugs को रोकते नहीं; वे उन bugs की cost cap करते हैं जिन्हें आप आते हुए नहीं देख पाए।

जो lessons सामान्य रूप से लागू होते हैं

सभी postmortems में चार patterns बार-बार दिखते हैं।

  1. API time ≠ chain time. Settlement lag, RPC lag, WebSocket lag - ये सभी ऐसे gaps लाते हैं जिन्हें bot code को explicitly handle करना चाहिए।
  2. Retries को idempotence चाहिए. Client-order-id के बिना retry करना duplicate-order risk है। हमेशा।
  3. हर market property को explicitly पढ़ो. NegRisk flag, tick size, expiration. कभी default मत करो; हमेशा source of truth से पढ़ो।
  4. Kill switch floor है, feature नहीं. Risk controls bugs पर losses cap करते हैं। Strategies bugs को नहीं रोकतीं; वे assume करती हैं कि bot सही काम कर रहा है। Bot हमेशा सही काम नहीं करेगा।

इस series के हर chapter में इनमें से कोई न कोई pattern कहीं न कहीं embedded है। ये production bot के load-bearing principles हैं। इन्हें छोड़ोगे, तो ये अपने postmortems में फिर मिलेंगे।

अक्सर पूछे जाने वाले प्रश्न

Polymarket bot की सबसे महंगी mistake क्या है?
Paper-trading के 30-trade gate तक पहुँचने से पहले live हो जाना। हमने यह किया है। गलती सिर्फ पैसा खोना नहीं है - बल्कि controlled environment में strategy से सीखने का मौका खो देना भी है। जो bots बहुत जल्दी live हो जाते हैं, वे या तो nuked होकर abandon कर दिए जाते हैं, या re-paper-trading से पहले महीनों recovery में बर्बाद कर देते हैं।
Phantom fill bug क्या है?
जब bot को लगता है कि order fill हो गया, लेकिन exchange ने उसे अभी तक filled नहीं माना होता। Symptoms: position आपके bot state में दिखती है लेकिन on-chain नहीं, जिससे retry पर double-orders बन जाते हैं। हमारे trader में इसे तीन commits (e68a087, 8bb7761, 06deaef) के जरिए ठीक किया गया: buys के लिए FOK use करो, status को matched होने तक poll करो, और कभी status=delayed को filled मत मानो।
lol-ctg-ccg whipsaw incident क्या था?
एक thin order book वाले esports market में हमारा trader 0.14 पर -$2.55 stop-loss fire कर बैठा, फिर 2 minutes के भीतर price को 0.325 तक recover होते देखता रहा। हमने stop-loss को -4 percentage points पर configure किया था, जो thin esports books के लिए बहुत tight है। Fix: low-liquidity markets के लिए SL को -8pp तक widen किया, और tighter SL सिर्फ thick books (NBA, high-liquidity soccer) के लिए रखा। देखें memory/trader-sl-wider.md।
NegRisk flag bug कैसे manifest हुआ?
Bot ने multi-outcome markets पर neg_risk=true set किए बिना orders place कीं। Orders confusing error messages के साथ reject हुईं, जिससे retry में कई seconds की देरी हुई, और fill miss हो गए। Commit 06deaef में fix: हमेशा market metadata के अनुसार neg_risk set करें, कभी assume न करें।
Sleep-through-bug incident क्या था?
Wallet 4am पर stuck order के साथ wedge हो गया था। Owner ने bot को halt करने का निर्देश दिया; data/halt_autobuy file को touch किया। Bot ने अगले trade attempt से पहले file detect कर ली और order place करने से इनकार कर दिया। Owner को खराब state की बजाय clean state मिली। halt-sentinel pattern validate हुआ; अब हम इसे हर bot में default ship करते हैं।
इन postmortems से सबसे ज़्यादा generalizable lesson क्या है?
Happy path पर कभी भरोसा मत करो। हमने जो भी bug ship किया, वह इस assumption से आया कि request सफल हो गई, fill असली थी, या price move नहीं करेगी। Defensive code लिखो: assume करो orders fail होंगे, reconciliations diverge होंगी, और कोई market कुछ अजीब करने वाला है। Paranoia tax छोटा है; उसे छोड़ने की कीमत बाद में लिखा गया आपका postmortem है।