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.
- Waktu API ≠ waktu chain. Settlement lag, RPC lag, WebSocket lag - semuanya menimbulkan celah yang harus ditangani secara eksplisit oleh kode bot.
- Retry membutuhkan idempotence. Retry tanpa client-order-id berisiko menjadi duplicate-order. Selalu.
- Baca setiap properti market secara eksplisit. Flag NegRisk, tick size, expiration. Jangan pernah men-default; selalu baca dari source of truth.
- 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.





