Polymarket Bot Tutorial · Bab 32 dari 32

Kesalahan nyata bot Polymarket dan postmortem-nya: phantom fills, sticky-fail dedup, whipsaw lol-ctg-ccg, bug flag NegRisk, go-live terlalu cepat - beserta commit dan tanggal yang memperbaiki masing-masing.

Apa yang dibahas di bab ini

Catatan produksi kami sendiri tentang bug yang merugikan uang sungguhan. Polanya lebih penting daripada detailnya - kelas bug yang sama berulang di berbagai bot, dan obatnya biasanya watchdog yang hilang, bukan strategi yang lebih baik. Bab ini dimaksudkan untuk menyelamatkan biaya belajar Anda.

  • Phantom fills (commit e68a087, 8bb7761)
  • Bug flag NegRisk (commit 06deaef)
  • Sticky-fail dedup (commit 4c0bef1)
  • Insiden whipsaw: lol-ctg-ccg
  • Go-live terlalu cepat: wipe 2025
  • Sleep-through-bug: kill switch bekerja
  • Pelajaran yang dapat digeneralisasi

Phantom fills (commit e68a087, 8bb7761)

Insiden phantom-fill besar pertama pada trader kami, Mei 2025. Bot menempatkan 22 order beli FOK, semuanya match di CLOB. Bot segera mencoba memasang 22 order jual GTC. 8 di antaranya ditolak dengan "balance: 0 / sum of active orders: 0 / order amount: 10000000."

Akar masalah: settlement lag (bab 12). CLOB match dalam 100ms, bot memasang jual dalam 200ms, tetapi transfer Polygon ERC-1155 memakan waktu sekitar 2 detik. CLOB menolak jual karena chain masih menunjukkan saldo nol.

Perbaikan: sisipkan jeda blocking 5 detik antara pembelian sukses apa pun dan tindak lanjut GTC apa pun pada token yang sama. Commit e68a087 dan 8bb7761. Tidak ada insiden phantom-fill sejak saat itu.

Pelajaran: waktu API dan waktu chain adalah timeline yang berbeda. Kode yang menganggap keduanya sinkron akan mengalami mode kegagalan persis ini.

Bug flag NegRisk (commit 06deaef)

Sebuah event multi-outcome NegRisk dengan 8 kandidat sempat memiliki arb 1.8c (jumlah ask YES = 0.982). Arber kami mengeksekusi semua 8 order beli FOK. 6 fill; 2 terselesaikan ke exchange contract yang salah.

Akar masalah: bot memanggil createAndPostOrder tanpa mengatur negRisk: true di objek flags. Dua market memiliki tanggal pembuatan historis yang berbeda dan memerlukan flag tersebut; enam lainnya tidak membutuhkannya karena contract dasar mereka sudah routing melalui NegRisk secara default.

Perbaikan: baca market.negRisk dari Gamma untuk setiap market, lalu teruskan ke setiap pemanggilan order. Commit 06deaef. Kami menjalankan ulang arb dengan flag diaktifkan; 2 yang tersisa terselesaikan dengan benar.

Pelajaran: jangan pernah men-default properti market. Baca secara eksplisit dari source of truth setiap saat.

Sticky-fail dedup (commit 4c0bef1)

Bot mencoba ulang pembelian yang gagal 5 kali dalam 12 detik. Percobaan pertama sebenarnya sukses (network timeout membuat bot tidak melihat respons); 4 retry berikutnya membuat 4 posisi tambahan. Total: 5 posisi pada market yang sama padahal yang diinginkan hanya 1.

Akar masalah: tidak ada client-order-id yang idempotent. Logika retry bot adalah "kalau gagal, coba lagi dengan salt baru." CLOB tidak punya cara untuk mengenali retry sebagai duplikat.

Perbaikan: generate UUID deterministik per order yang dimaksud sebelum percobaan pertama. Semua retry menggunakan client-order-id yang sama, sehingga CLOB dapat melakukan dedup. Commit 4c0bef1.

Pelajaran: retry tanpa idempotence adalah duplikat. Setiap order memerlukan identifier stabil di sisi client.

Insiden whipsaw: lol-ctg-ccg

Sebuah pertandingan esports (CTG vs CCG) membuat bot masuk beli di 0.45 saat imbalance berbalik positif. Dalam 30 detik, imbalance berbalik negatif dan sell GTC kami di 0.50 terkena order orang lain. PnL: +5c × 10 saham = +$0.50.

10 menit kemudian, imbalance market yang sama berbalik positif lagi. Bot masuk lagi di 0.42. Kali ini imbalance tidak pernah pulih; mid turun ke 0.18 dan posisi terbawa sampai resolusi di 0.

Akar masalah: strategi memperlakukan imbalance sebagai sinyal arah tetapi tidak melacak bahwa imbalance sedang memantul - kedua sinyal itu adalah noise, bukan informasi. Bot terkena whipsaw oleh dua sinyal gagal pada market yang sama dalam 20 menit.

Perbaikan: cooldown per market - setelah fill, tidak ada entry baru pada market yang sama selama 30 menit. Memungkinkan beberapa entry di market yang berbeda, tetapi tidak back-to-back pada market yang sama.

Pelajaran: sinyal yang memantul bukanlah sinyal. Filter untuk persistensi sebelum bertindak.

Go-live terlalu cepat: wipe 2025

Sebuah strategi market-making baru lolos 12 paper trade. Builder tidak menunggu sampai 30, memutuskan "kelihatannya bagus," lalu deploy live dengan modal $500. Dalam 18 jam, wallet turun menjadi $200.

Akar masalah: 12 trade bukan sampel yang cukup untuk membedakan WR 60% dari WR 35%. Strategi tersebut sebenarnya WR 35%; jendela paper 12 trade kebetulan memiliki streak yang tidak representatif.

Gate 30 trade ada alasannya. Variansi pada sampel 12 trade membuatnya tak bisa dibedakan dari "strategi ini tidak bekerja."

Pelajaran: disiplin mengalahkan keyakinan. Gate 30 trade tidak bisa dinegosiasikan.

Sleep-through-bug: kill switch bekerja

Bot punya off-by-one pada filter waktu hari - seharusnya pause pada 02:00 UTC, ternyata baru pause pada 03:00 UTC. Selama jam 02:00-03:00 yang tidak di-pause, Polygon RPC sangat membatasi request kami; read path bot mengembalikan data yang stale.

Bot terus trading berdasarkan harga stale. PnL pada jam itu: -$3.20 dari 22 trade. Kill switch daily-loss terpicu pada -5%, menghentikan bot, dan mengirim alert Telegram pada 03:08 UTC. Builder bangun dengan bot yang sudah dihentikan pada 09:00, total kerusakan dibatasi oleh ambang kill.

Pelajaran: bug-nya nyata tetapi kill switch bekerja. -$3.20 alih-alih -$50.00. Kontrol risiko tidak mencegah bug; mereka membatasi biaya dari bug yang tidak Anda lihat datang.

Pelajaran yang dapat digeneralisasi

Di semua postmortem, empat pola berulang.

  1. Waktu API ≠ waktu chain. Settlement lag, RPC lag, WebSocket lag - semuanya menimbulkan celah yang harus ditangani secara eksplisit oleh kode bot.
  2. Retry membutuhkan idempotence. Retry tanpa client-order-id berisiko menjadi duplicate-order. Selalu.
  3. Baca setiap properti market secara eksplisit. Flag NegRisk, tick size, expiration. Jangan pernah men-default; selalu baca dari source of truth.
  4. Kill switch adalah lantai, bukan fitur. Kontrol risiko membatasi kerugian akibat bug. Strategi tidak mencegah bug; strategi mengasumsikan bot bekerja dengan benar. Bot tidak selalu bekerja dengan benar.

Setiap bab dalam seri ini memiliki salah satu pola ini di suatu tempat. Itulah prinsip-prinsip penopang produksi bot. Lewati mereka dan Anda akan menemukannya lagi dalam postmortem Anda sendiri.

Pertanyaan yang sering diajukan

Apa kesalahan Polymarket bot yang paling mahal?
Go-live sebelum paper trading mencapai gate 30 trade. Kami pernah melakukannya. Kesalahannya bukan hanya kehilangan uang - tetapi kehilangan kesempatan untuk belajar dari strategi di lingkungan yang terkontrol. Bot yang live terlalu cepat biasanya dihancurkan lalu ditinggalkan, atau menghabiskan berbulan-bulan untuk pulih sebelum kembali paper-trading.
Apa itu bug phantom fill?
Saat bot percaya sebuah order sudah fill tetapi exchange mencatatnya belum fill. Gejalanya: posisi muncul di state bot tetapi tidak di chain, sehingga saat retry terjadi duplicate-order. Diperbaiki di trader kami melalui tiga commit (e68a087, 8bb7761, 06deaef): gunakan FOK untuk buy, poll status sampai match, jangan pernah menganggap status=delayed sebagai fill.
Apa itu insiden whipsaw lol-ctg-ccg?
Sebuah market esports di order book tipis di mana trader kami mengeksekusi stop-loss -$2.55 di 0.14, lalu melihat harga pulih ke 0.325 dalam 2 menit. Kami mengonfigurasi stop-loss pada -4 percentage points, yang terlalu ketat untuk order book esports tipis. Perbaikan: perluas SL ke -8pp untuk market likuiditas rendah, dan pertahankan SL yang lebih ketat hanya untuk order book tebal (NBA, sepak bola likuiditas tinggi). Lihat memory/trader-sl-wider.md.
Bagaimana bug flag NegRisk termanifestasi?
Bot memasang order tanpa mengatur neg_risk=true pada market multi-outcome. Order ditolak dengan pesan error yang membingungkan, menyebabkan penundaan beberapa detik sebelum retry, yang berujung pada fill terlewat. Perbaikan di commit 06deaef: selalu set neg_risk berdasarkan metadata market, jangan pernah mengasumsikan.
Apa insiden sleep-through-bug?
Wallet tersangkut dengan order yang macet pada jam 4 pagi. Owner menginstruksikan bot untuk berhenti; menyentuh file data/halt_autobuy. Bot mendeteksi file tersebut sebelum percobaan trade berikutnya dan menolak memasang order. Owner bangun dengan state yang bersih, bukan yang lebih buruk. Pola halt-sentinel tervalidasi; sekarang kami mengirimkannya sebagai default di setiap bot.
Apa pelajaran tunggal yang paling dapat digeneralisasi dari postmortem ini?
Jangan pernah percaya jalur yang mulus. Setiap bug yang kami ship berasal dari asumsi bahwa request sukses, fill itu nyata, atau harga tidak akan bergerak. Kode secara defensif: anggap order bisa gagal, anggap rekonsiliasi bisa divergen, anggap satu market akan melakukan sesuatu yang aneh. Pajak paranoia kecil; biaya mengabaikannya adalah postmortem yang akan Anda tulis nanti.