HomeAboutResearchProductsDocs

Building a Polymarket Bot, Part 2

Polymarket
Trading-Engine
Ethereum

Dec 23, 2025

Building a Polymarket Bot, Part 2: Selection is Performance Engineering

πŸ“’ Docs Β· ☎️ Telegram Β· 𝕏 @ZEITFinance Β· 𝕏 @autonomous_af

← Previous: Part 1, Microstructure Before Math

ZEIT FINANCE Β· Building a Polymarket Bot

Part 2 β€” Selection is Performance Engineering

From Raw Data to High-Speed Execution


The Rookie Mistake

If you're building a bot, the rookie move is to just plug into the WebSocket, subscribe to * (everything), and tell yourself:

"I'll just filter out the noise in my loop."

Congratulations, you just built a slow bot.

A serious trading engine implementation doesn't try to trade "Polymarket" as a whole. It trades a specific, ruthless subset of markets that fit its hardware limits.


The Events You Monitor Define Your Physics

Your Latency: Every useless packet you ingest is a tax on your reaction time. Eating too much data makes you slow.

Your Uptime: Trying to drink from the firehose is the fastest way to OOM your server.

Your Edge: Don't run races you can't win. Focus on marketsβ€”the tracks where your code actually has the advantage.

In high-frequency environments, Market Selection is a hard dependency for performance engineering.


1. The Architecture: The Scanner vs. The Executor

Scanner vs Executor Architecture

The Bottleneck

Most builders mistakenly put Discovery (finding valid markets) and Execution (reacting to price) in the same event loop.

The Golden Rule

You cannot afford to parse "Will it rain?" metadata while you are trying to arb the "US Election" market.

To stay fast, you must decouple your architecture into two distinct processes:

Component Role Speed Priority
Discovery Loop (Scanner) Index all data, build relations, query targets Thorough > Fast
Execution Loop (Executor) Parse ticks, calculate edge, send orders Fast > Everything

2. The Deep Dive: Why You Need a Custom Indexer

Most developers assume the Scanner just calls GET /markets?active=true and passes the result to the bot.

This is insufficient.

A robust Scanner is actually a Market Indexer. It should ingest everythingβ€”active, closed, and resolvedβ€”and restructure it into a relational database (Postgres/SQLite/etc.).

The "Unlimited Flexibility" Strategy

❌ API Filtering

Great for fetching raw data, but terrible for complex filtering. Cannot answer compound questions.

βœ“ Local SQL Index

Replace complex client-side loops with a single, millisecond-fast SQL query.

Example: Find Tradeable Political Markets

Instead of fighting API filters, you run one query against your local index:

SELECT e.id FROM events e
JOIN markets m ON e.id = m.event_id
WHERE e.category = 'Politics'
  AND e.end_date < NOW() + INTERVAL '14 days'
GROUP BY e.id
HAVING COUNT(m.id) <= 5           -- Complexity Gate
   AND MIN(m.liquidity) > 10000;  -- Weakest Link Gate

This gives you a precise list of targets instantly. You waste zero CPU cycles on noise.


3. The Logic Pipeline: A Funnel of Gates

Once you have the data indexed, how do you decide what to pass to the Executor?

Stop viewing market selection as a binary "Good/Bad" switch.

View it as a Funnel of Strict Gates.

╔═══════════════════════════════════════════════════════════════════╗
β•‘                     ALL AVAILABLE MARKETS                          β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•
                              ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚   GATE 1: COHERENCE (Structure)β”‚
              β”‚   Is the Event fully defined? β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  GATE 2: LIQUIDITY (Weakest   β”‚
              β”‚  Link Rule)                   β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  GATE 3: HORIZON (Goldilocks  β”‚
              β”‚  Zone)                        β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
              β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
              β”‚  GATE 4: COMPUTE (Hardware    β”‚
              β”‚  Cap)                         β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                              ↓
╔═══════════════════════════════════════════════════════════════════╗
β•‘                     HIGH-QUALITY TARGETS                           β•‘
β•‘              (Ready for the Executor)                              β•‘
β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•

Your goal is to aggressively discard noise to protect your Executor's latency.


Gate 1: Coherence (Structure)

Before looking at price, check if the market is physically tradable.

The Check: Is the Event fully defined? Are all N sibling markets indexed and active?

The Logic: If an Event has broken metadata or a "disabled" outcome, you cannot safely calculate probability.

Action: β›” Discard immediately.


Gate 2: Liquidity (The Weakest Link Rule)

This is the most critical gate for NegRisk (multi-outcome) strategies.

Because you must buy all outcomes to build a hedged package, your ability to trade is bottlenecked by the worst order book in the set.

The Trap: The Liquidity Vacuum

Scenario: You see a 5-candidate Event. The top 2 candidates trade $100k volume. The bottom 3 are "dust" with $5 depth.

The Failure Mode: If you try to buy the package, you will clear the top candidates easily, but smash through the dust books on the bottom candidates. You incur massive slippage on the cheap legs, destroying your edge.

The Check: Does the weakest Market in the Event meet your minimum depth threshold?

Action: If Min(Liquidity_Leg_1...N) < Threshold β†’ β›” The entire Event is dead.


Gate 3: The Goldilocks Zone (Horizon)

Markets behave differently based on expiry. Capital has an opportunity cost.

The Check: Is Expiry_Date inside your strategy's Goldilocks zone?

The Logic:

| Horizon | Characteristics | Risk Profile | |---------|-----------------|--------------| | Too Soon (< 24h) | Extreme gamma. Prices jump violently. | Short capital lockup, but high execution risk. | | Sweet Spot (24h–90d) | Stable pricing, reasonable lockup. | Balanced risk/reward. | | Too Late (> 90d) | Dead capital. Money locked for months. | Low yield, poor capital efficiency. |

Action: Filter for the duration that matches your capital efficiency targets.


Gate 4: The Hardware Cap (Compute)

The final gate is physical, not financial.

The Check: Is Count(Selected_Markets) < Max_Capacity?

The Logic: If your Executor hits CPU limits at 500 active subscriptions, but your filters return 800 candidates, you are in danger. A lagging bot loses money.

Action: Rank the survivors by Volume/Spread and strictly cap the list size to your hardware limit.

⚑ It is better to trade 50 markets fast than 500 markets slow.


Summary: Selection is the First Line of Defense

Your bot's performance is defined by what you choose to ignore.

Key Takeaways

βœ… Architecture: Split your bot. The Scanner indexes and filters; the Executor trades. Never put them in the same event loop.

βœ… Own the Data: Scrape the raw endpoints. Build a local SQL index to unlock "Unlimited Flexibility" for complex strategy queries.

βœ… The Funnel: Apply strict Gates (Coherence β†’ Liquidity β†’ Horizon β†’ Cap) to ensure your Executor only wastes cycles on high-quality targets.

βœ… Weakest Link Logic: Always filter NegRisk events by their thinnest leg, not their total volume.


What's Next

Now that we have a clean, fast stream of tradable Markets, we need to understand the data itself.

Part 3 will cover The Local Mirror (WebSockets & State): Why asking for the price is too slow, and how to maintain a millisecond-perfect copy of the order book in RAM.


Keep Building

Follow on X: @ZEITFinance
Follow on X: @autonomous_af
Join Telegram: t.me/zeitfi
Read the Docs: zeit-1.gitbook.io/zeit


Continue the Series

← Prev (Part 1)
Microstructure Before Math
Next (Part 3)
The Local Mirror (WebSockets & State)
β†’

This article is Part 2 of the ZEIT Finance series on building Polymarket trading bots. ZEIT Finance turns prediction markets into perpetual assets.

HomeAboutResearchProducts

Β© 2025 Autonomous Finance. All rights reserved.