Polymarket Bot Tutorial · 32 bölümün 32.si

Gerçek Polymarket bot hataları ve postmortemler: phantom fills, sticky-fail dedup, lol-ctg-ccg whipsaw, NegRisk flag bug, premature go-live - her birini düzelten commit'ler ve tarihlerle birlikte.

Bu bölüm neleri kapsıyor

Gerçek para kaybettiren hatalara dair kendi production günlüğümüz. Önemli olan ayrıntılar değil, örüntü - aynı bug sınıfları botlarda tekrar tekrar ortaya çıkar ve çözüm genellikle daha iyi bir strategy değil, eksik bir watchdog olur. Bu bölüm sizi bu ders ücretinden kurtarmak için yazıldı.

  • 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
  • Genelleştirilebilen dersler

Phantom fills (commits e68a087, 8bb7761)

Trader'ımızda ilk büyük phantom-fill olayı, Mayıs 2025. Bot 22 FOK buy verdi, hepsi CLOB'da match oldu. Bot hemen 22 GTC sell post etmeye çalıştı. Bunların 8'i "balance: 0 / sum of active orders: 0 / order amount: 10000000." hatasıyla reddedildi.

Kök neden: settlement lag (12. bölüm). CLOB 100ms içinde match etti, bot sell'i 200ms içinde gönderdi, ancak Polygon ERC-1155 transferi yaklaşık 2 saniye sürdü. Chain hâlâ sıfır balance gösterdiği için CLOB sell'i reddetti.

Fix: Aynı token üzerinde başarılı bir buy ile bunu takip eden herhangi bir GTC arasında 5 saniyelik bloklayıcı bekleme ekleyin. Commit'ler e68a087 ve 8bb7761. O zamandan beri sıfır phantom-fill olayı yaşandı.

Ders: API zamanı ile chain zamanı farklı zaman çizgileridir. Bunların senkron olduğunu varsayan code tam da bu hata moduna çarpar.

NegRisk flag bug (commit 06deaef)

8 adaylı bir NegRisk multi-outcome event'inde toplam YES ask'lerin 0.982 olması nedeniyle 1.8c'lik anlık bir arb oluştu. Arber'ımız 8 FOK buy'ın hepsini gönderdi. Bunların 6'sı fill oldu; 2'si yanlış exchange contract'ına settle etti.

Kök neden: bot, flags nesnesinde negRisk: true ayarlamadan createAndPostOrder çağırıyordu. Market'lerin ikisinin tarihsel creation date'i farklıydı ve flag gerektiriyordu; diğer altısının ise buna ihtiyacı yoktu çünkü underlying contract'ları varsayılan olarak zaten NegRisk üzerinden route ediliyordu.

Fix: Her market için Gamma'dan market.negRisk değerini okuyun ve her order çağrısına aktarın. Commit 06deaef. Arb'ı flag açık halde yeniden çalıştırdık; kalan 2 order doğru şekilde settle oldu.

Ders: Bir market özelliğini asla default etmeyin. Her seferinde source of truth'tan açıkça okuyun.

Sticky-fail dedup (commit 4c0bef1)

Bot, 12 saniye içinde başarısız olan bir buy'ı 5 kez yeniden denedi. İlk deneme aslında başarılıydı (network timeout nedeniyle bot response'u göremedi); sonraki 4 retry 4 ek pozisyon oluşturdu. Sonuç: 1 istediğimiz halde aynı markette 5 pozisyon.

Kök neden: idempotent bir client-order-id yoktu. Bot'un retry mantığı şuydu: "eğer başarısız olduysa, yeni bir salt ile tekrar dene." CLOB'un bu retry'ları duplicate olarak tanımasının hiçbir yolu yoktu.

Fix: İlk denemeden önce amaçlanan her order için deterministik bir UUID üretin. Tüm retry'lar aynı client-order-id'yi kullanır, böylece CLOB dedup yapabilir. Commit 4c0bef1.

Ders: Idempotence olmadan yapılan retry'lar duplicate üretir. Her order'ın sabit bir client-side identifier'ı olmalı.

Whipsaw incident: lol-ctg-ccg

Bir esports match (CTG vs CCG) sırasında imbalance pozitife döndüğünde bot 0.45'ten buy'a girdi. 30 saniye içinde imbalance negatife döndü ve 0.50'deki GTC sell'imiz başka birinin order'ı tarafından vuruldu. PnL: +5c × 10 share = +$0.50.

10 dakika sonra aynı market'in imbalance'ı tekrar pozitife döndü. Bot yeniden 0.42'den girdi. Bu kez imbalance hiç toparlanmadı; mid 0.18'e kaydı ve pozisyon çözülmeye kadar 0'a kadar gitti.

Kök neden: strategy, imbalance'ı yönsel bir signal olarak ele alıyordu ama imbalance'ın sekip durduğunu izlemiyordu - her iki signal da bilgi değil, gürültüydü. Bot, aynı markette 20 dakika içinde iki başarısız signal arasında whipsaw oldu.

Fix: market başına cooldown - bir fill'den sonra aynı markette 30 dakika boyunca yeni entry yok. Farklı marketlerde birden fazla entry'ye izin verildi, ancak aynı markette arka arkaya değil.

Ders: Sekip duran bir signal, signal değildir. Harekete geçmeden önce persistence için filtreleyin.

Premature go-live: 2025 wipe

Yeni bir market-making strategy 12 paper trade'i geçti. Builder 30'u beklemedi, "iyi görünüyor" dedi, $500 sermaye ile live deploy etti. 18 saat içinde wallet $200'e düştü.

Kök neden: 12 trade, %60 WR ile %35 WR'yi ayırt etmek için yeterli örneklem değil. Strategy gerçekte %35 WR'ydi; 12 trade'lik paper window sadece temsil edici olmayan bir seri yakalamıştı.

30-trade gate'in bir sebebi var. 12 trade'lik bir sample'daki variance, bunu "strategy çalışmıyor" durumundan ayırt edilemez hale getirir.

Ders: Disiplin, conviction'dan daha önemlidir. 30-trade gate pazarlık konusu değildir.

Sleep-through-bug: kill switch çalıştı

Bot'un time-of-day filter'ında bir off-by-one vardı - 02:00 UTC'de duraklaması gerekirken aslında 03:00 UTC'de duraklıyordu. Duraklatılmayan 02:00-03:00 saatinde Polygon RPC isteklerimizi ciddi biçimde rate-limit ediyordu; bot'un read path'i eski veri dönüyordu.

Bot, eski fiyatlarla işlem yapmaya devam etti. O saatteki PnL: 22 trade boyunca -$3.20. Daily-loss kill switch -%5'te devreye girdi, botu durdurdu ve 03:08 UTC'de bir Telegram alert'i gönderdi. Builder 09:00'da durdurulmuş bir bot'a uyandı; toplam hasar kill threshold ile sınırlandı.

Ders: Bug gerçekti ama kill switch çalıştı. -$3.20, -$50.00 yerine. Risk controls bug'ları önlemez; görmediğiniz bug'ların maliyetini sınırlar.

Genelleştirilebilen dersler

Tüm postmortem'ler boyunca dört örüntü tekrar ediyor.

  1. API time ≠ chain time. Settlement lag, RPC lag, WebSocket lag - hepsi bot code'unun açıkça ele alması gereken boşluklar yaratır.
  2. Retry'lar idempotence gerektirir. Client-order-id olmadan yapılan her retry, duplicate-order riskidir. Her zaman.
  3. Her market özelliğini açıkça okuyun. NegRisk flag, tick size, expiration. Asla default etmeyin; her zaman source of truth'tan okuyun.
  4. Kill switch taban çizgisidir, özellik değil. Risk controls, bug'ların neden olduğu kayıpları sınırlar. Strategy'ler bug'ları önlemez; bot'un doğru çalıştığını varsayarlar. Bot her zaman doğru çalışmayacaktır.

Bu serideki her bölümün bir yerinde bu örüntülerden biri yer alır. Bunlar production bot'un taşıyıcı prensipleridir. Bunları atlayın, kendi postmortem'lerinizde yeniden karşınıza çıkarlar.

Sıkça sorulan sorular

En pahalı Polymarket bot hatası nedir?
Paper-trading, 30-trade gate'ine ulaşmadan live'a çıkmak. Bunu biz yaptık. Hata sadece para kaybetmek değildir - aynı zamanda strategy'den kontrollü bir ortamda öğrenme şansını kaybetmektir. Çok erken live'a çıkan bot'lar ya nuke edilip terk edilir ya da yeniden paper-trading yapmadan önce aylarca toparlanmaya çalışarak boşa zaman harcar.
Phantom fill bug nedir?
Bot bir order'ın fill olduğunu düşünürken exchange'in onu henüz fill olmamış olarak kaydetmesidir. Belirtiler: pozisyon bot state'inde görünür ama on-chain'de görünmez, bu da retry sırasında double-order'a yol açar. Trader'ımızda üç commit (e68a087, 8bb7761, 06deaef) ile düzeltildi: buy'larda FOK kullanın, durum match olana kadar poll edin, status=delayed'i asla filled sanmayın.
lol-ctg-ccg whipsaw incident nedir?
Sığ bir order book'a sahip bir esports market'inde trader'ımızın 0.14'te -$2.55 stop-loss tetiklemesi ve ardından 2 dakika içinde fiyatın 0.325'e toparlanmasını izlemesi. Thin esports book'lar için çok dar olan -4 yüzde puanlık stop-loss yapılandırmıştık. Fix: düşük liquidity market'ler için SL'yi -8pp'ye genişlettik, daha sıkı SL'yi yalnızca kalın book'lar için bıraktık (NBA, yüksek liquidity'li soccer). Bkz. memory/trader-sl-wider.md.
NegRisk flag bug nasıl ortaya çıktı?
Bot, multi-outcome market'lerde neg_risk=true ayarlamadan order verdi. Order'lar kafa karıştırıcı hata mesajlarıyla reddedildi; bu da retry öncesinde birkaç saniyelik gecikmelere ve kaçırılan fill'lere yol açtı. Commit 06deaef'teki fix: her zaman market metadata'sına göre neg_risk ayarlayın, asla varsaymayın.
Sleep-through-bug olayı neydi?
Wallet sabah 4'te takılı bir order ile sıkıştı. Sahip bot'a durmasını söyledi; data/halt_autobuy dosyasına dokundu. Bot, bir sonraki trade denemesinden önce dosyayı tespit etti ve order vermeyi reddetti. Sahip, daha kötü bir durum yerine temiz bir state'e uyandı. Halt-sentinel pattern doğrulandı; artık her bot'ta varsayılan olarak gönderiyoruz.
Bu postmortem'lerden çıkarılabilecek tek en genel ders nedir?
Mutlu path'e asla güvenmeyin. Gönderdiğimiz her bug, bir request'in başarılı olduğunu, bir fill'in gerçek olduğunu ya da bir fiyatın hareket etmeyeceğini varsaymaktan kaynaklandı. Defensive code yazın: order'ların başarısız olacağını, reconciliation'ların ayrışacağını, bir market'in garip bir şey yapmak üzere olduğunu varsayın. Paranoia maliyeti küçüktür; bundan kaçınmanın bedeli ise sonradan yazacağınız postmortem'dir.