Skip to main content

Example Trading Bot

A complete, working Python bot implementing a simple mean-reversion strategy:
  1. Fetch hot markets
  2. Find markets where Yes price < 0.40 (undervalued)
  3. Buy small positions
  4. Monitor and sell when price rises above 0.60

Full Source Code


Running the Bot


Key Patterns

Always pass quantity and price as strings to prevent floating-point issues:
Each order includes a STABLE idempotency key. The key MUST stay the same across retries of the same logical order — the server’s idempotency layer (/v1/ordersIdempotency-Key header) only deduplicates when the key is identical to a previous attempt:
Do NOT use uuid.uuid4() or a raw timestamp directly in your idempotency key. Both change on every retry, so the server treats each retry as a fresh order and you double-fill on the first transient error. Use uuid.uuid5() over a deterministic seed (order tuple + second bucket) so retries within the same second collapse to the same key, but two genuinely independent orders a second later don’t collide. For high-frequency strategies that place multiple orders per second, pass an explicit idempotency_key (e.g. f"{strategy}-{client_seq}") so each logical order has its own key.
The /v1/orders endpoint has a 5-second server-side deadline. If the order persists but the response times out, you get:
Do NOT retry — your order DID land. Read X-Polysim-Order-Id (header) or body.order_id (JSON), then poll GET /v1/orders/{id} until status is terminal (FILLED / CANCELLED / REJECTED / EXPIRED; PENDING means still resting).
response.raise_for_status() crashes on 503 BEFORE you can read the body. If you call it before inspecting the status code, you’ll lose the order_id. Always check response.status_code == 503 FIRST and recover from the header / body before raise_for_status().
The example place_order() above implements this recovery pattern.
On HTTP 429, read the Retry-After header and wait exactly that long:

Next Steps