πΊπΈ English
Dec 23, 2025
π Docs Β· βοΈ Telegram Β· π @ZEITFinance Β· π @autonomous_af
β Previous: Part 1, Microstructure Before Math
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.
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.
Most builders mistakenly put Discovery (finding valid markets) and Execution (reacting to price) in the same event loop.
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 |
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.).
Great for fetching raw data, but terrible for complex filtering. Cannot answer compound questions.
Replace complex client-side loops with a single, millisecond-fast SQL query.
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.
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.
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.
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.
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.
Markets behave differently based on expiry. Capital has an opportunity cost.
The Check: Is Expiry_Date inside your strategy's Goldilocks zone?
| 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.
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.
Your bot's performance is defined by what you choose to ignore.
β 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.
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.
Follow on X: @ZEITFinance
Follow on X: @autonomous_af
Join Telegram: t.me/zeitfi
Read the Docs: zeit-1.gitbook.io/zeit
This article is Part 2 of the ZEIT Finance series on building Polymarket trading bots. ZEIT Finance turns prediction markets into perpetual assets.