<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Bo$onaX</title>
    <description>The latest articles on DEV Community by Bo$onaX (@xniiinx).</description>
    <link>https://dev.to/xniiinx</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3794067%2F20c11b2d-9a8a-4ddc-962d-7dd011136ea9.png</url>
      <title>DEV Community: Bo$onaX</title>
      <link>https://dev.to/xniiinx</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/xniiinx"/>
    <language>en</language>
    <item>
      <title>Polymarket Arbitrage Bot: Production Architecture</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Thu, 27 Aug 2026 14:31:52 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-arbitrage-bot-production-architecture-2058</link>
      <guid>https://dev.to/xniiinx/polymarket-arbitrage-bot-production-architecture-2058</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Build a Polymarket arbitrage bot with real-time order books, fee-aware execution, risk controls, and production-ready Python architecture.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A useful &lt;strong&gt;Polymarket arbitrage bot&lt;/strong&gt; is not simply a script that checks whether two prices add up to less than $1.&lt;/p&gt;

&lt;p&gt;The difficult part is turning a theoretical pricing discrepancy into an executable trade after accounting for &lt;strong&gt;fees, spread, available liquidity, partial fills, stale quotes, execution failure, and inventory risk&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Polymarket's current production trading stack uses CLOB V2. The official Python client is &lt;code&gt;py-clob-client-v2&lt;/code&gt;, while real-time market data is available through the public WebSocket market channel. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;This article presents a compact architecture for building an arbitrage engine around those primitives.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bo$onaX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
Github: &lt;a href="https://github.com/n9xdev/poly-alpha-lab" rel="noopener noreferrer"&gt;https://github.com/n9xdev/poly-alpha-lab&lt;/a&gt;&lt;br&gt;
X: &lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;&lt;br&gt;
Telegram: &lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to structure an arbitrage engine&lt;/li&gt;
&lt;li&gt;How to consume Polymarket order-book updates&lt;/li&gt;
&lt;li&gt;How to calculate fee-aware opportunities&lt;/li&gt;
&lt;li&gt;How to separate detection from execution&lt;/li&gt;
&lt;li&gt;How to manage two-leg execution risk&lt;/li&gt;
&lt;li&gt;How to test and monitor the system&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  1. The Architecture
&lt;/h2&gt;

&lt;p&gt;A production bot should separate &lt;strong&gt;market data, strategy, risk, execution, and observability&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    WS[Polymarket WebSocket] --&amp;gt; BOOK[Order Book Cache]
    META[Market Metadata] --&amp;gt; BOOK
    BOOK --&amp;gt; DETECT[Arbitrage Detector]
    DETECT --&amp;gt; COST[Fee + Slippage Model]
    COST --&amp;gt; RISK[Risk Engine]
    RISK --&amp;gt; EXEC[Execution Engine]
    EXEC --&amp;gt; CLOB[Polymarket CLOB V2]
    CLOB --&amp;gt; FILLS[Fill Events]
    FILLS --&amp;gt; POS[Position Manager]
    POS --&amp;gt; MON[Metrics + Logs]
    EXEC --&amp;gt; MON&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The key design principle is simple: &lt;strong&gt;never let the strategy directly control the exchange client&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The strategy produces an opportunity. The risk layer decides whether it is allowed. The execution layer determines how it is actually traded.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Real-Time Market Data
&lt;/h2&gt;

&lt;p&gt;Polymarket provides a public WebSocket market channel for order-book snapshots and incremental updates. The documented channel supports book updates, price changes, last-trade events, tick-size changes, and other market lifecycle events. Clients should also send the documented heartbeat. ([Polymarket Documentation][2])&lt;/p&gt;

&lt;p&gt;For an arbitrage system, maintain an in-memory book:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;bid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;bid_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;ask_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;

&lt;span class="n"&gt;books&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not repeatedly poll REST endpoints for every strategy decision when streaming data is available. The detector should react to book events and operate against the latest validated local state.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Detecting an Arbitrage Opportunity
&lt;/h2&gt;

&lt;p&gt;For a binary market, a simple conceptual parity check is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cost = yes_ask + no_ask
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the combined executable cost is below the eventual combined payout, there may be an opportunity.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;yes_ask + no_ask &amp;lt; 1&lt;/code&gt; is &lt;strong&gt;not sufficient&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The actual decision should look more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;net_edge =
    guaranteed_or_expected_value
    - execution_cost
    - taker_fee
    - slippage
    - inventory_risk_buffer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polymarket currently applies taker fees only to fee-enabled markets, with fees calculated at match time. The market's fee configuration can be queried through the CLOB market information API. Makers are not charged the trading fee, and eligible maker activity can receive rebates. ([Polymarket Documentation][3])&lt;/p&gt;

&lt;p&gt;Therefore, hard-coding a universal fee percentage into your arbitrage bot is a mistake.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Strategy Layer
&lt;/h2&gt;

&lt;p&gt;Keep the strategy deliberately small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_opportunity&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;min_edge&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;combined&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;combined&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;yes_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;no_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;edge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In production, &lt;code&gt;min_edge&lt;/code&gt; should represent the &lt;strong&gt;minimum executable edge after all known costs&lt;/strong&gt;, not an arbitrary percentage.&lt;/p&gt;

&lt;p&gt;The detector should also verify:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sufficient size exists at both prices&lt;/li&gt;
&lt;li&gt;quotes are fresh&lt;/li&gt;
&lt;li&gt;both tokens belong to the intended market&lt;/li&gt;
&lt;li&gt;market is still tradable&lt;/li&gt;
&lt;li&gt;tick sizes are valid&lt;/li&gt;
&lt;li&gt;current fee configuration is known&lt;/li&gt;
&lt;li&gt;available capital supports both legs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Execution Is the Hard Part
&lt;/h2&gt;

&lt;p&gt;The biggest architectural mistake is treating arbitrage as a detection problem.&lt;/p&gt;

&lt;p&gt;It is primarily an &lt;strong&gt;execution problem&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Suppose the detector sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YES ask = 0.47
NO ask  = 0.51
Combined = 0.98
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That does not mean you can buy both at those prices.&lt;/p&gt;

&lt;p&gt;The YES order might fill while the NO ask disappears. You now have directional exposure.&lt;/p&gt;

&lt;p&gt;A safer execution engine therefore tracks every opportunity as a state machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DETECTED
   ↓
VALIDATED
   ↓
LEG_A_SUBMITTED
   ↓
LEG_A_FILLED
   ↓
LEG_B_SUBMITTED
   ↓
COMPLETE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Failure states should include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPIRED
PARTIAL
CANCELLED
UNWOUND
ERROR
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The execution layer should never assume that submission equals execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Python Project Structure
&lt;/h2&gt;

&lt;p&gt;A practical project can remain compact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;polymarket_arb/
├── config.py
├── market_data.py
├── orderbook.py
├── strategy.py
├── fees.py
├── risk.py
├── execution.py
├── positions.py
├── monitoring.py
└── main.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official documentation currently recommends the V2 Python client, &lt;code&gt;py-clob-client-v2&lt;/code&gt;, for CLOB integrations. Legacy V1 clients are no longer supported against production CLOB V2. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;Keep credentials outside source code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLY_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;API_SECRET&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLY_API_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;API_PASSPHRASE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLY_API_PASSPHRASE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Private keys should be handled separately and never logged.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Risk Engine
&lt;/h2&gt;

&lt;p&gt;Before submitting either leg, enforce hard limits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;available_capital&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_position&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;available_capital&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;max_position&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Production systems should additionally enforce:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;maximum market exposure&lt;/li&gt;
&lt;li&gt;maximum simultaneous opportunities&lt;/li&gt;
&lt;li&gt;maximum one-leg exposure&lt;/li&gt;
&lt;li&gt;stale-book timeout&lt;/li&gt;
&lt;li&gt;daily loss limit&lt;/li&gt;
&lt;li&gt;emergency shutdown&lt;/li&gt;
&lt;li&gt;duplicate-order protection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A particularly important control is a &lt;strong&gt;one-leg timeout&lt;/strong&gt;. If the hedge does not fill quickly enough, the bot must have a predefined response rather than waiting indefinitely.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Performance Considerations
&lt;/h2&gt;

&lt;p&gt;Latency matters, but optimizing Python syntax before optimizing architecture is usually backwards.&lt;/p&gt;

&lt;p&gt;Prioritize:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;WebSocket market data&lt;/li&gt;
&lt;li&gt;local order-book state&lt;/li&gt;
&lt;li&gt;event-driven strategy evaluation&lt;/li&gt;
&lt;li&gt;persistent connections&lt;/li&gt;
&lt;li&gt;asynchronous execution&lt;/li&gt;
&lt;li&gt;minimal network hops&lt;/li&gt;
&lt;li&gt;measured order submission latency&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Polymarket's documentation currently identifies &lt;code&gt;eu-west-2&lt;/code&gt; as the primary CLOB server region and documents direct co-location availability for eligible users. ([Polymarket Documentation][4])&lt;/p&gt;

&lt;p&gt;Measure your actual pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market event
→ detector
→ validation
→ signing
→ submission
→ acknowledgement
→ fill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not claim a latency target without measuring your own infrastructure.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Failure Modes
&lt;/h2&gt;

&lt;p&gt;Common failures include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stale books:&lt;/strong&gt; A cached opportunity is no longer executable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Partial fills:&lt;/strong&gt; One leg executes while the hedge disappears.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fee blindness:&lt;/strong&gt; Gross spread looks profitable while net execution is negative.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Liquidity blindness:&lt;/strong&gt; The best displayed price exists only for a tiny quantity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Duplicate execution:&lt;/strong&gt; Multiple event handlers trigger the same opportunity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Market lifecycle errors:&lt;/strong&gt; The market changes state while orders are being prepared.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Credential leakage:&lt;/strong&gt; API credentials or private keys enter logs, repositories, or telemetry.&lt;/p&gt;

&lt;p&gt;The bot should treat every external response as untrusted input and every order as an asynchronous state transition.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Testing Strategy
&lt;/h2&gt;

&lt;p&gt;Start with deterministic replay.&lt;/p&gt;

&lt;p&gt;Store historical order-book events and feed them into the same detector used in production.&lt;/p&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;normal book updates&lt;/li&gt;
&lt;li&gt;disappearing liquidity&lt;/li&gt;
&lt;li&gt;crossed quotes&lt;/li&gt;
&lt;li&gt;partial fills&lt;/li&gt;
&lt;li&gt;rejected orders&lt;/li&gt;
&lt;li&gt;WebSocket disconnects&lt;/li&gt;
&lt;li&gt;duplicate events&lt;/li&gt;
&lt;li&gt;stale timestamps&lt;/li&gt;
&lt;li&gt;fee changes&lt;/li&gt;
&lt;li&gt;market closure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then run the exact strategy in simulation before enabling live execution.&lt;/p&gt;

&lt;p&gt;The goal is not merely to prove that the detector finds arbitrage. It is to prove that the &lt;strong&gt;whole state machine behaves correctly when arbitrage disappears halfway through execution&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Monitoring
&lt;/h2&gt;

&lt;p&gt;Track at minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;opportunities_detected
opportunities_rejected
orders_submitted
orders_filled
partial_fills
unwinds
gross_edge
realized_pnl
fees_paid
slippage
data_age
order_latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structured logs should include a unique opportunity ID so that detection, orders, fills, and position changes can be reconstructed later.&lt;/p&gt;

&lt;p&gt;Polymarket also provides an authenticated user WebSocket channel for real-time order and trade events, making it useful for synchronizing execution state with actual account activity. ([Polymarket Documentation][5])&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Practical Example
&lt;/h2&gt;

&lt;p&gt;Consider a hypothetical opportunity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;YES ask:  $0.46
NO ask:   $0.51
Gross cost: $0.97
Gross edge: $0.03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A naive bot immediately buys both.&lt;/p&gt;

&lt;p&gt;A production bot asks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Is the book fresh?
Is enough size available?
Are fees enabled?
What is the effective fee?
What happens if only YES fills?
Can NO still be executed?
What is the maximum acceptable unwind loss?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only after those checks does the risk engine authorize execution.&lt;/p&gt;

&lt;p&gt;That difference is what separates an &lt;strong&gt;arbitrage detector&lt;/strong&gt; from an &lt;strong&gt;arbitrage trading system&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Advanced Improvements
&lt;/h2&gt;

&lt;p&gt;Once the core engine works, add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multi-market opportunity ranking&lt;/li&gt;
&lt;li&gt;fee-aware dynamic thresholds&lt;/li&gt;
&lt;li&gt;execution simulation&lt;/li&gt;
&lt;li&gt;inventory-aware sizing&lt;/li&gt;
&lt;li&gt;cross-market arbitrage models&lt;/li&gt;
&lt;li&gt;persistent event storage&lt;/li&gt;
&lt;li&gt;automatic strategy kill switches&lt;/li&gt;
&lt;li&gt;latency histograms&lt;/li&gt;
&lt;li&gt;replay-based regression tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also separate alpha generation from execution completely, allowing multiple strategies to share one execution and risk framework.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is a Polymarket arbitrage bot risk-free?
&lt;/h3&gt;

&lt;p&gt;No. A theoretical arbitrage can still suffer from partial fills, changing liquidity, execution failure, fees, and operational risk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does YES + NO below $1 always mean profit?
&lt;/h3&gt;

&lt;p&gt;No. You must evaluate executable size, fees, slippage, and execution risk.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use REST or WebSocket?
&lt;/h3&gt;

&lt;p&gt;For real-time order-book-driven strategies, WebSocket is the natural primary market-data path. REST remains useful for queries and account operations. ([Polymarket Documentation][2])&lt;/p&gt;

&lt;h3&gt;
  
  
  Which Python SDK should new integrations use?
&lt;/h3&gt;

&lt;p&gt;Polymarket's current documentation specifies &lt;code&gt;py-clob-client-v2&lt;/code&gt; for the CLOB V2 integration. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;h3&gt;
  
  
  Can arbitrage be profitable?
&lt;/h3&gt;

&lt;p&gt;It can be theoretically attractive, but profitability is strategy-, market-, liquidity-, fee-, and execution-dependent. No specific return should be assumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A serious &lt;strong&gt;Polymarket arbitrage bot&lt;/strong&gt; is not a price-comparison script.&lt;/p&gt;

&lt;p&gt;The durable architecture is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stream → normalize → detect → price costs → validate risk → execute → reconcile → monitor.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Build those boundaries correctly and you can change the arbitrage strategy without rebuilding the entire trading infrastructure.&lt;/p&gt;

&lt;p&gt;Trading and arbitrage involve substantial risk. Examples in this article are educational and do not imply profitability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Articles
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Build a Polymarket Trading Bot in Python&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;build a Polymarket trading bot in Python&lt;/em&gt;&lt;br&gt;
Why: foundational implementation.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket API Explained for Developers&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket API architecture&lt;/em&gt;&lt;br&gt;
Why: explains the API layer behind the bot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build a Real-Time Polymarket Order Book Monitor&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;real-time Polymarket order book monitor&lt;/em&gt;&lt;br&gt;
Why: directly supports the market-data layer.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket CLOB Architecture Explained&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket CLOB architecture&lt;/em&gt;&lt;br&gt;
Why: explains the execution venue.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket Trading Bot Risk Management&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket bot risk management&lt;/em&gt;&lt;br&gt;
Why: expands the risk engine.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket WebSocket Trading Data&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket WebSocket data&lt;/em&gt;&lt;br&gt;
Why: supports event-driven architecture.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://polymarket.com" rel="noopener noreferrer"&gt;Official Polymarket&lt;/a&gt; — platform and market interface.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com" rel="noopener noreferrer"&gt;Polymarket Developer Documentation&lt;/a&gt; — primary technical reference.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/trading/overview" rel="noopener noreferrer"&gt;Polymarket CLOB Trading Overview&lt;/a&gt; — CLOB architecture, authentication, and SDKs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/v2-migration" rel="noopener noreferrer"&gt;CLOB V2 Migration Guide&lt;/a&gt; — essential for current integrations.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/trading/fees" rel="noopener noreferrer"&gt;Polymarket Fees Documentation&lt;/a&gt; — current fee mechanics.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/api-reference/wss/market" rel="noopener noreferrer"&gt;Polymarket Market WebSocket Documentation&lt;/a&gt; — real-time order-book data.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://x.com/PolymarketDevs" rel="noopener noreferrer"&gt;Polymarket Developers on X&lt;/a&gt; — developer announcements.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://poly-smart-x.medium.com/polymarket-arbitrage-bot-automated-trading-with-7-high-performance-strategies-781801a03b10" rel="noopener noreferrer"&gt;Polymarket arbitrage bot — Medium example&lt;/a&gt; — third-party implementation discussion; useful for comparison, not authoritative.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=6p5hxaePrEw&amp;amp;utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket arbitrage bot — YouTube example&lt;/a&gt; — practical community demonstration; not an official technical source.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>polymarket</category>
      <category>arbitrage</category>
      <category>bot</category>
      <category>architecture</category>
    </item>
    <item>
      <title>Polymarket Trading Bot Setup: Practical 2026 Guide</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Wed, 26 Aug 2026 14:12:25 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-trading-bot-setup-practical-2026-guide-472h</link>
      <guid>https://dev.to/xniiinx/polymarket-trading-bot-setup-practical-2026-guide-472h</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Learn Polymarket Trading Bot Setup with Python, CLOB V2, authentication, WebSockets, execution, testing, security, and monitoring.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A serious Polymarket auto-trading bot is more than a Python script that submits orders. The difficult part is connecting &lt;strong&gt;market discovery, real-time order-book data, strategy logic, risk controls, authenticated execution, and monitoring&lt;/strong&gt; without allowing one component to corrupt the others.&lt;/p&gt;

&lt;p&gt;Polymarket's current CLOB architecture uses off-chain matching with on-chain settlement on Polygon. Its official documentation currently recommends the V2 clients, including &lt;code&gt;py-clob-client-v2&lt;/code&gt; for Python.&lt;/p&gt;

&lt;p&gt;This walkthrough builds the foundation for a production-oriented &lt;strong&gt;Polymarket Trading Bot Setup&lt;/strong&gt; without pretending that the infrastructure itself creates an edge.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bo$onaX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
X: &lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;&lt;br&gt;
Telegram: &lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;&lt;br&gt;
Github: &lt;a href="https://github.com/n9xdev/poly-alpha-lab" rel="noopener noreferrer"&gt;https://github.com/n9xdev/poly-alpha-lab&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to structure a Polymarket trading bot&lt;/li&gt;
&lt;li&gt;How CLOB V2 authentication works&lt;/li&gt;
&lt;li&gt;How to separate market data from execution&lt;/li&gt;
&lt;li&gt;How to use Python safely&lt;/li&gt;
&lt;li&gt;How to test before live execution&lt;/li&gt;
&lt;li&gt;How to monitor orders, fills, errors, and connectivity&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  1. Recommended Architecture
&lt;/h2&gt;

&lt;p&gt;A clean bot should separate responsibilities:&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart LR
    A[Market Discovery] --&amp;gt; B[Market Data Engine]
    B --&amp;gt; C[Strategy Engine]
    C --&amp;gt; D[Risk Manager]
    D --&amp;gt; E[Execution Engine]
    E --&amp;gt; F[Polymarket CLOB]
    F --&amp;gt; G[Order / Trade Events]
    G --&amp;gt; H[Portfolio State]
    H --&amp;gt; D
    B --&amp;gt; I[Monitoring]
    E --&amp;gt; I
    H --&amp;gt; I&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;The key design principle is simple: &lt;strong&gt;the strategy should decide what it wants to do; the execution layer should decide how to safely submit it.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Polymarket provides public methods for market data, prices, and order books without user credentials, while authenticated methods are required for trading operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Install the Current Python Client
&lt;/h2&gt;

&lt;p&gt;Do not blindly copy older tutorials using the legacy package. Polymarket's migration documentation says the old &lt;code&gt;py-clob-client&lt;/code&gt; package is for the previous CLOB version and recommends the V2 client for production integrations.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

pip &lt;span class="nb"&gt;install &lt;/span&gt;py-clob-client-v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pin the version you validate in production rather than allowing an unattended dependency upgrade to change trading behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configure Secrets
&lt;/h2&gt;

&lt;p&gt;Never hard-code wallet credentials.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_private_key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLOB_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_api_key"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLOB_SECRET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_secret"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;CLOB_PASSPHRASE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_passphrase"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For real deployments, use a secrets manager or protected environment configuration rather than committing &lt;code&gt;.env&lt;/code&gt; files to Git.&lt;/p&gt;

&lt;p&gt;Polymarket's current authentication model has two layers: wallet-based signing for L1 authentication and HMAC-based API credentials for L2 authenticated operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Initialize the Trading Client
&lt;/h2&gt;

&lt;p&gt;A minimal authenticated client can be structured like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;py_clob_client_v2&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApiCreds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ClobClient&lt;/span&gt;

&lt;span class="n"&gt;HOST&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://clob.polymarket.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;creds&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ApiCreds&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;api_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLOB_API_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;api_secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLOB_SECRET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;api_passphrase&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;CLOB_PASSPHRASE&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ClobClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;HOST&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;chain_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;137&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PRIVATE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;creds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Trading client initialized&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official V2 Python client documents this L1/L2 model and uses Polygon chain ID &lt;code&gt;137&lt;/code&gt; for mainnet.&lt;/p&gt;

&lt;p&gt;Before using live capital, verify the account configuration, signer type, funder address, and permissions required by your account setup.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Build the Market-Data Layer
&lt;/h2&gt;

&lt;p&gt;Do not make your strategy responsible for API requests.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For slower workflows, REST is sufficient. For event-driven strategies, use the public Market WebSocket. The official stream provides order-book snapshots and price-change updates, among other market events.&lt;/p&gt;

&lt;p&gt;This gives you a much cleaner architecture:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebSocket → local market state → strategy → risk → execution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;rather than:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;strategy → repeatedly poll API → make decision → submit order&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Add a Strategy Interface
&lt;/h2&gt;

&lt;p&gt;Keep strategy logic independent from Polymarket-specific networking.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fair_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;fair_value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;side&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BUY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reason&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;model_edge&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is deliberately hypothetical. A model's estimated fair value is not guaranteed to predict the outcome correctly.&lt;/p&gt;

&lt;p&gt;A real strategy should account for &lt;strong&gt;spread, liquidity, fees, slippage, execution probability, position exposure, and model uncertainty&lt;/strong&gt; before deciding that an apparent edge is tradable.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Put Risk Before Execution
&lt;/h2&gt;

&lt;p&gt;The risk layer should be able to reject a valid-looking signal.&lt;/p&gt;

&lt;p&gt;Typical controls include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Maximum position per market&lt;/li&gt;
&lt;li&gt;Maximum total exposure&lt;/li&gt;
&lt;li&gt;Maximum order size&lt;/li&gt;
&lt;li&gt;Maximum daily loss&lt;/li&gt;
&lt;li&gt;Maximum number of outstanding orders&lt;/li&gt;
&lt;li&gt;Price sanity checks&lt;/li&gt;
&lt;li&gt;Market-status checks&lt;/li&gt;
&lt;li&gt;Kill switch&lt;/li&gt;
&lt;li&gt;Duplicate-order protection&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fair_value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;risk_manager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;allows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;submit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one boundary prevents strategy bugs from becoming unrestricted order flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Execution
&lt;/h2&gt;

&lt;p&gt;Polymarket's current CLOB API supports order types including GTC, FOK, GTD, and FAK. The official order endpoint also returns an order ID and status such as &lt;code&gt;live&lt;/code&gt;, &lt;code&gt;matched&lt;/code&gt;, or &lt;code&gt;delayed&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The execution layer should therefore record:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signal_id
market
token_id
side
requested_price
requested_size
order_id
status
fill_size
fill_price
timestamp
error
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never treat a successful HTTP response as equivalent to a successful fill.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Production Considerations
&lt;/h2&gt;

&lt;p&gt;A production bot needs more than working code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connectivity:&lt;/strong&gt; reconnect WebSockets after disconnects and rebuild local state when necessary.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State:&lt;/strong&gt; persist open orders and positions so a process restart does not create duplicate exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retries:&lt;/strong&gt; retry transient network failures carefully. Never blindly retry an order submission without understanding whether the previous request succeeded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Clock:&lt;/strong&gt; synchronize timestamps and log server/client timing consistently.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dependencies:&lt;/strong&gt; pin and test SDK versions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Latency:&lt;/strong&gt; optimize only after measuring the actual path from market event → decision → order submission. Network placement, serialization, strategy computation, and connection reuse can all matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. Failure Modes
&lt;/h2&gt;

&lt;p&gt;Common mistakes include:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Using outdated SDK examples.&lt;/li&gt;
&lt;li&gt;Recreating clients for every order.&lt;/li&gt;
&lt;li&gt;Polling when a WebSocket architecture is more appropriate.&lt;/li&gt;
&lt;li&gt;Assuming an accepted order means it filled.&lt;/li&gt;
&lt;li&gt;Ignoring partial fills.&lt;/li&gt;
&lt;li&gt;Losing local state after a restart.&lt;/li&gt;
&lt;li&gt;Retrying non-idempotent actions blindly.&lt;/li&gt;
&lt;li&gt;Storing private keys in source code.&lt;/li&gt;
&lt;li&gt;Trading without position limits.&lt;/li&gt;
&lt;li&gt;Assuming historical strategy performance will continue.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The CLOB V2 migration is especially important: Polymarket explicitly states that legacy clients should not be used for current production CLOB V2 integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. Testing Strategy
&lt;/h2&gt;

&lt;p&gt;Build in stages:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 1 — Read only:&lt;/strong&gt; discover markets and inspect books.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 2 — Replay:&lt;/strong&gt; feed recorded market events into the strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 3 — Paper execution:&lt;/strong&gt; simulate orders, fills, fees, and inventory.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 4 — Small live test:&lt;/strong&gt; validate authentication and execution with controlled exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stage 5 — Production:&lt;/strong&gt; enable full monitoring and risk controls.&lt;/p&gt;

&lt;p&gt;The most important test is not “does the bot place an order?” It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens if the network fails immediately after the order request?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your system must be able to reconcile its state instead of guessing.&lt;/p&gt;

&lt;h2&gt;
  
  
  12. Monitoring
&lt;/h2&gt;

&lt;p&gt;At minimum, expose metrics for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;WebSocket connection state&lt;/li&gt;
&lt;li&gt;REST request latency&lt;/li&gt;
&lt;li&gt;API errors&lt;/li&gt;
&lt;li&gt;Orders submitted&lt;/li&gt;
&lt;li&gt;Orders rejected&lt;/li&gt;
&lt;li&gt;Orders filled&lt;/li&gt;
&lt;li&gt;Fill ratio&lt;/li&gt;
&lt;li&gt;Open exposure&lt;/li&gt;
&lt;li&gt;Realized/unrealized P&amp;amp;L&lt;/li&gt;
&lt;li&gt;Strategy decisions&lt;/li&gt;
&lt;li&gt;Risk rejections&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The authenticated User WebSocket can provide real-time order and trade events, making it useful for keeping execution state synchronized.&lt;/p&gt;

&lt;h2&gt;
  
  
  13. Practical Example
&lt;/h2&gt;

&lt;p&gt;Suppose your model estimates a hypothetical outcome at &lt;strong&gt;62%&lt;/strong&gt;, while the executable price is &lt;strong&gt;$0.55&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The bot should not simply say:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;62% &amp;gt; 55% → BUY&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model probability
        ↓
Fair-value estimate
        ↓
Spread + liquidity check
        ↓
Fee/slippage estimate
        ↓
Position-risk check
        ↓
Order-size calculation
        ↓
Submit
        ↓
Verify actual order/fill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That difference separates a trading experiment from a trading system.&lt;/p&gt;

&lt;h2&gt;
  
  
  14. Advanced Improvements
&lt;/h2&gt;

&lt;p&gt;Once the foundation works, add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local order-book reconstruction&lt;/li&gt;
&lt;li&gt;Event-driven strategy evaluation&lt;/li&gt;
&lt;li&gt;Persistent state&lt;/li&gt;
&lt;li&gt;Order reconciliation&lt;/li&gt;
&lt;li&gt;Portfolio-level risk&lt;/li&gt;
&lt;li&gt;Strategy replay&lt;/li&gt;
&lt;li&gt;Structured JSON logging&lt;/li&gt;
&lt;li&gt;Prometheus/Grafana metrics&lt;/li&gt;
&lt;li&gt;Multiple strategy modules&lt;/li&gt;
&lt;li&gt;Market-specific configuration&lt;/li&gt;
&lt;li&gt;Automated kill switches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For builders using Polymarket's Builder ecosystem, order attribution can also be attached to orders through the documented builder-code mechanism.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is Python suitable for a Polymarket trading bot?
&lt;/h3&gt;

&lt;p&gt;Yes. Polymarket officially provides Python tooling, including its current CLOB client ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need API credentials to read market data?
&lt;/h3&gt;

&lt;p&gt;Public market-data methods do not require user credentials. Trading operations do.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I start with live trading?
&lt;/h3&gt;

&lt;p&gt;No. Validate market data, strategy behavior, order handling, and recovery logic before committing meaningful capital.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does automation guarantee profitability?
&lt;/h3&gt;

&lt;p&gt;No. Infrastructure can improve consistency and execution, but it cannot guarantee a positive trading edge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use REST or WebSockets?
&lt;/h3&gt;

&lt;p&gt;Use REST where request/response access is appropriate and WebSockets when your strategy benefits from continuous market-event updates. Polymarket documents both interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A reliable &lt;strong&gt;Polymarket Trading Bot Setup&lt;/strong&gt; is fundamentally an engineering problem.&lt;/p&gt;

&lt;p&gt;Start with clean separation between data, strategy, risk, execution, and state. Use the current CLOB tooling, protect credentials, test failure scenarios, and measure execution instead of assuming it.&lt;/p&gt;

&lt;p&gt;The bot's first objective should not be making money.&lt;/p&gt;

&lt;p&gt;It should be &lt;strong&gt;behaving correctly when the market, network, API, strategy, or process does something unexpected.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Risk disclaimer:&lt;/strong&gt; This article is educational and does not constitute financial advice. Automated prediction-market trading can result in losses. Strategy performance is uncertain, and historical or hypothetical examples do not guarantee future results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Related Articles / Internal Topic Cluster
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build a Real-Time Polymarket Order Book Monitor&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket order book monitor&lt;/em&gt;&lt;br&gt;
Why: Natural next step after market-data architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Build a Polymarket Paper Trading Bot in Python&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket paper trading bot&lt;/em&gt;&lt;br&gt;
Why: Introduces safer execution testing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket API Explained for Developers&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket API&lt;/em&gt;&lt;br&gt;
Why: Covers the API architecture behind the bot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Build a Polymarket Trading Bot in Python&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;build a Polymarket trading bot in Python&lt;/em&gt;&lt;br&gt;
Why: Broader implementation guide.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket CLOB and Order Book Architecture&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket CLOB architecture&lt;/em&gt;&lt;br&gt;
Why: Explains the execution infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket&lt;/a&gt; — Official prediction-market platform.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Documentation&lt;/a&gt; — Primary technical reference for APIs, SDKs, trading, and developer tooling.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/trading/quickstart?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Trading Quickstart&lt;/a&gt; — Official end-to-end order setup.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Polymarket/py-clob-client-v2?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Python CLOB Client V2&lt;/a&gt; — Official Python implementation reference.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/polymarket?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket GitHub Organization&lt;/a&gt; — Official developer repositories and SDKs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://medium.com/%40benjamin.bigdev/how-polymarket-orders-actually-get-executed-a-deep-dive-into-clob-v2-for-developers-fdcd5d395ef5?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Medium: CLOB V2 Execution Deep Dive&lt;/a&gt; — Useful third-party explanation of the CLOB V2 execution lifecycle; verify implementation details against official docs.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://dev.to/bluewhale-quant-lab/building-a-low-latency-polymarket-trading-bot-in-python-py-clob-client-websocket-4il8?utm_source=chatgpt.com"&gt;DEV.to: Low-Latency Polymarket Bot in Python&lt;/a&gt; — Practical third-party discussion of WebSockets and execution architecture; not an authoritative source.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.youtube.com/watch?v=7R0mR7KvmSs&amp;amp;utm_source=chatgpt.com" rel="noopener noreferrer"&gt;YouTube: Polymarket API Tutorial&lt;/a&gt; — Practical video walkthrough; use official documentation to validate current API details.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://x.com/PolymarketDevs?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Developers on X&lt;/a&gt; — Useful for following developer announcements; verify important technical changes against the documentation.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>polymarket</category>
      <category>trading</category>
      <category>bot</category>
      <category>setup</category>
    </item>
    <item>
      <title>Polymarket Trading Bot Position Sizing: A Practical Guide</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Tue, 25 Aug 2026 09:00:53 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-trading-bot-position-sizing-a-practical-guide-59jj</link>
      <guid>https://dev.to/xniiinx/polymarket-trading-bot-position-sizing-a-practical-guide-59jj</guid>
      <description>&lt;h1&gt;
  
  
  Polymarket Trading Bot Position Sizing
&lt;/h1&gt;

&lt;p&gt;A profitable signal is not enough. A &lt;strong&gt;Polymarket trading bot&lt;/strong&gt; also needs to decide how much capital to risk.&lt;/p&gt;

&lt;p&gt;Position sizing is one of the most important—and most underestimated—parts of &lt;strong&gt;Polymarket algorithmic trading&lt;/strong&gt;. A bot with a good signal can still perform badly if it repeatedly overcommits capital, ignores liquidity, or treats correlated markets as independent opportunities.&lt;/p&gt;

&lt;p&gt;This guide shows how to build a practical Python position-sizing engine for a Polymarket bot using estimated probability, market price, fractional Kelly sizing, liquidity caps, and portfolio-level risk controls.&lt;/p&gt;

&lt;p&gt;Polymarket provides developer resources for programmatic market interaction, including market data and trading infrastructure. Builders should verify implementation details against the current official documentation before connecting production capital.&lt;/p&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bo$onaX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
X: &lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;&lt;br&gt;
Telegram: &lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;&lt;br&gt;
Youtube: &lt;a href="https://youtu.be/fbtzTnPiRW0?si=alLrul9Rw75m2fVf" rel="noopener noreferrer"&gt;https://youtu.be/fbtzTnPiRW0?si=alLrul9Rw75m2fVf&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to convert a probability model into a position size&lt;/li&gt;
&lt;li&gt;Why market price alone should not determine size&lt;/li&gt;
&lt;li&gt;How to calculate binary-contract Kelly sizing&lt;/li&gt;
&lt;li&gt;Why fractional Kelly is usually safer for uncertain models&lt;/li&gt;
&lt;li&gt;How to cap positions using portfolio and liquidity constraints&lt;/li&gt;
&lt;li&gt;How to implement the logic in Python&lt;/li&gt;
&lt;li&gt;How to monitor and test a production sizing engine&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  The Core Position-Sizing Problem
&lt;/h2&gt;

&lt;p&gt;Suppose your model estimates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Probability of YES: 62%
Market price:        55¢
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your estimated edge is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;edge = 0.62 - 0.55 = 0.07
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The obvious conclusion is to buy YES. But how much?&lt;/p&gt;

&lt;p&gt;A fixed strategy might buy $100 every time. That ignores an important distinction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;62% model vs 55¢ market
52% model vs 45¢ market
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both have a 7 percentage-point difference, but the payout structure and model confidence may differ.&lt;/p&gt;

&lt;p&gt;A robust &lt;strong&gt;Polymarket trading strategy&lt;/strong&gt; should separate:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Signal generation&lt;/li&gt;
&lt;li&gt;Probability estimation&lt;/li&gt;
&lt;li&gt;Position sizing&lt;/li&gt;
&lt;li&gt;Execution&lt;/li&gt;
&lt;li&gt;Portfolio risk management
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Market Data] --&amp;gt; B[Probability Model]
    B --&amp;gt; C[Estimated Edge]
    C --&amp;gt; D[Position Sizing Engine]
    D --&amp;gt; E[Risk &amp;amp; Liquidity Caps]
    E --&amp;gt; F[Polymarket Order Book]
    F --&amp;gt; G[Execution]
    G --&amp;gt; H[Portfolio State]
    H --&amp;gt; D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The sizing engine should never assume that a signal is automatically worth the maximum possible trade.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1: Calculate Edge
&lt;/h2&gt;

&lt;p&gt;For a YES contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estimated_probability&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;market_price&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;estimated_probability&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.62&lt;/span&gt;
&lt;span class="n"&gt;market_price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.55&lt;/span&gt;

&lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;estimated_probability&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;market_price&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# 0.07
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is only the beginning. Before sizing the trade, your bot should account for execution costs, spread, potential slippage, and model uncertainty.&lt;/p&gt;

&lt;p&gt;A practical approximation is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;net_edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_probability&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;entry_price&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;cost_buffer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;cost_buffer&lt;/code&gt; is strategy-specific. Do not hard-code a universal Polymarket fee or slippage value without checking the current market and official documentation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2: Use Kelly Criterion
&lt;/h2&gt;

&lt;p&gt;For a binary position, a simplified Kelly calculation can be expressed as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;f = (p × b - q) / b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;p&lt;/code&gt; = estimated probability of winning&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;q&lt;/code&gt; = &lt;code&gt;1 - p&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;b&lt;/code&gt; = potential profit relative to the amount risked&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;f&lt;/code&gt; = fraction of bankroll to allocate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a YES contract purchased at price &lt;code&gt;c&lt;/code&gt;, the theoretical profit multiple at resolution is approximately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;b = (1 - c) / c
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Python implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;kelly_fraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;probability&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Probability must be between 0 and 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price must be between 0 and 1&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
    &lt;span class="n"&gt;q&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;probability&lt;/span&gt;

    &lt;span class="n"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probability&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fraction&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.62&lt;/span&gt;
&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.55&lt;/span&gt;

&lt;span class="n"&gt;kelly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;kelly_fraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Kelly fraction: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kelly&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a theoretical fraction of bankroll.&lt;/p&gt;

&lt;p&gt;But full Kelly can be dangerous when your probability estimate is imperfect—which, in real trading, it almost always is.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3: Use Fractional Kelly
&lt;/h2&gt;

&lt;p&gt;A more conservative approach is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;fractional_kelly&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;kelly&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;KELLY_MULTIPLIER&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fractional_kelly_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bankroll&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;KELLY_MULTIPLIER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;kelly_fraction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;bankroll&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;fraction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact multiplier is a strategy parameter, not a universal rule. A smaller multiplier may be appropriate when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the probability model is poorly calibrated&lt;/li&gt;
&lt;li&gt;historical data is limited&lt;/li&gt;
&lt;li&gt;markets are highly correlated&lt;/li&gt;
&lt;li&gt;execution costs are uncertain&lt;/li&gt;
&lt;li&gt;liquidity is thin&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 4: Add Hard Risk Caps
&lt;/h2&gt;

&lt;p&gt;Kelly alone should not control your &lt;strong&gt;Polymarket bot&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A production sizing engine should apply multiple limits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RiskLimits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;max_position_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;
    &lt;span class="n"&gt;max_portfolio_exposure_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.40&lt;/span&gt;
    &lt;span class="n"&gt;max_market_liquidity_pct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.10&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;calculate_position_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bankroll&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;available_liquidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;RiskLimits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;kelly_multiplier&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;raw_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fractional_kelly_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;bankroll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;bankroll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;kelly_multiplier&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;position_cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;bankroll&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_position_pct&lt;/span&gt;

    &lt;span class="n"&gt;liquidity_cap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;available_liquidity&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_market_liquidity_pct&lt;/span&gt;

    &lt;span class="n"&gt;final_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;raw_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;position_cap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;liquidity_cap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;final_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result is not simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model edge → maximum capital
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model edge
    ↓
Kelly estimate
    ↓
fractional Kelly
    ↓
portfolio cap
    ↓
liquidity cap
    ↓
final position size
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Position Sizing and the Polymarket Order Book
&lt;/h2&gt;

&lt;p&gt;Your model may recommend a $2,000 position, but the visible &lt;strong&gt;Polymarket order book&lt;/strong&gt; may not support a $2,000 trade at your expected price.&lt;/p&gt;

&lt;p&gt;That creates execution risk.&lt;/p&gt;

&lt;p&gt;Before sending an order, a production &lt;strong&gt;Polymarket API Python&lt;/strong&gt; client should estimate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;available size at target prices&lt;/li&gt;
&lt;li&gt;average fill price&lt;/li&gt;
&lt;li&gt;spread&lt;/li&gt;
&lt;li&gt;potential slippage&lt;/li&gt;
&lt;li&gt;whether the trade itself moves the market&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simple position-size formula can therefore become:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final_size =
min(
    model_size,
    portfolio_cap,
    liquidity_cap,
    slippage_cap
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For active strategies, live market data can be monitored through the relevant Polymarket data infrastructure and websocket interfaces described in the current developer documentation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Production Architecture
&lt;/h2&gt;

&lt;p&gt;A clean &lt;strong&gt;Polymarket trading bot Python&lt;/strong&gt; architecture should keep sizing independent from execution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;strategy/
    signal.py
    probability_model.py

risk/
    position_sizing.py
    exposure.py
    correlation.py

execution/
    orderbook.py
    orders.py
    fills.py

monitoring/
    metrics.py
    alerts.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This separation is important because your signal model may change while your risk engine should remain conservative.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retry Carefully
&lt;/h3&gt;

&lt;p&gt;Do not blindly retry an order because a request failed. First determine whether the order may have been accepted.&lt;/p&gt;

&lt;p&gt;Use exponential backoff for safe retryable network operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;

&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;operation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warning&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Operation failed on attempt %d: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt;

            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Order submission requires idempotency and order-state reconciliation. Network failure does not necessarily mean that an order was rejected.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Failure Modes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Full Kelly with an overconfident model
&lt;/h3&gt;

&lt;p&gt;A small probability-estimation error can dramatically affect recommended size.&lt;/p&gt;

&lt;p&gt;Use conservative sizing until calibration has been validated.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Ignoring correlated exposure
&lt;/h3&gt;

&lt;p&gt;Five positions may look diversified but actually depend on the same event or price movement.&lt;/p&gt;

&lt;p&gt;Portfolio-level exposure matters more than the number of open trades.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Sizing from the last traded price
&lt;/h3&gt;

&lt;p&gt;Your actual fill may occur at a worse price.&lt;/p&gt;

&lt;p&gt;Size from executable order-book liquidity, not an outdated snapshot.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Treating paper trading as live trading
&lt;/h3&gt;

&lt;p&gt;Paper systems often fail to model partial fills, queue position, slippage, and adverse selection accurately.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. No maximum loss controls
&lt;/h3&gt;

&lt;p&gt;Every automated system should have hard limits independent of the strategy model.&lt;/p&gt;




&lt;h2&gt;
  
  
  Testing and Monitoring
&lt;/h2&gt;

&lt;p&gt;Test the sizing engine independently from the &lt;strong&gt;Polymarket market making bot&lt;/strong&gt; or execution layer.&lt;/p&gt;

&lt;p&gt;At minimum:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_no_positive_edge_returns_zero&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fractional_kelly_size&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;bankroll&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;probability&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.50&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;0.55&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Monitor:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bankroll&lt;/li&gt;
&lt;li&gt;open exposure&lt;/li&gt;
&lt;li&gt;gross and net exposure&lt;/li&gt;
&lt;li&gt;largest position&lt;/li&gt;
&lt;li&gt;position size as percentage of equity&lt;/li&gt;
&lt;li&gt;estimated versus realized fill price&lt;/li&gt;
&lt;li&gt;model probability versus market probability&lt;/li&gt;
&lt;li&gt;rejected orders&lt;/li&gt;
&lt;li&gt;partial fills&lt;/li&gt;
&lt;li&gt;daily drawdown&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current Polymarket exchange stack has undergone recent upgrades, including changes described by Polymarket to exchange contracts and order-book behavior, so production bots should be maintained against the latest official migration and developer documentation rather than relying on old SDK assumptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Practical Example
&lt;/h2&gt;

&lt;p&gt;Assume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bankroll:                 $10,000
Model probability:        0.62
YES entry price:          0.55
Fractional Kelly:         25%
Maximum position:         5% bankroll
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your sizing engine calculates a theoretical Kelly amount, reduces it using the fractional Kelly multiplier, and then checks the hard position limit.&lt;/p&gt;

&lt;p&gt;Even if the model recommends more, the final position cannot exceed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$10,000 × 5% = $500
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If order-book liquidity or expected slippage requires an even smaller amount, the bot should reduce the position further.&lt;/p&gt;

&lt;p&gt;That is the central principle:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The best position size is not the largest mathematically possible position. It is the largest position your strategy, liquidity, execution system, and portfolio risk limits can realistically support.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Advanced Improvements
&lt;/h2&gt;

&lt;p&gt;More advanced &lt;strong&gt;Polymarket automated trading&lt;/strong&gt; systems can add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;probability calibration curves&lt;/li&gt;
&lt;li&gt;confidence-weighted Kelly sizing&lt;/li&gt;
&lt;li&gt;correlation-aware portfolio sizing&lt;/li&gt;
&lt;li&gt;dynamic exposure limits&lt;/li&gt;
&lt;li&gt;volatility-aware capital allocation&lt;/li&gt;
&lt;li&gt;strategy-level capital budgets&lt;/li&gt;
&lt;li&gt;real-time fill-quality feedback&lt;/li&gt;
&lt;li&gt;model-specific risk multipliers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A useful next step is to make the sizing multiplier dynamic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;final_kelly_multiplier =
base_multiplier
× model_confidence
× liquidity_quality
× portfolio_risk_factor
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows a &lt;strong&gt;Polymarket arbitrage bot&lt;/strong&gt; or directional strategy to reduce capital automatically when execution quality deteriorates.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  How much should a Polymarket trading bot risk per trade?
&lt;/h3&gt;

&lt;p&gt;There is no universal number. Use estimated edge, model confidence, available liquidity, portfolio exposure, and a hard maximum position cap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is Kelly Criterion good for a Polymarket bot?
&lt;/h3&gt;

&lt;p&gt;It can be useful, but full Kelly assumes accurate probabilities. Fractional Kelly and hard risk caps are generally more robust for uncertain real-world models.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should a Polymarket arbitrage bot use position sizing?
&lt;/h3&gt;

&lt;p&gt;Yes. Arbitrage still has execution risk, partial-fill risk, capital constraints, and settlement or inventory considerations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I size trades from the best bid or ask?
&lt;/h3&gt;

&lt;p&gt;Use realistic executable prices and enough order-book depth to estimate the actual average fill price.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a Polymarket websocket improve position sizing?
&lt;/h3&gt;

&lt;p&gt;Yes. Real-time market data can help update liquidity and pricing inputs, but the final implementation should follow the current official Polymarket developer documentation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://polymarket.com" rel="noopener noreferrer"&gt;Polymarket Official Website&lt;/a&gt; — Market access and platform information.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com" rel="noopener noreferrer"&gt;Official Polymarket Documentation&lt;/a&gt; — Primary technical authority for API and trading implementation.&lt;/li&gt;
&lt;li&gt;— Official starting point for developers looking for programmatic resources.&lt;/li&gt;
&lt;li&gt;— Useful for developers building applications and infrastructure around Polymarket.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://x.com/Polymarket" rel="noopener noreferrer"&gt;Polymarket Official X Account&lt;/a&gt; — Official announcements and platform updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Third-party Medium, DEV.to, and YouTube resources were not included here because a current, directly relevant resource could not be verified confidently enough for this technical article.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Position sizing is the bridge between a &lt;strong&gt;Polymarket trading strategy&lt;/strong&gt; and actual capital risk.&lt;/p&gt;

&lt;p&gt;A production system should not simply ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Is this trade profitable?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It should ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How much should we risk after accounting for edge, model uncertainty, liquidity, execution quality, and existing exposure?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For most systems, a strong starting architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Probability model
→ Net edge
→ Fractional Kelly
→ Position cap
→ Liquidity cap
→ Portfolio risk check
→ Order execution
→ Fill reconciliation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That framework works for directional strategies, &lt;strong&gt;Polymarket arbitrage&lt;/strong&gt;, market making, and more complex algorithmic systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Educational and trading-risk disclaimer:&lt;/strong&gt; This article is for educational and software-development purposes only. Prediction-market trading involves substantial risk. No position-sizing formula guarantees profit or prevents losses. Test thoroughly and independently verify current platform behavior before deploying capital.&lt;/p&gt;




&lt;h1&gt;
  
  
  Related Articles
&lt;/h1&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How Polymarket CLOB Works&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “Polymarket CLOB architecture”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Helps readers understand how orders interact with the exchange.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket Order Book Explained&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “Polymarket order book liquidity”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Essential for liquidity-aware position sizing.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Handle Slippage in a Polymarket Bot&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “slippage-aware position sizing”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Connects sizing decisions with realistic execution costs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Build a Polymarket Trading Bot&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “build a Polymarket trading bot”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Broad pillar article for implementation architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket WebSocket Guide&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “real-time Polymarket market data”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Supports live price and liquidity updates.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket Arbitrage Bot Development&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “Polymarket arbitrage bot”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Explains sizing in multi-leg strategies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket TWAP Trading Bot&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Anchor text:&lt;/strong&gt; “Polymarket TWAP strategy”&lt;br&gt;
&lt;strong&gt;Why:&lt;/strong&gt; Connects position sizing with time-sensitive market strategies.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>polymarket</category>
      <category>trading</category>
      <category>position</category>
      <category>sizing</category>
    </item>
    <item>
      <title>Build a Real-Time Polymarket Order Book Monitor with Python</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Sat, 22 Aug 2026 12:35:31 +0000</pubDate>
      <link>https://dev.to/xniiinx/build-a-real-time-polymarket-order-book-monitor-with-python-10pf</link>
      <guid>https://dev.to/xniiinx/build-a-real-time-polymarket-order-book-monitor-with-python-10pf</guid>
      <description>&lt;h1&gt;
  
  
  Build a Real-Time Polymarket Order Book Monitor
&lt;/h1&gt;

&lt;p&gt;A trading bot should not make decisions from stale snapshots. If you want to understand liquidity, spread, depth, or changes in market structure, you need a continuously updated view of the Polymarket order book.&lt;/p&gt;

&lt;p&gt;This tutorial builds a lightweight &lt;strong&gt;Polymarket order book Python&lt;/strong&gt; monitor using the public CLOB Market WebSocket. Polymarket documents this channel as a real-time feed for order-book, price, and market lifecycle updates.&lt;/p&gt;

&lt;p&gt;The implementation intentionally focuses on market data—not order execution—so it can be used as the foundation for research, dashboards, alerts, or an automated trading system.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How Polymarket token IDs relate to order-book subscriptions&lt;/li&gt;
&lt;li&gt;How to connect to the CLOB Market WebSocket&lt;/li&gt;
&lt;li&gt;How to process &lt;code&gt;book&lt;/code&gt; and &lt;code&gt;price_change&lt;/code&gt; events&lt;/li&gt;
&lt;li&gt;How to calculate best bid, best ask, and spread&lt;/li&gt;
&lt;li&gt;How to handle reconnects and heartbeats&lt;/li&gt;
&lt;li&gt;How to detect stale market data&lt;/li&gt;
&lt;li&gt;How to turn raw WebSocket events into trading signals&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Polymarket CLOB] --&amp;gt; B[Market WebSocket]
    B --&amp;gt; C[Python Async Client]
    C --&amp;gt; D[Order Book State]
    D --&amp;gt; E[Spread / Depth Metrics]
    D --&amp;gt; F[Trading Signal Engine]
    D --&amp;gt; G[Logging / Monitoring]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important design decision is separating &lt;strong&gt;transport&lt;/strong&gt; from &lt;strong&gt;state&lt;/strong&gt;. The WebSocket delivers events; your application maintains the current book.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Install the Dependencies
&lt;/h2&gt;

&lt;p&gt;For this monitor, authentication is not required because the Market WebSocket is public.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;websockets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need a Polymarket &lt;strong&gt;asset ID/token ID&lt;/strong&gt; for the outcome you want to monitor. The Market Channel subscribes using &lt;code&gt;assets_ids&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;TOKEN_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_TOKEN_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not hard-code credentials into a market-data monitor. In this example, there are no credentials at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Connect to the Market WebSocket
&lt;/h2&gt;

&lt;p&gt;The documented Market Channel endpoint is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wss://ws-subscriptions-clob.polymarket.com/ws/market
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The subscription message contains &lt;code&gt;type: "market"&lt;/code&gt; and one or more asset IDs.&lt;/p&gt;

&lt;p&gt;A minimal monitor looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;websockets&lt;/span&gt;

&lt;span class="n"&gt;WS_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;wss://ws-subscriptions-clob.polymarket.com/ws/market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;TOKEN_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_TOKEN_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s %(levelname)s %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;websockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;WS_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;ping_interval&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;assets_ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;TOKEN_ID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;

        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Subscribed to %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TOKEN_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;raw_message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;raw_message&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PONG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;continue&lt;/span&gt;

            &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;raw_message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;handle_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;handle_message&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;event_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;event_type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;event_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;event_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price_change&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price update: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price_changes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;elif&lt;/span&gt; &lt;span class="n"&gt;event_type&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;last_trade_price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Trade: %s @ %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;bids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="n"&gt;asks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;bids&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;asks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;asks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;spread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;best_bid&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Bid=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;best_bid&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Ask=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Spread=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;spread&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;monitor&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The initial &lt;code&gt;book&lt;/code&gt; event contains aggregated bid and ask levels. Polymarket also documents &lt;code&gt;price_change&lt;/code&gt; as an order-book price-level delta event.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Don't Ignore the Heartbeat
&lt;/h2&gt;

&lt;p&gt;A production client should implement the documented application-level heartbeat. Polymarket's current documentation specifies that clients send &lt;code&gt;PING&lt;/code&gt; every 10 seconds and receive &lt;code&gt;PONG&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Add a dedicated heartbeat task:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;heartbeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;PING&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then start it after connecting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;heartbeat_task&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;heartbeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;raw_message&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;finally&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;heartbeat_task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cancel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is preferable to relying blindly on the WebSocket library's protocol-level ping mechanism because the Polymarket feed specifies its own application-level heartbeat.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Maintain Book State
&lt;/h2&gt;

&lt;p&gt;For research, repeatedly printing snapshots is not enough.&lt;/p&gt;

&lt;p&gt;Store price levels in dictionaries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For every snapshot:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;size&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A real implementation should also process every documented price-level change according to its &lt;code&gt;side&lt;/code&gt;, &lt;code&gt;price&lt;/code&gt;, and &lt;code&gt;size&lt;/code&gt; fields.&lt;/p&gt;

&lt;p&gt;The key principle is simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The WebSocket is the event stream. Your local order book is the state machine.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Useful Real-Time Metrics
&lt;/h2&gt;

&lt;p&gt;Once the book is normalized, you can calculate:&lt;/p&gt;

&lt;h3&gt;
  
  
  Best bid
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Best ask
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Spread
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;spread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;best_bid&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Midpoint
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Top-of-book imbalance
&lt;/h3&gt;

&lt;p&gt;A simple research metric is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;imbalance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bid_size&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;ask_size&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bid_size&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;ask_size&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These metrics do &lt;strong&gt;not&lt;/strong&gt; constitute a profitable strategy by themselves. They are observations that can become inputs to a broader execution or pricing model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production Considerations
&lt;/h2&gt;

&lt;p&gt;A production monitor should add:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Automatic reconnection&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Exponential backoff&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Subscription restoration&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Heartbeat monitoring&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Message validation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sequence/state consistency checks&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stale-data detection&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Structured logging&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Persistent event storage&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Graceful shutdown&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do not assume that an open TCP/WebSocket connection means your market data is healthy.&lt;/p&gt;

&lt;p&gt;Polymarket's status history has documented WebSocket incidents and CLOB maintenance events, so operational monitoring matters even when your application code is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Failure Modes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Connection succeeds but no data arrives
&lt;/h3&gt;

&lt;p&gt;Check the asset ID, subscription payload, market state, and application heartbeat.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your book becomes inconsistent
&lt;/h3&gt;

&lt;p&gt;Do not treat every message as an independent snapshot. Distinguish full &lt;code&gt;book&lt;/code&gt; events from incremental &lt;code&gt;price_change&lt;/code&gt; events.&lt;/p&gt;

&lt;h3&gt;
  
  
  Your monitor silently becomes stale
&lt;/h3&gt;

&lt;p&gt;Track the timestamp of the most recent valid market event and raise an alert when it exceeds your application's freshness threshold.&lt;/p&gt;

&lt;h3&gt;
  
  
  The code breaks after a Polymarket API change
&lt;/h3&gt;

&lt;p&gt;Pin and regularly review dependencies, then check the official documentation and changelog before upgrading production infrastructure. Polymarket's changelog records significant CLOB/API changes, including the 2026 CLOB V2 production migration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance Considerations
&lt;/h2&gt;

&lt;p&gt;Do not perform expensive calculations inside the WebSocket receive loop.&lt;/p&gt;

&lt;p&gt;A better architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WebSocket
   ↓
Parser
   ↓
Book State
   ↓
Event Queue
   ↓
Analytics Workers
   ↓
Strategy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The receive loop should process messages quickly and hand heavier work to another component.&lt;/p&gt;

&lt;p&gt;For high-frequency research, avoid unnecessary JSON transformations, excessive logging, database writes on every event, and repeated full-book sorting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security
&lt;/h2&gt;

&lt;p&gt;A public order-book monitor does not need private keys or trading credentials.&lt;/p&gt;

&lt;p&gt;Keep the market-data process separate from execution credentials whenever possible. If you later connect the monitor to order placement, store secrets in environment variables or a proper secret-management system.&lt;/p&gt;

&lt;p&gt;Never put private keys, API secrets, or seed phrases inside source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing Strategy
&lt;/h2&gt;

&lt;p&gt;Use recorded WebSocket messages to build deterministic tests.&lt;/p&gt;

&lt;p&gt;Test at least:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Empty books&lt;/li&gt;
&lt;li&gt;One-sided books&lt;/li&gt;
&lt;li&gt;Multiple price levels&lt;/li&gt;
&lt;li&gt;Price-level removal&lt;/li&gt;
&lt;li&gt;Price changes&lt;/li&gt;
&lt;li&gt;Malformed JSON&lt;/li&gt;
&lt;li&gt;Unknown event types&lt;/li&gt;
&lt;li&gt;Reconnection&lt;/li&gt;
&lt;li&gt;Heartbeat failure&lt;/li&gt;
&lt;li&gt;Stale timestamps&lt;/li&gt;
&lt;li&gt;Tick-size changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A particularly useful test is replaying a historical event sequence and verifying that your reconstructed book matches the expected final state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Monitoring and Observability
&lt;/h2&gt;

&lt;p&gt;Expose metrics such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;websocket_connected
last_message_timestamp
messages_received
book_events
price_change_events
reconnect_count
parse_errors
book_age_seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For trading infrastructure, &lt;strong&gt;data freshness is itself a metric&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A strategy using a technically correct but stale order book can make decisions based on a market that no longer exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Improvements
&lt;/h2&gt;

&lt;p&gt;Once the basic monitor works, extend it into a research-grade market-data engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subscribe to multiple tokens&lt;/li&gt;
&lt;li&gt;Maintain separate books per asset&lt;/li&gt;
&lt;li&gt;Store normalized events in Parquet&lt;/li&gt;
&lt;li&gt;Calculate depth at multiple price levels&lt;/li&gt;
&lt;li&gt;Track spread changes&lt;/li&gt;
&lt;li&gt;Detect liquidity withdrawals&lt;/li&gt;
&lt;li&gt;Build order-book imbalance features&lt;/li&gt;
&lt;li&gt;Compare Polymarket prices with external models&lt;/li&gt;
&lt;li&gt;Feed normalized data into a signal engine&lt;/li&gt;
&lt;li&gt;Replay recorded books for backtesting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This creates a clean separation between &lt;strong&gt;market-data collection&lt;/strong&gt;, &lt;strong&gt;feature generation&lt;/strong&gt;, &lt;strong&gt;strategy logic&lt;/strong&gt;, and &lt;strong&gt;execution&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is the Polymarket order book available through WebSocket?
&lt;/h3&gt;

&lt;p&gt;Yes. The public Market Channel provides real-time order-book and market updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need API credentials to monitor an order book?
&lt;/h3&gt;

&lt;p&gt;No. The Market Channel is public. The authenticated User Channel is separate and is used for user-specific order and trade updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is an asset ID?
&lt;/h3&gt;

&lt;p&gt;It identifies a specific outcome token used by the CLOB Market WebSocket subscription.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I poll the order book instead?
&lt;/h3&gt;

&lt;p&gt;Polling can be useful for snapshots and recovery, but a streaming architecture is more appropriate when you need continuous market-data updates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does an order-book monitor guarantee trading profits?
&lt;/h3&gt;

&lt;p&gt;No. Market-data quality is only one component of a trading system. Slippage, fees, liquidity, latency, adverse selection, execution risk, and model error can all affect results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Building a &lt;strong&gt;Polymarket order book Python&lt;/strong&gt; monitor is less about printing bids and asks and more about building a reliable market-data pipeline.&lt;/p&gt;

&lt;p&gt;Start with the public CLOB Market WebSocket, maintain local book state, process snapshots and price changes correctly, implement heartbeats and reconnection, and measure data freshness.&lt;/p&gt;

&lt;p&gt;Once that foundation is reliable, you can build analytics and trading logic on top of it without coupling strategy code to the raw WebSocket transport.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Educational disclaimer:&lt;/strong&gt; This article is for software-development and market-data research purposes. Order-book signals do not guarantee profitable trading, and automated trading involves financial and technical risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related Articles
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Build a Polymarket Trading Bot in Python&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket trading bot in Python&lt;/em&gt;&lt;br&gt;
Connects market-data infrastructure to the complete bot architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket API Explained for Developers&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket API&lt;/em&gt;&lt;br&gt;
Provides broader API architecture and endpoint context.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How Polymarket CLOB Works&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket CLOB&lt;/em&gt;&lt;br&gt;
Explains the central-limit order-book model behind the monitor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket WebSocket API Guide&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket WebSocket API&lt;/em&gt;&lt;br&gt;
Natural follow-up for streaming architecture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Calculate Polymarket Market Probability&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket probability calculation&lt;/em&gt;&lt;br&gt;
Connects prices and order-book observations to quantitative analysis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Building a Polymarket Market-Making Bot&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;em&gt;Polymarket market-making bot&lt;/em&gt;&lt;br&gt;
Extends the data layer toward automated quoting.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket&lt;/a&gt; — Official prediction-market platform.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Documentation&lt;/a&gt; — Primary technical reference.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/api-reference/wss/market?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Market Channel documentation&lt;/a&gt; — Current CLOB Market WebSocket message and subscription reference.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/changelog?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Changelog&lt;/a&gt; — Useful for tracking API and CLOB changes.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://status.polymarket.com/en-us?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Status&lt;/a&gt; — Operational status and incident history.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I have intentionally omitted Medium, DEV.to, and YouTube resources because I could not verify a specific current resource that is sufficiently relevant to this exact implementation without fabricating a URL.&lt;/p&gt;

&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bo$onaX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
X: &lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;&lt;br&gt;
Telegram: &lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;&lt;/p&gt;

</description>
      <category>polymarket</category>
      <category>orderbook</category>
      <category>python</category>
    </item>
    <item>
      <title>Polymarket Market Scanner in Python: Build One</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Fri, 21 Aug 2026 16:52:39 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-market-scanner-in-python-build-one-30dj</link>
      <guid>https://dev.to/xniiinx/polymarket-market-scanner-in-python-build-one-30dj</guid>
      <description>&lt;h1&gt;
  
  
  Build a Polymarket Market Scanner in Python
&lt;/h1&gt;

&lt;p&gt;A trading bot should not start by placing orders. It should first answer a simpler question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which Polymarket markets are worth looking at right now?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is the job of a market scanner.&lt;/p&gt;

&lt;p&gt;A useful &lt;strong&gt;Polymarket market scanner&lt;/strong&gt; continuously turns a large universe of prediction markets into a smaller, structured candidate set based on conditions such as market status, liquidity, volume, expiration, price, category, and order-book availability.&lt;/p&gt;

&lt;p&gt;Polymarket currently exposes public market data without authentication, including market discovery through the Gamma API and order-book/pricing data through the CLOB API. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;In this tutorial, we will build a read-only Python scanner that discovers active markets, applies quantitative filters, and produces candidates that a later strategy or execution engine can evaluate.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trading-risk disclaimer:&lt;/strong&gt; A scanner identifies markets matching predefined conditions. It does not establish that a trade is profitable. Spread, liquidity, fees, slippage, latency, adverse selection, model error, and resolution risk still matter.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;p&gt;By the end, you will understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How Polymarket market discovery works&lt;/li&gt;
&lt;li&gt;How to use the current keyset market endpoint&lt;/li&gt;
&lt;li&gt;How to paginate through markets safely&lt;/li&gt;
&lt;li&gt;How to filter markets quantitatively&lt;/li&gt;
&lt;li&gt;How to separate discovery from price/order-book analysis&lt;/li&gt;
&lt;li&gt;How to design a scanner that can evolve into a trading system&lt;/li&gt;
&lt;li&gt;What changes are required for production deployment&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Market Scanner Architecture
&lt;/h2&gt;

&lt;p&gt;The important design decision is to separate &lt;strong&gt;market discovery&lt;/strong&gt; from &lt;strong&gt;market evaluation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A scanner should not download every order book every time it scans the entire market universe. That creates unnecessary network traffic and makes scaling harder.&lt;/p&gt;

&lt;p&gt;A better architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Gamma Market Discovery] --&amp;gt; B[Market Universe]
    B --&amp;gt; C[Basic Filters]
    C --&amp;gt; D[Candidate Markets]
    D --&amp;gt; E[CLOB Price / Order Book]
    E --&amp;gt; F[Quantitative Filters]
    F --&amp;gt; G[Ranked Opportunities]
    G --&amp;gt; H[Strategy Engine]
    H --&amp;gt; I[Execution Engine]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Gamma API provides market discovery and metadata. The CLOB API provides market prices and order-book information. Polymarket documents these as separate parts of its market-data architecture. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;That separation is useful because metadata changes much more slowly than order-book state.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Which API Should the Scanner Use?
&lt;/h2&gt;

&lt;p&gt;For broad market discovery, the current documentation provides a keyset-paginated endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://gamma-api.polymarket.com/markets/keyset
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It supports filters such as &lt;code&gt;closed&lt;/code&gt;, liquidity ranges, volume ranges, date ranges, tags, and ordering. The endpoint uses an opaque &lt;code&gt;next_cursor&lt;/code&gt; returned by one request as &lt;code&gt;after_cursor&lt;/code&gt; for the next request. Its maximum &lt;code&gt;limit&lt;/code&gt; is currently 100. ([Polymarket Documentation][2])&lt;/p&gt;

&lt;p&gt;This is preferable for a large scanner to repeatedly requesting arbitrary offsets.&lt;/p&gt;

&lt;p&gt;The CLOB API is then appropriate when the scanner needs order-book information such as bids, asks, midpoint, or prices. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;For a read-only scanner, authentication is not required for public market data. ([Polymarket Documentation][1])&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Project Setup
&lt;/h2&gt;

&lt;p&gt;For a simple scanner, Python's standard HTTP tooling is enough.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv

&lt;span class="c"&gt;# Windows&lt;/span&gt;
.venv&lt;span class="se"&gt;\S&lt;/span&gt;cripts&lt;span class="se"&gt;\a&lt;/span&gt;ctivate

&lt;span class="c"&gt;# Linux/macOS&lt;/span&gt;
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

pip &lt;span class="nb"&gt;install &lt;/span&gt;httpx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A minimal project can look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;polymarket-scanner/
├── scanner.py
├── requirements.txt
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;requirements.txt&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;httpx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No private key or trading credential is necessary for this version.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Fetch Markets With Keyset Pagination
&lt;/h2&gt;

&lt;p&gt;The first component is a market-discovery client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="n"&gt;GAMMA_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://gamma-api.polymarket.com/markets/keyset&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;fetch_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
    &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ascending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after_cursor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;

        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GAMMA_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
        &lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;next_cursor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;

        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;markets&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key detail is that the cursor is treated as opaque data. Do not try to construct or interpret it yourself.&lt;/p&gt;

&lt;p&gt;The official documentation specifically describes &lt;code&gt;next_cursor&lt;/code&gt; → &lt;code&gt;after_cursor&lt;/code&gt; pagination and rejects the &lt;code&gt;offset&lt;/code&gt; parameter for this endpoint. ([Polymarket Documentation][2])&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Add Basic Market Filters
&lt;/h2&gt;

&lt;p&gt;The raw market universe is usually much larger than the universe a strategy actually needs.&lt;/p&gt;

&lt;p&gt;For example, a scanner might require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;market is active&lt;/li&gt;
&lt;li&gt;market is not closed&lt;/li&gt;
&lt;li&gt;sufficient liquidity&lt;/li&gt;
&lt;li&gt;sufficient volume&lt;/li&gt;
&lt;li&gt;a known question&lt;/li&gt;
&lt;li&gt;an acceptable expiration horizon
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;filter_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;min_liquidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;min_volume&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;

    &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_liquidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_volume&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The numbers above are &lt;strong&gt;example configuration values&lt;/strong&gt;, not claims about optimal thresholds.&lt;/p&gt;

&lt;p&gt;A production scanner should make them configurable rather than hard-coding assumptions.&lt;/p&gt;

&lt;p&gt;The market API exposes fields including liquidity, volume, question, outcome information, dates, and other metadata. ([Polymarket Documentation][3])&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Parsing Outcome Prices
&lt;/h2&gt;

&lt;p&gt;Polymarket's market data represents outcomes and outcome prices as corresponding arrays. For binary markets, the first outcome and first price can commonly represent the first outcome in that market's outcome ordering. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;Because API representations can contain serialized JSON strings, parse them defensively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_outcomes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
    &lt;span class="n"&gt;outcomes_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcomes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;prices_raw&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcomePrices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;outcomes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outcomes_raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prices_raw&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outcomes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner can now reason about price levels without making assumptions about the underlying market question.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. A Complete Basic Scanner
&lt;/h2&gt;

&lt;p&gt;Putting the components together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;

&lt;span class="n"&gt;GAMMA_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://gamma-api.polymarket.com/markets/keyset&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nb"&gt;format&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;%(asctime)s %(levelname)s %(message)s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;parse_outcomes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;tuple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;outcomes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcomes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="n"&gt;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcomePrices&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;[]&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;JSONDecodeError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;zip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outcomes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prices&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nf"&gt;str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;outcome&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
        &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;pass&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;scan_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;min_liquidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;min_volume&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;25_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;

    &lt;span class="n"&gt;candidates&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;

    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_pages&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;closed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ascending&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;false&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;after_cursor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;

            &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;GAMMA_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;httpx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPError&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Market request failed: %s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;

            &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;markets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]):&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;

                &lt;span class="n"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_liquidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;

                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;min_volume&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;

                &lt;span class="n"&gt;candidates&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slug&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;slug&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;liquidity&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;outcomes&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;parse_outcomes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="p"&gt;})&lt;/span&gt;

            &lt;span class="n"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;next_cursor&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;candidates&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;scan_markets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is deliberately read-only.&lt;/p&gt;

&lt;p&gt;That is a useful engineering boundary: &lt;strong&gt;discovery should not have permission to trade.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Scanner → Order Book Evaluation
&lt;/h2&gt;

&lt;p&gt;Metadata filtering is only the first stage.&lt;/p&gt;

&lt;p&gt;Suppose 5,000 markets exist but only 100 satisfy your basic liquidity and volume criteria. There is little reason to request detailed order books for all 5,000.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;5,000 markets
     ↓
metadata filters
     ↓
100 candidates
     ↓
order-book queries
     ↓
20 liquid candidates
     ↓
strategy/model evaluation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLOB provides endpoints for individual and batch order-book and price queries. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;For a latency-sensitive scanner, the WebSocket market channel is another option. The documented market channel provides real-time order-book, price, and market-lifecycle updates. ([Polymarket Documentation][4])&lt;/p&gt;

&lt;p&gt;This creates two different scanner modes:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Batch scanner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Useful for research, scheduled screening, dashboards, and periodic candidate discovery.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Streaming scanner&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Useful when the system must react to changing market state rather than repeatedly polling.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Ranking Candidates
&lt;/h2&gt;

&lt;p&gt;Filtering answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does this market qualify?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ranking answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Which qualifying markets deserve attention first?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A simple ranking function could combine normalized liquidity and volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;score_market&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;liquidity&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a trading signal. It is merely a prioritization mechanism.&lt;/p&gt;

&lt;p&gt;A more sophisticated scanner could rank by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bid/ask spread&lt;/li&gt;
&lt;li&gt;displayed depth&lt;/li&gt;
&lt;li&gt;recent volume&lt;/li&gt;
&lt;li&gt;time to expiration&lt;/li&gt;
&lt;li&gt;price distance from a model estimate&lt;/li&gt;
&lt;li&gt;volatility&lt;/li&gt;
&lt;li&gt;market category&lt;/li&gt;
&lt;li&gt;event-level concentration&lt;/li&gt;
&lt;li&gt;historical price movement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The crucial principle is to keep &lt;strong&gt;market selection&lt;/strong&gt; separate from &lt;strong&gt;trade prediction&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A scanner should tell the strategy engine &lt;em&gt;where to look&lt;/em&gt;, not secretly become the strategy itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Production Considerations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Rate limits
&lt;/h3&gt;

&lt;p&gt;Polymarket documents rate limits across the Gamma, Data, and CLOB APIs. Current documentation lists Gamma &lt;code&gt;/markets&lt;/code&gt; at 300 requests per 10 seconds and CLOB &lt;code&gt;/book&lt;/code&gt; at 1,500 requests per 10 seconds, among other limits. ([Polymarket Documentation][5])&lt;/p&gt;

&lt;p&gt;Do not build a scanner around the assumption that unlimited polling is acceptable.&lt;/p&gt;

&lt;p&gt;Use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;bounded concurrency&lt;/li&gt;
&lt;li&gt;batching where supported&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;exponential backoff&lt;/li&gt;
&lt;li&gt;incremental updates&lt;/li&gt;
&lt;li&gt;WebSockets for continuously changing data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rate-limit values can change, so production systems should treat the official rate-limit documentation as the source of truth.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keyset pagination
&lt;/h3&gt;

&lt;p&gt;Use the current keyset endpoint for large market scans rather than designing new code around offset pagination. Polymarket announced the keyset endpoints in April 2026 and subsequently documented a maximum &lt;code&gt;limit&lt;/code&gt; of 100. ([Polymarket Documentation][6])&lt;/p&gt;

&lt;h3&gt;
  
  
  SDK selection
&lt;/h3&gt;

&lt;p&gt;Polymarket now maintains a unified Python SDK, &lt;code&gt;polymarket-client&lt;/code&gt;, which is currently described by the project as beta. ([GitHub][7])&lt;/p&gt;

&lt;p&gt;The older &lt;code&gt;py-clob-client&lt;/code&gt; repository is archived, while Polymarket's current Python SDK repository recommends the unified SDK for new projects. ([GitHub][8])&lt;/p&gt;

&lt;p&gt;For a small scanner, direct documented HTTP calls can be perfectly reasonable. For a larger application, evaluate the current official SDK and its stability before committing your architecture to a particular interface.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. Failure Modes and Common Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Scanning every order book
&lt;/h3&gt;

&lt;p&gt;This wastes requests and increases latency.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better:&lt;/strong&gt; filter the universe first.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using stale market assumptions
&lt;/h3&gt;

&lt;p&gt;Market APIs evolve. Fields, endpoints, SDKs, and pagination behavior can change.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better:&lt;/strong&gt; verify production assumptions against the current documentation and changelog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Treating liquidity as executable liquidity
&lt;/h3&gt;

&lt;p&gt;A liquidity number does not tell you exactly how much size you can execute at your desired price.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better:&lt;/strong&gt; inspect the actual order book before making execution decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assuming the displayed probability is your edge
&lt;/h3&gt;

&lt;p&gt;A market price is not automatically a trading opportunity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better:&lt;/strong&gt; compare market state against an independently constructed model and account for execution costs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mixing discovery and execution
&lt;/h3&gt;

&lt;p&gt;A scanner that can also immediately submit trades creates unnecessary operational risk.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Better:&lt;/strong&gt; keep discovery, signal generation, risk management, and execution as separate components.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. Performance Considerations
&lt;/h2&gt;

&lt;p&gt;The first optimization should usually be &lt;strong&gt;reducing unnecessary requests&lt;/strong&gt;, not micro-optimizing Python.&lt;/p&gt;

&lt;p&gt;A sensible progression is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Fetch market metadata.&lt;/li&gt;
&lt;li&gt;Filter locally.&lt;/li&gt;
&lt;li&gt;Batch price/order-book requests when appropriate.&lt;/li&gt;
&lt;li&gt;Cache relatively static metadata.&lt;/li&gt;
&lt;li&gt;Move continuously changing data to WebSockets.&lt;/li&gt;
&lt;li&gt;Parallelize only within documented limits.&lt;/li&gt;
&lt;li&gt;Measure request latency and processing time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, maintain two datasets:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market_metadata
    id
    question
    category
    liquidity
    volume
    end_date

market_state
    best_bid
    best_ask
    midpoint
    depth
    timestamp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents the scanner from repeatedly rebuilding static information.&lt;/p&gt;




&lt;h2&gt;
  
  
  13. Security
&lt;/h2&gt;

&lt;p&gt;A market scanner does not need a private key.&lt;/p&gt;

&lt;p&gt;Keep it that way.&lt;/p&gt;

&lt;p&gt;If the scanner eventually connects to a trading engine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;keep private keys outside source code&lt;/li&gt;
&lt;li&gt;use environment variables or a secret manager&lt;/li&gt;
&lt;li&gt;restrict credentials to the minimum required permissions&lt;/li&gt;
&lt;li&gt;separate research and production environments&lt;/li&gt;
&lt;li&gt;never log secrets&lt;/li&gt;
&lt;li&gt;never commit &lt;code&gt;.env&lt;/code&gt; files&lt;/li&gt;
&lt;li&gt;isolate order execution from market discovery&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Polymarket's authenticated trading workflows require credentials, but public market discovery does not. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;p&gt;A read-only scanner is therefore an excellent first component to build and test before introducing trading credentials.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Testing Strategy
&lt;/h2&gt;

&lt;p&gt;A scanner should be testable without contacting the live API.&lt;/p&gt;

&lt;p&gt;Separate network access from filtering logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;select_candidates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;min_liquidity&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="n"&gt;market&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;markets&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;min_liquidity&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then test synthetic inputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_liquidity_filter&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;markets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;50000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;1000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;active&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;90000&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;select_candidates&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing fields&lt;/li&gt;
&lt;li&gt;malformed JSON&lt;/li&gt;
&lt;li&gt;HTTP errors&lt;/li&gt;
&lt;li&gt;empty pages&lt;/li&gt;
&lt;li&gt;expired cursors&lt;/li&gt;
&lt;li&gt;duplicate markets&lt;/li&gt;
&lt;li&gt;unexpected API fields&lt;/li&gt;
&lt;li&gt;rate-limit responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Network tests should be separate integration tests.&lt;/p&gt;




&lt;h2&gt;
  
  
  15. Monitoring and Observability
&lt;/h2&gt;

&lt;p&gt;A production scanner should answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How many markets were discovered?&lt;/li&gt;
&lt;li&gt;How many passed each filter?&lt;/li&gt;
&lt;li&gt;How long did discovery take?&lt;/li&gt;
&lt;li&gt;How many CLOB requests were made?&lt;/li&gt;
&lt;li&gt;How many requests failed?&lt;/li&gt;
&lt;li&gt;What is the current scan cycle duration?&lt;/li&gt;
&lt;li&gt;When was each candidate last updated?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Useful metrics include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;markets_discovered
markets_filtered
candidate_count
api_request_count
api_error_count
scan_duration_ms
candidate_age_seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Logging the number of candidates rejected by each filter is especially valuable.&lt;/p&gt;

&lt;p&gt;If liquidity filtering suddenly eliminates 99% of markets, you want to know whether the market changed—or your API parsing broke.&lt;/p&gt;




&lt;h2&gt;
  
  
  16. Practical Example: Building a Shortlist
&lt;/h2&gt;

&lt;p&gt;Imagine a strategy only wants markets that satisfy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;active = true
closed = false
liquidity &amp;gt;= configured threshold
volume &amp;gt;= configured threshold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner creates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;123&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Example question?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;80000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;456&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Another question?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;liquidity&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;volume&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;150000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next component can then request detailed market state.&lt;/p&gt;

&lt;p&gt;This architecture is much easier to reason about than a single Python script that simultaneously discovers markets, calculates signals, manages risk, signs orders, and submits trades.&lt;/p&gt;




&lt;h2&gt;
  
  
  17. Advanced Improvements
&lt;/h2&gt;

&lt;p&gt;Once the basic scanner works, several upgrades become possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tag-aware scanning
&lt;/h3&gt;

&lt;p&gt;Use market tags to build specialized scanners for categories such as politics, crypto, sports, or economics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expiration-aware scanning
&lt;/h3&gt;

&lt;p&gt;Prioritize markets based on time remaining until their end date.&lt;/p&gt;

&lt;h3&gt;
  
  
  Spread filtering
&lt;/h3&gt;

&lt;p&gt;Exclude markets where the executable spread is too wide for your model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Depth-aware filtering
&lt;/h3&gt;

&lt;p&gt;A market can appear liquid while having insufficient depth at the price your strategy needs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Model-driven scanning
&lt;/h3&gt;

&lt;p&gt;Instead of simply ranking markets by volume, calculate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model_probability - market_probability
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then investigate candidates with sufficiently large discrepancies.&lt;/p&gt;

&lt;p&gt;That discrepancy is &lt;strong&gt;not automatically profit&lt;/strong&gt;. It is a research signal that still requires execution and risk analysis.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real-time architecture
&lt;/h3&gt;

&lt;p&gt;For continuously updating systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A[Market Discovery] --&amp;gt; B[Candidate Registry]
    B --&amp;gt; C[WebSocket Subscriptions]
    C --&amp;gt; D[Live Order Book State]
    D --&amp;gt; E[Feature Engine]
    E --&amp;gt; F[Signal Engine]
    F --&amp;gt; G[Risk Engine]
    G --&amp;gt; H[Execution]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The scanner becomes the front door to the trading system rather than the entire system.&lt;/p&gt;




&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a Polymarket market scanner?
&lt;/h3&gt;

&lt;p&gt;A Polymarket market scanner is software that discovers and filters markets according to predefined conditions such as activity, liquidity, volume, price, expiration, or order-book characteristics.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a Polymarket scanner need API credentials?
&lt;/h3&gt;

&lt;p&gt;Not for public market discovery. Polymarket documents public market data as accessible without authentication. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use the Gamma API or CLOB API?
&lt;/h3&gt;

&lt;p&gt;Use Gamma for broad market discovery and metadata, then use CLOB data when you need current prices or order-book information. ([Polymarket Documentation][1])&lt;/p&gt;

&lt;h3&gt;
  
  
  Can a scanner identify profitable trades?
&lt;/h3&gt;

&lt;p&gt;It can identify candidates that satisfy a model's conditions, but it cannot guarantee profitability. Execution costs, liquidity, model error, and market risk remain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should a scanner use REST or WebSockets?
&lt;/h3&gt;

&lt;p&gt;REST is appropriate for discovery and periodic scans. WebSockets are useful when the system needs continuously updated order-book and market-state information. ([Polymarket Documentation][4])&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;A good &lt;strong&gt;Polymarket market scanner&lt;/strong&gt; is not complicated because of its number of lines of Python. It is complicated because it sits at the boundary between market discovery, real-time data, quantitative filtering, and eventually execution.&lt;/p&gt;

&lt;p&gt;The strongest architecture is therefore modular:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;discover → filter → enrich → rank → evaluate → execute&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Start with public market data. Use keyset pagination for broad discovery. Reduce the universe before requesting expensive real-time data. Keep your scanner read-only until its data pipeline is reliable. Then add order-book state, quantitative models, risk controls, and execution as independent components.&lt;/p&gt;

&lt;p&gt;That approach produces infrastructure that can evolve from a simple research script into a serious automated trading system without turning the scanner itself into an untestable monolith.&lt;/p&gt;




&lt;h2&gt;
  
  
  Related Articles
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Build a Polymarket Trading Bot in Python&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;code&gt;Polymarket trading bot in Python&lt;/code&gt;&lt;br&gt;
Why: Natural next step after market discovery.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket API Explained for Developers&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;code&gt;Polymarket API&lt;/code&gt;&lt;br&gt;
Why: Explains the API architecture behind the scanner.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;How to Read Polymarket Order Books in Python&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;code&gt;Polymarket order book data&lt;/code&gt;&lt;br&gt;
Why: Extends candidate discovery into executable market-state analysis.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Building a Real-Time Polymarket WebSocket Client&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;code&gt;Polymarket WebSocket market data&lt;/code&gt;&lt;br&gt;
Why: Moves from periodic scanning to streaming data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket Trading Bot Architecture&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;code&gt;Polymarket trading bot architecture&lt;/code&gt;&lt;br&gt;
Why: Shows how scanners fit into larger trading infrastructure.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Polymarket Probability and Fair-Value Modeling&lt;/strong&gt;&lt;br&gt;
Anchor: &lt;code&gt;Polymarket fair-value model&lt;/code&gt;&lt;br&gt;
Why: Connects market selection with quantitative evaluation.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Useful Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket&lt;/a&gt; — The trading platform and market interface.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Documentation&lt;/a&gt; — Primary technical reference for APIs, SDKs, WebSockets, and market infrastructure. ([Polymarket Documentation][9])&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/market-data/overview?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Market Data Overview&lt;/a&gt; — Overview of Gamma, CLOB, and Data APIs and how market data is organized. ([Polymarket Documentation][1])&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/api-reference/markets/list-markets-keyset-pagination?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;List Markets — Keyset Pagination&lt;/a&gt; — Relevant reference for implementing the scanner's market-discovery loop. ([Polymarket Documentation][2])&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Polymarket/py-sdk?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Python SDK&lt;/a&gt; — Official unified Python SDK; currently documented as beta. ([GitHub][7])&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/Polymarket?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket GitHub organization&lt;/a&gt; — Official developer repositories and tooling. ([GitHub][10])&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://x.com/Polymarket?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket on X&lt;/a&gt; — Official Polymarket account.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.polymarket.com/changelog?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket changelog&lt;/a&gt; — Useful for tracking API and platform changes. ([Polymarket Documentation][6])&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I could not verify the specific Medium, DEV.to, or YouTube resources belonging to your content series from the information provided, so I have intentionally &lt;strong&gt;not fabricated those URLs&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  About the Author
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Bo$onaX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
X: [&lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;]&lt;br&gt;
Youtube: [&lt;a href="https://youtube.com/@bosonax" rel="noopener noreferrer"&gt;https://youtube.com/@bosonax&lt;/a&gt;]&lt;br&gt;
Telegram: [&lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>ai</category>
      <category>crypto</category>
      <category>polymarket</category>
      <category>strategy</category>
    </item>
    <item>
      <title>Polymarket API Explained for Developers: CLOB, Gamma, Data &amp; WebSockets</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Wed, 19 Aug 2026 15:13:31 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-api-explained-for-developers-clob-gamma-data-websockets-2apd</link>
      <guid>https://dev.to/xniiinx/polymarket-api-explained-for-developers-clob-gamma-data-websockets-2apd</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Polymarket API Explained: CLOB, Gamma, Data &amp;amp; WebSockets&lt;/p&gt;

&lt;p&gt;Learn the Polymarket API from a developer’s perspective: Gamma, CLOB, Data API, WebSockets, authentication, Python SDKs, rate limits and bots.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Polymarket API Explained for Developers
&lt;/h1&gt;

&lt;p&gt;If you are building a Polymarket trading bot, analytics system, market scanner, dashboard, or automated execution engine, the difficult part is not sending an HTTP request.&lt;/p&gt;

&lt;p&gt;The difficult part is understanding &lt;strong&gt;which Polymarket API should own which responsibility&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Polymarket currently exposes several developer surfaces: Gamma for market discovery and metadata, the CLOB API for prices, order books and trading, the Data API for positions and historical activity, and WebSocket channels for real-time updates. The official documentation also provides SDKs for interacting with these systems.&lt;/p&gt;

&lt;p&gt;There is another important reason to understand the architecture before writing a bot: &lt;strong&gt;Polymarket's production trading stack changed substantially in 2026&lt;/strong&gt;. CLOB V2 went live on the production CLOB host in April 2026, and legacy V1 SDKs and V1-signed orders are no longer supported in production.&lt;/p&gt;

&lt;p&gt;This guide builds a developer-oriented mental model of the current Polymarket API, shows how the different services fit together, demonstrates Python integration patterns, and explains what changes when you move from a research script to a production trading system.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Technical note:&lt;/strong&gt; Polymarket's APIs evolve. Endpoint names, SDK surfaces, limits, and authentication requirements should always be checked against the current official documentation before deploying a live trading system.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  What You'll Learn
&lt;/h2&gt;

&lt;p&gt;By the end of this guide, you will understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How the Polymarket API architecture is divided&lt;/li&gt;
&lt;li&gt;When to use Gamma API versus CLOB API versus Data API&lt;/li&gt;
&lt;li&gt;How market IDs, condition IDs, and token IDs relate&lt;/li&gt;
&lt;li&gt;How to retrieve market metadata with Python&lt;/li&gt;
&lt;li&gt;How to inspect prices and order books&lt;/li&gt;
&lt;li&gt;How Polymarket WebSockets differ from REST polling&lt;/li&gt;
&lt;li&gt;How CLOB authentication works&lt;/li&gt;
&lt;li&gt;The distinction between L1 wallet authentication and L2 API credentials&lt;/li&gt;
&lt;li&gt;How the current CLOB V2 architecture affects integrations&lt;/li&gt;
&lt;li&gt;How to design retries, rate-limit handling, and reconnect logic&lt;/li&gt;
&lt;li&gt;How to structure a production trading bot around the API&lt;/li&gt;
&lt;li&gt;What to log and monitor&lt;/li&gt;
&lt;li&gt;Which security mistakes can turn a bot into a liability&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  1. The Polymarket API Architecture
&lt;/h1&gt;

&lt;p&gt;The first mistake developers make is thinking of the &lt;strong&gt;Polymarket API&lt;/strong&gt; as one REST API.&lt;/p&gt;

&lt;p&gt;It is better to think of it as a collection of services with different jobs.&lt;/p&gt;

&lt;p&gt;At a high level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                         Your Application
                                |
              +-----------------+-----------------+
              |                 |                 |
              v                 v                 v
        Gamma API           CLOB API          Data API
        Discovery        Prices / Books      Positions /
        Metadata          Trading            Analytics
              |                 |                 |
              +-----------------+-----------------+
                                |
                           WebSocket
                         Real-time events
                                |
                                v
                       Trading / Strategy
                                |
                                v
                         Polygon settlement
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polymarket's official market-data documentation describes three primary REST surfaces:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Primary responsibility&lt;/th&gt;
&lt;th&gt;Typical use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Gamma API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Events, markets and discovery&lt;/td&gt;
&lt;td&gt;Find markets and metadata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CLOB API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prices, order books and trading&lt;/td&gt;
&lt;td&gt;Trading and execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Data API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Positions, trades and analytics&lt;/td&gt;
&lt;td&gt;Portfolio and historical analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;WebSocket&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Streaming market/user events&lt;/td&gt;
&lt;td&gt;Real-time systems&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The official documentation explicitly separates Gamma, CLOB and Data API functionality in this way.&lt;/p&gt;

&lt;p&gt;That separation should also appear in your application architecture.&lt;/p&gt;

&lt;p&gt;A trading bot should generally &lt;strong&gt;not&lt;/strong&gt; use the same request loop for market discovery, order-book updates, account reconciliation, and order execution.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Gamma API: Market Discovery and Metadata
&lt;/h1&gt;

&lt;p&gt;The Gamma API is where you typically start.&lt;/p&gt;

&lt;p&gt;Its production base URL is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://gamma-api.polymarket.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Gamma exposes market and event discovery endpoints such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /events
GET /events/{id}
GET /markets
GET /markets/{id}
GET /public-search
GET /tags
GET /series
GET /sports
GET /teams
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These endpoints are public market-data endpoints and do not require wallet authentication.&lt;/p&gt;

&lt;p&gt;For example, retrieving a market by ID uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://gamma-api.polymarket.com/markets/{id}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and the response contains metadata including the question, condition ID, slug, dates, category and other market attributes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Gamma matters to a trading bot
&lt;/h3&gt;

&lt;p&gt;Suppose your strategy trades only:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;active markets,&lt;/li&gt;
&lt;li&gt;markets closing within a particular time window,&lt;/li&gt;
&lt;li&gt;markets containing a specific category,&lt;/li&gt;
&lt;li&gt;markets with sufficient liquidity,&lt;/li&gt;
&lt;li&gt;or markets matching a particular question pattern.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You should solve that filtering problem before your execution engine ever considers placing an order.&lt;/p&gt;

&lt;p&gt;A useful architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gamma
  |
  | market discovery
  v
Market Registry
  |
  | eligible token IDs
  v
Strategy Engine
  |
  v
CLOB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This avoids repeatedly querying metadata during latency-sensitive execution.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Market IDs, Condition IDs and Token IDs
&lt;/h1&gt;

&lt;p&gt;This is one of the most important concepts for Polymarket developers.&lt;/p&gt;

&lt;p&gt;A market can have multiple identifiers representing different layers of the system.&lt;/p&gt;

&lt;p&gt;You will encounter concepts such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;market ID&lt;/li&gt;
&lt;li&gt;event ID&lt;/li&gt;
&lt;li&gt;condition ID&lt;/li&gt;
&lt;li&gt;token ID / asset ID&lt;/li&gt;
&lt;li&gt;slug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not treat these as interchangeable strings.&lt;/p&gt;

&lt;p&gt;The Gamma API is primarily concerned with market and event metadata. The CLOB operates on &lt;strong&gt;outcome token IDs&lt;/strong&gt; when you request prices, order books, or create orders.&lt;/p&gt;

&lt;p&gt;The official market-data documentation describes a market as mapping to CLOB token IDs, a market address, a question ID and a condition ID.&lt;/p&gt;

&lt;p&gt;For a binary market, your application will typically need to identify the appropriate outcome token before asking the CLOB for its book.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Event
  |
  +-- Market
       |
       +-- Condition ID
       |
       +-- YES token ID
       |
       +-- NO token ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction matters because an order-book request needs an &lt;strong&gt;asset/token identifier&lt;/strong&gt;, not merely the human-readable question.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical rule
&lt;/h3&gt;

&lt;p&gt;Store identifiers explicitly in your internal model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;market_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;condition_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;yes_token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;no_token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not scatter raw IDs throughout your strategy code.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. CLOB API: The Trading Layer
&lt;/h1&gt;

&lt;p&gt;The CLOB is the part of the Polymarket API that matters most when your application actually needs to trade.&lt;/p&gt;

&lt;p&gt;The production CLOB host is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://clob.polymarket.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official documentation describes Polymarket's CLOB as a hybrid-decentralized trading system: orders are matched off-chain while matched trades settle onchain. Orders are EIP-712 signed messages, and settlement occurs on Polygon.&lt;/p&gt;

&lt;p&gt;The CLOB exposes functionality for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;prices,&lt;/li&gt;
&lt;li&gt;order books,&lt;/li&gt;
&lt;li&gt;spreads,&lt;/li&gt;
&lt;li&gt;midpoint prices,&lt;/li&gt;
&lt;li&gt;historical prices,&lt;/li&gt;
&lt;li&gt;order creation,&lt;/li&gt;
&lt;li&gt;order cancellation,&lt;/li&gt;
&lt;li&gt;open orders,&lt;/li&gt;
&lt;li&gt;trades,&lt;/li&gt;
&lt;li&gt;account information,&lt;/li&gt;
&lt;li&gt;and related trading operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The public market-data surface includes endpoints such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /price
GET /prices
GET /book
POST /books
GET /prices-history
GET /midpoint
GET /spread
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;according to the current official documentation.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. Reading an Order Book
&lt;/h1&gt;

&lt;p&gt;An automated strategy should rarely make a trading decision from a single displayed price.&lt;/p&gt;

&lt;p&gt;The order book provides a more useful execution picture.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ASKS
0.63   500
0.62   350
0.61   200
----------------
0.60   250   &amp;lt;- best bid
0.59   400
0.58   700
BIDS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From this you can derive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;best bid,&lt;/li&gt;
&lt;li&gt;best ask,&lt;/li&gt;
&lt;li&gt;spread,&lt;/li&gt;
&lt;li&gt;depth,&lt;/li&gt;
&lt;li&gt;available size,&lt;/li&gt;
&lt;li&gt;estimated execution price,&lt;/li&gt;
&lt;li&gt;and potential slippage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CLOB exposes &lt;code&gt;/book&lt;/code&gt; for an individual token and &lt;code&gt;/books&lt;/code&gt; for multiple books.&lt;/p&gt;

&lt;p&gt;A simple read-only request can be implemented without exposing any trading credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;


&lt;span class="n"&gt;CLOB_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://clob.polymarket.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CLOB_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_TOKEN_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;YOUR_TOKEN_ID&lt;/code&gt; with a real token ID obtained from your market-discovery workflow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do not assume the first price is the executable price
&lt;/h3&gt;

&lt;p&gt;A common bot-design error is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_price&lt;/span&gt;&lt;span class="p"&gt;(...)&lt;/span&gt;
&lt;span class="nf"&gt;buy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A production execution engine should instead reason about:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signal
  |
  v
target price
  |
  v
current book
  |
  +--&amp;gt; spread
  |
  +--&amp;gt; available depth
  |
  +--&amp;gt; expected fill price
  |
  +--&amp;gt; slippage
  |
  v
risk checks
  |
  v
order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The distinction becomes especially important when the strategy trades meaningful size.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. Price, Midpoint and Spread
&lt;/h1&gt;

&lt;p&gt;The CLOB provides separate concepts for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;price,&lt;/li&gt;
&lt;li&gt;midpoint,&lt;/li&gt;
&lt;li&gt;spread,&lt;/li&gt;
&lt;li&gt;order book.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not collapse them into one variable called &lt;code&gt;market_price&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://clob.polymarket.com&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="n"&gt;token_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_TOKEN_ID&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;midpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/midpoint&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="n"&gt;spread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/spread&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Price:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Midpoint:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;midpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Spread:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;spread&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For strategy research, these values answer different questions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Price&lt;/strong&gt; can be useful for a specific side.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Midpoint&lt;/strong&gt; gives you a reference between the current bid and ask.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spread&lt;/strong&gt; tells you something about the cost of crossing the market.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Order-book depth&lt;/strong&gt; tells you whether your intended size can actually be executed near the displayed price.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. Tick Size and Fee Information
&lt;/h1&gt;

&lt;p&gt;A robust trading engine should not hard-code assumptions about every market.&lt;/p&gt;

&lt;p&gt;The CLOB provides endpoints for market-specific properties such as tick size and fee rate.&lt;/p&gt;

&lt;p&gt;For example, the current documentation exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /tick-size
GET /fee-rate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with &lt;code&gt;token_id&lt;/code&gt; identifying the relevant asset.&lt;/p&gt;

&lt;p&gt;The tick-size endpoint returns a &lt;code&gt;minimum_tick_size&lt;/code&gt;, while the fee-rate endpoint returns a base fee rate in basis points.&lt;/p&gt;

&lt;p&gt;That means an execution engine should conceptually do this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market selected
      |
      v
fetch market parameters
      |
      +--&amp;gt; tick size
      |
      +--&amp;gt; fee information
      |
      +--&amp;gt; neg-risk / market configuration
      |
      v
validate order
      |
      v
sign
      |
      v
submit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not assume every market can accept arbitrary decimal prices.&lt;/p&gt;

&lt;p&gt;The official Python SDK changelog also documents validation around prices being multiples of the tick size.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. Data API: Positions, Trades and Analytics
&lt;/h1&gt;

&lt;p&gt;The Data API answers a different class of questions.&lt;/p&gt;

&lt;p&gt;Its production host is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://data-api.polymarket.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current documentation includes endpoints for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /positions
GET /closed-positions
GET /activity
GET /value
GET /oi
GET /holders
GET /trades
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are intended for positions, activity, market analytics and historical trade information.&lt;/p&gt;

&lt;p&gt;For example, current positions can be requested through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://data-api.polymarket.com/positions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response contains fields such as asset, condition ID, size, average price, current value, PnL-related fields, outcome and market metadata.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not use the CLOB for everything?
&lt;/h3&gt;

&lt;p&gt;Because the services answer different questions.&lt;/p&gt;

&lt;p&gt;A clean bot architecture might use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gamma
  -&amp;gt; What markets exist?

CLOB
  -&amp;gt; What can I trade right now?

Data API
  -&amp;gt; What positions/activity do I have?

WebSocket
  -&amp;gt; What changed since the last event?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That division is much easier to maintain than a single giant API wrapper.&lt;/p&gt;




&lt;h1&gt;
  
  
  9. WebSockets: Stop Polling When You Need Real-Time State
&lt;/h1&gt;

&lt;p&gt;REST is excellent for snapshots.&lt;/p&gt;

&lt;p&gt;It is not always the right abstraction for continuous state.&lt;/p&gt;

&lt;p&gt;Polymarket provides public WebSocket market channels for real-time order-book, price and market-lifecycle updates. The current market channel includes book snapshots, price changes, last-trade-price events and tick-size changes.&lt;/p&gt;

&lt;p&gt;The market channel is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/wss/market
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A subscription contains asset IDs.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REST
 |
 +--&amp;gt; initial snapshot
 |
 v
WebSocket
 |
 +--&amp;gt; book update
 +--&amp;gt; price change
 +--&amp;gt; trade
 +--&amp;gt; tick-size change
 +--&amp;gt; lifecycle event
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official market-channel documentation also specifies a client heartbeat: send a ping every 10 seconds and expect a pong response.&lt;/p&gt;

&lt;p&gt;That detail matters in production.&lt;/p&gt;

&lt;p&gt;A WebSocket client should not simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="n"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recv&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;forever.&lt;/p&gt;

&lt;p&gt;It needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;heartbeat handling,&lt;/li&gt;
&lt;li&gt;reconnect logic,&lt;/li&gt;
&lt;li&gt;subscription restoration,&lt;/li&gt;
&lt;li&gt;sequence/state validation where applicable,&lt;/li&gt;
&lt;li&gt;logging,&lt;/li&gt;
&lt;li&gt;connection metrics,&lt;/li&gt;
&lt;li&gt;and a recovery path back to REST snapshots.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  10. User WebSocket Channel
&lt;/h1&gt;

&lt;p&gt;For authenticated applications, Polymarket also provides a user WebSocket channel.&lt;/p&gt;

&lt;p&gt;The user channel can stream order and trade events. Its subscription uses API credentials and supports market subscriptions.&lt;/p&gt;

&lt;p&gt;This is particularly useful for execution engines.&lt;/p&gt;

&lt;p&gt;Instead of repeatedly asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Is my order filled?"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;your application can maintain an event-driven order state.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ORDER_SUBMITTED
      |
      v
ORDER_ACKNOWLEDGED
      |
      v
LIVE
      |
      +--------+
      |        |
      v        v
PARTIAL    CANCELLED
FILL          |
      |        |
      v        |
FILLED &amp;lt;-------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The event stream should update your local order state, while periodic reconciliation against the REST API protects against missed messages or connection failures.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. The Authentication Model: L1 vs L2
&lt;/h1&gt;

&lt;p&gt;One of the most important pieces of the Polymarket API is its authentication model.&lt;/p&gt;

&lt;p&gt;The current CLOB documentation describes two authentication levels:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Level&lt;/th&gt;
&lt;th&gt;Mechanism&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;EIP-712 wallet signature&lt;/td&gt;
&lt;td&gt;Create/derive API credentials&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;L2&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;HMAC-SHA256 API credentials&lt;/td&gt;
&lt;td&gt;Authenticated trading/account requests&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The official documentation states that your private key is used to derive L2 credentials, consisting of an API key, secret and passphrase.&lt;/p&gt;

&lt;p&gt;This distinction is important because &lt;strong&gt;API credentials do not replace order signing&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For order creation, the order itself still requires an appropriate EIP-712 signature. L2 authentication authenticates the API request; it is not the same thing as authorizing the signed order.&lt;/p&gt;

&lt;p&gt;Think about it this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Wallet private key
       |
       | EIP-712 authentication
       v
L2 API credentials
       |
       | HMAC-authenticated API request
       v
CLOB
       |
       | EIP-712 signed order
       v
Order matching
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why simply obtaining an API key is not equivalent to having a complete trading integration.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. Never Put Private Keys in Source Code
&lt;/h1&gt;

&lt;p&gt;This should be non-negotiable.&lt;/p&gt;

&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;PRIVATE_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0x123...&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Better:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_PRIVATE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For local development:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;POLYMARKET_PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, use a proper secrets manager or protected environment configuration.&lt;/p&gt;

&lt;p&gt;Never commit:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;private keys,&lt;/li&gt;
&lt;li&gt;seed phrases,&lt;/li&gt;
&lt;li&gt;API secrets,&lt;/li&gt;
&lt;li&gt;passphrases,&lt;/li&gt;
&lt;li&gt;wallet credentials,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;.env&lt;/code&gt; files containing production credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A trading bot with a leaked private key is not merely a software bug. It can become a direct loss-of-funds event.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. Current SDK Situation
&lt;/h1&gt;

&lt;p&gt;This is an area where older tutorials can become dangerous.&lt;/p&gt;

&lt;p&gt;Polymarket's older &lt;code&gt;py-clob-client&lt;/code&gt; repository was archived on May 25, 2026.&lt;/p&gt;

&lt;p&gt;Polymarket now maintains an official unified Python SDK under the &lt;code&gt;polymarket-client&lt;/code&gt; package. Its repository describes it as the official Python SDK and says it provides a unified interface across public data, authenticated accounts, trading, builder attribution and wallet workflows.&lt;/p&gt;

&lt;p&gt;However, the unified SDK is explicitly marked &lt;strong&gt;beta&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That produces an important practical distinction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;New project
   |
   +--&amp;gt; Evaluate official unified Python SDK
   |
   +--&amp;gt; Verify current API surface
   |
   +--&amp;gt; Pin/test the version
   |
   +--&amp;gt; Build integration tests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For CLOB-specific integrations, the official documentation currently points developers toward the CLOB V2 Python client:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;py-clob-client-v2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The CLOB trading overview lists the Python V2 client alongside the current TypeScript and Rust clients.&lt;/p&gt;

&lt;p&gt;Do not copy an old 2025 tutorial's dependency list into a production system without checking whether it targets the current CLOB architecture.&lt;/p&gt;




&lt;h1&gt;
  
  
  14. A Minimal Python Market-Discovery Client
&lt;/h1&gt;

&lt;p&gt;For market discovery, plain HTTP is often enough.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;typing&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;


&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;__name__&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;GAMMA_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://gamma-api.polymarket.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GammaClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Any&lt;/span&gt;&lt;span class="p"&gt;]]:&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;GAMMA_URL&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/markets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unexpected Gamma API response format&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;basicConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;logging&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;INFO&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GammaClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;markets&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;markets&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market=%s question=%s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
                &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Gamma request failed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unexpected Gamma response&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is intentionally read-only.&lt;/p&gt;

&lt;p&gt;It does not require:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a private key,&lt;/li&gt;
&lt;li&gt;API credentials,&lt;/li&gt;
&lt;li&gt;a wallet,&lt;/li&gt;
&lt;li&gt;or order-signing logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes it a good first integration test.&lt;/p&gt;




&lt;h1&gt;
  
  
  15. Using the Official Unified Python SDK
&lt;/h1&gt;

&lt;p&gt;The official unified SDK currently supports a public client interface.&lt;/p&gt;

&lt;p&gt;The official repository documents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pip &lt;span class="nb"&gt;install &lt;/span&gt;polymarket-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and provides a synchronous &lt;code&gt;PublicClient&lt;/code&gt; as well as an asynchronous &lt;code&gt;AsyncPublicClient&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A basic read-only example is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PublicClient&lt;/span&gt;


&lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;PublicClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_market&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;YOUR_MARKET_SLUG&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK's public client source confirms that market lookup supports identifiers such as ID, slug, and URL.&lt;/p&gt;

&lt;p&gt;Because the unified SDK is still beta, production systems should pin the dependency, run integration tests against the exact version being deployed, and monitor the project's release notes.&lt;/p&gt;




&lt;h1&gt;
  
  
  16. Building a Production-Oriented API Layer
&lt;/h1&gt;

&lt;p&gt;Do not allow strategy code to directly construct HTTP requests.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Strategy
   |
   v
MarketService
   |
   +--&amp;gt; Gamma
   |
   +--&amp;gt; CLOB
   |
   +--&amp;gt; Data API
   |
   +--&amp;gt; WebSocket
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketService&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;gamma_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;clob_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;data_client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gamma&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gamma_client&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clob&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clob_client&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;data_client&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_market_snapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gamma&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_market&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;clob&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yes_token_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;market&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your strategy should not care whether the data came from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;requests&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;httpx&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;an SDK,&lt;/li&gt;
&lt;li&gt;a cache,&lt;/li&gt;
&lt;li&gt;or a WebSocket-maintained local book.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That separation makes later infrastructure changes much easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  17. Rate Limits Are Part of the API Contract
&lt;/h1&gt;

&lt;p&gt;A production Polymarket integration needs explicit rate-limit handling.&lt;/p&gt;

&lt;p&gt;The current official rate-limit documentation states that API limits are enforced through Cloudflare throttling and that requests exceeding limits can be delayed/queued rather than immediately rejected. The limits operate over sliding windows.&lt;/p&gt;

&lt;p&gt;Examples currently documented include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Surface&lt;/th&gt;
&lt;th&gt;Endpoint&lt;/th&gt;
&lt;th&gt;Documented limit&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gamma&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/markets&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;300 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Gamma&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/events&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;500 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/positions&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;150 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/trades&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;200 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLOB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/book&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,500 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLOB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/price&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,500 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CLOB&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/midpoint&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,500 req / 10s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The official page contains the complete current table, including trading endpoint burst and sustained limits.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do not build this:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;while True:
    GET /markets
    GET /book
    GET /price
    sleep(0.01)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build this instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Startup
  |
  +--&amp;gt; Discover markets
  |
  +--&amp;gt; Cache metadata
  |
  v
WebSocket stream
  |
  +--&amp;gt; update market state
  |
  v
Strategy
  |
  +--&amp;gt; request REST snapshot only when required
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Streaming plus caching is usually a much cleaner architecture than aggressive REST polling.&lt;/p&gt;




&lt;h1&gt;
  
  
  18. Retry Strategy
&lt;/h1&gt;

&lt;p&gt;Retries should distinguish between transient infrastructure errors and permanent application errors.&lt;/p&gt;

&lt;p&gt;A basic pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;


&lt;span class="n"&gt;RETRYABLE_STATUS_CODES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;429&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;502&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;503&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;504&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_with_retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;10.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempts&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status_code&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;RETRYABLE_STATUS_CODES&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;

        &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="k"&gt;raise&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;attempts&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="n"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="mf"&gt;5.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="mf"&gt;0.25&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;delay&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unreachable&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But retries require more thought for &lt;strong&gt;trading operations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A retry of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET /book
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is usually straightforward.&lt;/p&gt;

&lt;p&gt;A retry of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be materially different.&lt;/p&gt;

&lt;p&gt;Before automatically retrying an order submission, your system should determine whether the original request was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rejected,&lt;/li&gt;
&lt;li&gt;accepted,&lt;/li&gt;
&lt;li&gt;processed but response lost,&lt;/li&gt;
&lt;li&gt;or actually matched.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blindly submitting the same trading instruction again can create duplicate exposure.&lt;/p&gt;




&lt;h1&gt;
  
  
  19. Idempotency and Order State
&lt;/h1&gt;

&lt;p&gt;A production execution engine should maintain its own order lifecycle.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;strategy signal
      |
      v
risk approval
      |
      v
order intent created
      |
      v
signed order
      |
      v
submission
      |
      v
local state = SUBMITTED
      |
      +--&amp;gt; WebSocket event
      |
      +--&amp;gt; REST reconciliation
      |
      v
LIVE / PARTIAL / FILLED / CANCELLED / REJECTED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The database should store enough information to reconstruct what happened.&lt;/p&gt;

&lt;p&gt;At minimum, consider persisting:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;client order identifier
market
token ID
side
requested price
requested size
order type
creation timestamp
submission timestamp
exchange order ID
status
matched size
average execution price
error code
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes extremely valuable when debugging a bot after a network failure.&lt;/p&gt;




&lt;h1&gt;
  
  
  20. WebSocket + REST Reconciliation
&lt;/h1&gt;

&lt;p&gt;Never assume a WebSocket connection is perfect.&lt;/p&gt;

&lt;p&gt;A robust system treats WebSocket events as a fast state-update mechanism and REST as a reconciliation mechanism.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                +----------------+
                | Local State DB |
                +-------+--------+
                        ^
                        |
            +-----------+-----------+
            |                       |
            |                       |
      WebSocket                 REST
      real-time                 snapshot
      updates                   reconciliation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the WebSocket disconnects:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;mark the stream stale;&lt;/li&gt;
&lt;li&gt;stop making decisions that depend on unknown state if necessary;&lt;/li&gt;
&lt;li&gt;reconnect;&lt;/li&gt;
&lt;li&gt;restore subscriptions;&lt;/li&gt;
&lt;li&gt;obtain a fresh snapshot;&lt;/li&gt;
&lt;li&gt;reconcile local state;&lt;/li&gt;
&lt;li&gt;resume normal processing.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is far safer than simply reconnecting and continuing from stale memory.&lt;/p&gt;




&lt;h1&gt;
  
  
  21. Practical Example: Market Scanner
&lt;/h1&gt;

&lt;p&gt;Let's build a small research-oriented scanner.&lt;/p&gt;

&lt;p&gt;The objective is not to trade.&lt;/p&gt;

&lt;p&gt;It will:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;query Gamma;&lt;/li&gt;
&lt;li&gt;identify markets;&lt;/li&gt;
&lt;li&gt;obtain token IDs;&lt;/li&gt;
&lt;li&gt;query CLOB market data;&lt;/li&gt;
&lt;li&gt;calculate a simple spread metric;&lt;/li&gt;
&lt;li&gt;print candidates.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;__future__&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;annotations&lt;/span&gt;

&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;


&lt;span class="n"&gt;GAMMA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://gamma-api.polymarket.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;CLOB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;https://clob.polymarket.com&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;session&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;kwargs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;GAMMA&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/markets&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;limit&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;isinstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;list&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;data&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;CLOB&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;/book&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;token_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;best_prices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;bids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="n"&gt;asks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;bids&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;asks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;bids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;level&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;level&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;asks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;best_bid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt;


&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;get_markets&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;question&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;question&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;# The exact field containing outcome/token information
&lt;/span&gt;    &lt;span class="c1"&gt;# should be validated against the current Gamma response
&lt;/span&gt;    &lt;span class="c1"&gt;# for the markets you intend to support.
&lt;/span&gt;    &lt;span class="n"&gt;token_ids&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;clobTokenIds&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;token_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;continue&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;first_token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;token_ids&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;first_token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="n"&gt;bid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;best_prices&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;bid&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;ask&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;continue&lt;/span&gt;

        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;  bid=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;bid&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; ask=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;spread=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;ask&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;bid&lt;/span&gt;&lt;span class="si"&gt;:&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nf"&gt;except &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RequestException&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;TypeError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Skipping market: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;exc&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is intentionally a &lt;strong&gt;research example&lt;/strong&gt;, not a production trading engine.&lt;/p&gt;

&lt;p&gt;The important engineering idea is the separation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gamma -&amp;gt; identify candidate
CLOB  -&amp;gt; inspect execution conditions
Strategy -&amp;gt; decide
Risk -&amp;gt; approve/reject
Execution -&amp;gt; trade
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  22. What a Real Trading Bot Should Look Like
&lt;/h1&gt;

&lt;p&gt;A production Polymarket bot should be closer to this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A[Gamma Market Discovery] --&amp;gt; B[Market Registry]
    B --&amp;gt; C[Eligibility Filter]

    C --&amp;gt; D[WebSocket Market Stream]
    D --&amp;gt; E[Local Market State]

    E --&amp;gt; F[Strategy Engine]
    F --&amp;gt; G[Risk Engine]

    G --&amp;gt;|Approved| H[Execution Engine]
    G --&amp;gt;|Rejected| I[Log Decision]

    H --&amp;gt; J[CLOB V2]
    J --&amp;gt; K[Order Events]

    K --&amp;gt; L[Order State Store]
    L --&amp;gt; M[Portfolio / Position Reconciliation]

    N[Data API] --&amp;gt; M
    M --&amp;gt; G

    O[Monitoring] --&amp;gt; D
    O --&amp;gt; H
    O --&amp;gt; M
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture creates explicit boundaries between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;discovery,&lt;/li&gt;
&lt;li&gt;market data,&lt;/li&gt;
&lt;li&gt;strategy,&lt;/li&gt;
&lt;li&gt;risk,&lt;/li&gt;
&lt;li&gt;execution,&lt;/li&gt;
&lt;li&gt;portfolio state,&lt;/li&gt;
&lt;li&gt;and observability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That separation is more important than whether your strategy is 100 lines or 10,000 lines.&lt;/p&gt;




&lt;h1&gt;
  
  
  23. Performance Considerations
&lt;/h1&gt;

&lt;p&gt;Performance is not simply about making HTTP requests faster.&lt;/p&gt;

&lt;p&gt;For an automated trading system, the relevant pipeline is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market event
   ↓
network transport
   ↓
message parsing
   ↓
state update
   ↓
strategy calculation
   ↓
risk checks
   ↓
order creation
   ↓
signature
   ↓
submission
   ↓
matching
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optimizing only one stage can produce little improvement if another stage dominates the path.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use WebSockets for continuously changing state
&lt;/h3&gt;

&lt;p&gt;If you need continuous order-book updates, streaming is generally more appropriate than repeatedly requesting snapshots.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep market metadata local
&lt;/h3&gt;

&lt;p&gt;Do not repeatedly retrieve the same market description every time a price changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Precompute strategy state
&lt;/h3&gt;

&lt;p&gt;If your strategy repeatedly calculates the same features, maintain incremental state rather than rebuilding the entire dataset.&lt;/p&gt;

&lt;h3&gt;
  
  
  Separate hot and cold paths
&lt;/h3&gt;

&lt;p&gt;A useful distinction:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cold path&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;market discovery,&lt;/li&gt;
&lt;li&gt;historical analysis,&lt;/li&gt;
&lt;li&gt;configuration,&lt;/li&gt;
&lt;li&gt;metadata refresh.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Hot path&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;order-book events,&lt;/li&gt;
&lt;li&gt;signal evaluation,&lt;/li&gt;
&lt;li&gt;risk checks,&lt;/li&gt;
&lt;li&gt;order submission,&lt;/li&gt;
&lt;li&gt;order-state updates.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture lets you optimize the latency-sensitive portion without turning the entire codebase into a low-level networking project.&lt;/p&gt;




&lt;h1&gt;
  
  
  24. Do Not Confuse Latency With Edge
&lt;/h1&gt;

&lt;p&gt;A fast API client does not automatically create a profitable trading strategy.&lt;/p&gt;

&lt;p&gt;Even if your infrastructure reacts quickly, you still face:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spread,&lt;/li&gt;
&lt;li&gt;slippage,&lt;/li&gt;
&lt;li&gt;liquidity constraints,&lt;/li&gt;
&lt;li&gt;adverse selection,&lt;/li&gt;
&lt;li&gt;fees where applicable,&lt;/li&gt;
&lt;li&gt;market impact,&lt;/li&gt;
&lt;li&gt;stale information,&lt;/li&gt;
&lt;li&gt;model error,&lt;/li&gt;
&lt;li&gt;execution uncertainty,&lt;/li&gt;
&lt;li&gt;resolution risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The correct optimization target is therefore not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Make the bot as fast as possible."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Make the complete decision-to-execution pipeline reliable enough that the strategy's assumptions remain valid."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Speed is one component of execution quality.&lt;/p&gt;




&lt;h1&gt;
  
  
  25. Security Architecture
&lt;/h1&gt;

&lt;p&gt;A trading system should have at least three security boundaries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boundary 1: Secrets
&lt;/h3&gt;

&lt;p&gt;Private keys and API secrets belong in a secrets-management layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boundary 2: Strategy
&lt;/h3&gt;

&lt;p&gt;Strategy code should not automatically have permission to transfer arbitrary funds or modify infrastructure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boundary 3: Execution
&lt;/h3&gt;

&lt;p&gt;The execution engine should enforce limits independently of strategy code.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RiskLimits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;max_order_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;max_position_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;max_daily_loss&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
    &lt;span class="n"&gt;max_open_orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;approve_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_order_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;projected_position&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;limits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_position_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The point is not that these exact limits are appropriate.&lt;/p&gt;

&lt;p&gt;The point is that &lt;strong&gt;risk controls should not depend on the strategy remembering to apply them&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  26. Geographic and Account Constraints
&lt;/h1&gt;

&lt;p&gt;API access does not mean every user or institution can necessarily trade every product.&lt;/p&gt;

&lt;p&gt;Polymarket's documentation includes geographic restrictions and eligibility requirements, and developers should validate the applicable restrictions for their users and deployment. The institutional site also states that institutional eligibility depends on jurisdiction.&lt;/p&gt;

&lt;p&gt;Do not build an application that assumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API accessible = trading permitted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are different questions.&lt;/p&gt;

&lt;p&gt;Your onboarding flow should validate the applicable account, geographic and product restrictions before attempting live trading.&lt;/p&gt;




&lt;h1&gt;
  
  
  27. Failure Modes You Should Expect
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Failure 1: Using an outdated SDK
&lt;/h2&gt;

&lt;p&gt;Older tutorials may reference the archived &lt;code&gt;py-clob-client&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; verify the current CLOB V2 documentation and official SDK repositories before installing dependencies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 2: Treating a market ID as a token ID
&lt;/h2&gt;

&lt;p&gt;The CLOB's price and order-book operations operate on asset/token identifiers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; explicitly maintain the mapping between market metadata and CLOB token IDs.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 3: Polling everything
&lt;/h2&gt;

&lt;p&gt;A bot that repeatedly requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;markets
prices
books
positions
orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can become unnecessarily expensive and difficult to scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; cache metadata, use streaming where appropriate, and use REST for snapshots/reconciliation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 4: Retrying POST blindly
&lt;/h2&gt;

&lt;p&gt;If a response disappears after an order was accepted, automatically submitting the same order again can create unintended exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; implement order-state reconciliation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 5: Ignoring tick size
&lt;/h2&gt;

&lt;p&gt;A strategy can calculate a mathematically valid price that is not valid for the market's configured increment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; retrieve and enforce the applicable tick size.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 6: Hard-coding fees
&lt;/h2&gt;

&lt;p&gt;Market economics can change, and the current CLOB provides a fee-rate endpoint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; retrieve the applicable fee information and include it in execution calculations.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 7: Trusting WebSocket state forever
&lt;/h2&gt;

&lt;p&gt;A disconnected or partially processed stream can leave local state stale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; reconnect and reconcile against authoritative REST data.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure 8: Logging secrets
&lt;/h2&gt;

&lt;p&gt;Avoid:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;credentials=%s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;credentials&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request_id
market_id
token_id
latency
status
error_code
order_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but never private keys or API secrets.&lt;/p&gt;




&lt;h1&gt;
  
  
  28. Testing Strategy
&lt;/h1&gt;

&lt;p&gt;A trading integration should have several levels of testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unit tests
&lt;/h2&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;price rounding,&lt;/li&gt;
&lt;li&gt;tick-size validation,&lt;/li&gt;
&lt;li&gt;spread calculations,&lt;/li&gt;
&lt;li&gt;position calculations,&lt;/li&gt;
&lt;li&gt;risk limits,&lt;/li&gt;
&lt;li&gt;retry behavior,&lt;/li&gt;
&lt;li&gt;order-state transitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_price_matches_tick_size&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;tick_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.01&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.55&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;tick_size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tick_size&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Integration tests
&lt;/h2&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Gamma market retrieval,&lt;/li&gt;
&lt;li&gt;CLOB connectivity,&lt;/li&gt;
&lt;li&gt;WebSocket subscriptions,&lt;/li&gt;
&lt;li&gt;Data API queries,&lt;/li&gt;
&lt;li&gt;authentication,&lt;/li&gt;
&lt;li&gt;order lifecycle handling.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The official unified SDK repository itself distinguishes ordinary unit tests from opt-in integration tests and separately protects metered tests that can spend funds or mutate live state.&lt;/p&gt;

&lt;p&gt;That is a useful model for your own test suite.&lt;/p&gt;




&lt;h2&gt;
  
  
  Failure-injection tests
&lt;/h2&gt;

&lt;p&gt;Simulate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HTTP 429,&lt;/li&gt;
&lt;li&gt;HTTP 500,&lt;/li&gt;
&lt;li&gt;connection reset,&lt;/li&gt;
&lt;li&gt;malformed JSON,&lt;/li&gt;
&lt;li&gt;WebSocket disconnect,&lt;/li&gt;
&lt;li&gt;delayed response,&lt;/li&gt;
&lt;li&gt;duplicate events,&lt;/li&gt;
&lt;li&gt;missing events,&lt;/li&gt;
&lt;li&gt;stale market state.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not merely to prove that the happy path works.&lt;/p&gt;

&lt;p&gt;The goal is to discover what the bot does when the network behaves badly.&lt;/p&gt;




&lt;h1&gt;
  
  
  29. Observability
&lt;/h1&gt;

&lt;p&gt;At minimum, measure:&lt;/p&gt;

&lt;h3&gt;
  
  
  API metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request_count
error_count
429_count
latency_ms
timeout_count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WebSocket metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;connection_count
disconnect_count
reconnect_count
last_message_age
subscription_count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Trading metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orders_submitted
orders_rejected
orders_cancelled
orders_filled
partial_fills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strategy metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signals_generated
signals_rejected_by_risk
signals_executed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Portfolio metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;position_size
cash_balance
open_order_count
realized_pnl
unrealized_pnl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Polymarket status system separately tracks the Trading API, WebSocket, Markets/Position data and on-chain settlement infrastructure.&lt;/p&gt;

&lt;p&gt;Your monitoring should therefore avoid treating "Polymarket is up" as one binary condition.&lt;/p&gt;

&lt;p&gt;A bot can have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Gamma: healthy
CLOB: healthy
WebSocket: disconnected
Data API: healthy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and still be unable to operate correctly.&lt;/p&gt;




&lt;h1&gt;
  
  
  30. Production Deployment Checklist
&lt;/h1&gt;

&lt;p&gt;Before enabling live trading:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Verify the current official API documentation&lt;/li&gt;
&lt;li&gt;[ ] Confirm the SDK version&lt;/li&gt;
&lt;li&gt;[ ] Test market discovery&lt;/li&gt;
&lt;li&gt;[ ] Test token-ID mapping&lt;/li&gt;
&lt;li&gt;[ ] Validate tick size&lt;/li&gt;
&lt;li&gt;[ ] Validate fee assumptions&lt;/li&gt;
&lt;li&gt;[ ] Test order signing&lt;/li&gt;
&lt;li&gt;[ ] Test authentication&lt;/li&gt;
&lt;li&gt;[ ] Test cancellation&lt;/li&gt;
&lt;li&gt;[ ] Test WebSocket reconnection&lt;/li&gt;
&lt;li&gt;[ ] Test REST reconciliation&lt;/li&gt;
&lt;li&gt;[ ] Implement risk limits&lt;/li&gt;
&lt;li&gt;[ ] Implement rate-limit handling&lt;/li&gt;
&lt;li&gt;[ ] Implement structured logging&lt;/li&gt;
&lt;li&gt;[ ] Remove credentials from logs&lt;/li&gt;
&lt;li&gt;[ ] Run a dry-run strategy&lt;/li&gt;
&lt;li&gt;[ ] Test failure scenarios&lt;/li&gt;
&lt;li&gt;[ ] Pin dependencies&lt;/li&gt;
&lt;li&gt;[ ] Set up alerts&lt;/li&gt;
&lt;li&gt;[ ] Verify jurisdiction/account eligibility&lt;/li&gt;
&lt;li&gt;[ ] Start with deliberately constrained exposure&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  31. Advanced Improvement: Build a Local Market State Engine
&lt;/h1&gt;

&lt;p&gt;For sophisticated bots, the API client should not be the strategy's state store.&lt;/p&gt;

&lt;p&gt;Instead, maintain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;best_bid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;midpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;spread&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;last_trade_price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;updated_at&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then WebSocket messages mutate this state.&lt;/p&gt;

&lt;p&gt;Your strategy consumes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market_state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than issuing a network request every time it wants a price.&lt;/p&gt;

&lt;p&gt;This changes the architecture from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;strategy -&amp;gt; API -&amp;gt; response -&amp;gt; strategy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WebSocket -&amp;gt; local state -&amp;gt; strategy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a much stronger foundation for event-driven systems.&lt;/p&gt;




&lt;h1&gt;
  
  
  32. Advanced Improvement: Separate Decision Time From Execution Time
&lt;/h1&gt;

&lt;p&gt;Store both.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signal_created_at
risk_check_at
order_signed_at
order_submitted_at
exchange_ack_at
first_fill_at
final_fill_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then calculate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signal -&amp;gt; risk
risk -&amp;gt; signing
signing -&amp;gt; submission
submission -&amp;gt; acknowledgement
acknowledgement -&amp;gt; fill
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This lets you identify where execution actually spends time.&lt;/p&gt;

&lt;p&gt;Without these timestamps, "the bot is slow" is not an actionable diagnosis.&lt;/p&gt;




&lt;h1&gt;
  
  
  33. Advanced Improvement: Treat Market Metadata as Versioned State
&lt;/h1&gt;

&lt;p&gt;Market metadata can change.&lt;/p&gt;

&lt;p&gt;Do not assume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;load_once_forever&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A better design periodically refreshes metadata and records changes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Registry
      |
      +--&amp;gt; metadata version
      +--&amp;gt; active/closed state
      +--&amp;gt; token mapping
      +--&amp;gt; tick size
      +--&amp;gt; market configuration
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your bot behaves differently after a market configuration change, you should be able to reconstruct what metadata it was using at the time.&lt;/p&gt;




&lt;h1&gt;
  
  
  34. Advanced Improvement: Add a Kill Switch
&lt;/h1&gt;

&lt;p&gt;Every automated trading system should have a mechanism to stop opening new exposure.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TradingMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;ENABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;enabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;REDUCE_ONLY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;reduce_only&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="n"&gt;DISABLED&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;disabled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the execution layer checks the mode before accepting an order.&lt;/p&gt;

&lt;p&gt;This gives you a way to respond to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;broken market data,&lt;/li&gt;
&lt;li&gt;unexpected API behavior,&lt;/li&gt;
&lt;li&gt;strategy anomalies,&lt;/li&gt;
&lt;li&gt;excessive losses,&lt;/li&gt;
&lt;li&gt;corrupted state,&lt;/li&gt;
&lt;li&gt;infrastructure incidents.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A kill switch should be implemented &lt;strong&gt;outside the strategy itself&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  35. Current Polymarket API Architecture in One Diagram
&lt;/h1&gt;

&lt;p&gt;The entire system can be reduced to this mental model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart LR
    A[Gamma API] --&amp;gt; B[Market Registry]
    B --&amp;gt; C[Token IDs]

    C --&amp;gt; D[CLOB REST]
    C --&amp;gt; E[CLOB WebSocket]

    D --&amp;gt; F[Prices / Books]
    E --&amp;gt; F

    G[Data API] --&amp;gt; H[Positions / Trades / Analytics]

    F --&amp;gt; I[Strategy]
    H --&amp;gt; I

    I --&amp;gt; J[Risk Engine]
    J --&amp;gt; K[CLOB V2 Order Signing]
    K --&amp;gt; L[Order Submission]

    L --&amp;gt; M[User WebSocket]
    M --&amp;gt; N[Order State]

    N --&amp;gt; H
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you remember only one thing from this article, remember this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Gamma tells your application what exists. CLOB tells it what can be traded and executes orders. Data API tells it what happened to positions and activity. WebSockets tell it what is changing now.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That division is the foundation of a maintainable Polymarket integration.&lt;/p&gt;




&lt;h1&gt;
  
  
  36. Frequently Asked Questions
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What is the Polymarket API?
&lt;/h2&gt;

&lt;p&gt;The Polymarket API is the collection of developer interfaces used to access Polymarket market data, trading infrastructure, positions, analytics and real-time events. The primary REST surfaces are Gamma, CLOB and Data API, complemented by WebSocket channels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does Polymarket have a Python API?
&lt;/h2&gt;

&lt;p&gt;Yes. Polymarket maintains an official Python SDK, currently distributed as &lt;code&gt;polymarket-client&lt;/code&gt;. The project is currently in beta. Polymarket also documents a Python CLOB V2 client for CLOB trading integrations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I access Polymarket market data without authentication?
&lt;/h2&gt;

&lt;p&gt;Yes. The official market-data documentation states that public market data is available without an API key, authentication or wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which API should I use to build a trading bot?
&lt;/h2&gt;

&lt;p&gt;A typical bot will use Gamma for market discovery, CLOB for order books and execution, Data API for portfolio/activity information, and WebSockets for real-time market and user events.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are L1 and L2 authentication?
&lt;/h2&gt;

&lt;p&gt;L1 uses an EIP-712 wallet signature and is used to create or derive API credentials. L2 uses HMAC-SHA256 API credentials for authenticated API operations. Orders themselves still require appropriate wallet-based order signing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is the old &lt;code&gt;py-clob-client&lt;/code&gt; still the right SDK?
&lt;/h2&gt;

&lt;p&gt;The original &lt;code&gt;Polymarket/py-clob-client&lt;/code&gt; repository was archived in May 2026. The current documentation points developers toward the CLOB V2 client, while Polymarket also maintains a newer unified Python SDK that is currently beta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I poll the CLOB or use WebSockets?
&lt;/h2&gt;

&lt;p&gt;For continuously changing market state, WebSockets are generally the more appropriate architecture. REST remains useful for snapshots, queries and reconciliation. The official market channel provides order-book and price events.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does a faster Polymarket API integration guarantee trading profits?
&lt;/h2&gt;

&lt;p&gt;No. API performance does not guarantee profitability. Execution quality depends on liquidity, spread, slippage, fees, adverse selection, strategy quality, model risk and other factors.&lt;/p&gt;




&lt;h1&gt;
  
  
  37. Conclusion
&lt;/h1&gt;

&lt;p&gt;The most important lesson when working with the &lt;strong&gt;Polymarket API&lt;/strong&gt; is that you should stop thinking about it as a single endpoint collection.&lt;/p&gt;

&lt;p&gt;Think in systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gamma&lt;/strong&gt; handles discovery and metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLOB&lt;/strong&gt; handles prices, order books and trading.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Data API&lt;/strong&gt; handles positions, trades and analytics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WebSockets&lt;/strong&gt; handle continuously changing state.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wallet signatures and L2 credentials&lt;/strong&gt; provide the authentication and authorization layers needed for authenticated trading.&lt;/p&gt;

&lt;p&gt;And your own application must provide the parts Polymarket cannot provide for you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;strategy logic,&lt;/li&gt;
&lt;li&gt;risk controls,&lt;/li&gt;
&lt;li&gt;state management,&lt;/li&gt;
&lt;li&gt;retries,&lt;/li&gt;
&lt;li&gt;reconciliation,&lt;/li&gt;
&lt;li&gt;observability,&lt;/li&gt;
&lt;li&gt;secrets management,&lt;/li&gt;
&lt;li&gt;testing,&lt;/li&gt;
&lt;li&gt;and operational safeguards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference between a five-minute API experiment and a serious trading system is not the ability to call &lt;code&gt;GET /book&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is everything surrounding that call.&lt;/p&gt;

&lt;p&gt;If you are building a Polymarket bot, start with read-only market discovery, build a reliable local market-state layer, add WebSocket processing, implement risk controls, and only then introduce authenticated execution.&lt;/p&gt;

&lt;p&gt;That sequence keeps the system understandable—and makes failures much easier to diagnose.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Educational/trading-risk disclaimer:&lt;/strong&gt; This article is for software-development and educational purposes only. Automated prediction-market trading involves financial risk, execution risk, liquidity risk and the possibility of losing capital. API behavior and market rules can change. Always verify current Polymarket documentation and test integrations before deploying live funds.&lt;/p&gt;




&lt;h1&gt;
  
  
  Related Articles
&lt;/h1&gt;

&lt;p&gt;Build these as a topic cluster around the &lt;strong&gt;Polymarket API&lt;/strong&gt; pillar article:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;How to Build a Polymarket Trading Bot in Python&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;build a Polymarket trading bot in Python&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Converts API knowledge into a complete automation workflow.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Polymarket CLOB API: Order Books, Prices and Order Execution&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;Polymarket CLOB API&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Deepens the execution/API layer introduced here.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Polymarket Gamma API: Market Discovery and Metadata&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;Polymarket Gamma API&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Targets developers primarily interested in market discovery.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;How Polymarket WebSockets Work&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;Polymarket WebSocket API&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Expands the real-time architecture section.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Polymarket API Authentication: L1, L2 and EIP-712&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;Polymarket API authentication&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Provides a dedicated security/authentication resource.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;How to Read a Polymarket Order Book With Python&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;read a Polymarket order book with Python&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Targets a practical implementation query.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Polymarket Trading Bot Architecture&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;Polymarket trading bot architecture&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Extends the architecture diagrams into a full system-design article.&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Polymarket CLOB V2 Migration Guide for Python Developers&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Anchor: &lt;code&gt;Polymarket CLOB V2 migration&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Why: Captures developers maintaining older integrations.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  Useful Resources
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Official Polymarket
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful for understanding the live market interface and validating how market metadata is presented to users.&lt;/p&gt;

&lt;h3&gt;
  
  
  Official API Documentation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Developer Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The primary technical authority for current endpoints, authentication, SDKs, rate limits and trading behavior.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relevant API Reference
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.polymarket.com/market-data/overview?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Market Data Overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A particularly useful starting point because it explains how Gamma, CLOB and Data API responsibilities are separated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Official Python SDK
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Polymarket/py-sdk?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Python SDK on GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The official unified Python client. It is currently beta, so developers should check its release history and test the exact dependency version they deploy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Medium: Polymarket API for Developers
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://medium.com/chainstack/polymarket-api-for-developers-data-clob-and-polygon-rpc-b03e137d0500?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket API for Developers: Data, CLOB, and Polygon RPC&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A useful third-party overview of the API architecture. It should be treated as supplementary rather than authoritative; current API behavior should be verified against Polymarket's official documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  YouTube: Polymarket API With Python
&lt;/h3&gt;

&lt;p&gt;A practical third-party walkthrough covering API setup, market data, order books and Python-based trading. It was published before the current CLOB V2 migration, so developers should cross-check implementation details against current official documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Official Polymarket X
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://x.com/Polymarket/status/2024514315823509826?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket on X&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful for product and ecosystem announcements. Technical implementation details should still be verified against the official developer documentation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Official Developer Resources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/Polymarket?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket GitHub Organization&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Contains official SDKs, client libraries and developer tooling. The organization's repositories include the current Python SDK and CLOB V2 clients.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;DEV.to resource:&lt;/strong&gt; No sufficiently relevant DEV.to article was verified during research, so it is intentionally omitted rather than publishing an unverified URL.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  About the Author
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Bo$onaX&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
X: [&lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;]&lt;br&gt;
Telegram: [&lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>polymarket</category>
      <category>api</category>
      <category>websockets</category>
      <category>developers</category>
    </item>
    <item>
      <title>Polymarket Trading Bot in Python: Build Guide for 2026</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Tue, 18 Aug 2026 19:24:50 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-trading-bot-in-python-build-guide-for-2026-10ag</link>
      <guid>https://dev.to/xniiinx/polymarket-trading-bot-in-python-build-guide-for-2026-10ag</guid>
      <description>&lt;p&gt;Build a Polymarket trading bot in Python with market discovery, order books, execution, risk controls, testing, and production monitoring.&lt;/p&gt;

&lt;h1&gt;
  
  
  How to Build a Polymarket Trading Bot in Python
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Current-API note:&lt;/strong&gt; Polymarket's developer stack is evolving. This guide reflects the official documentation and repositories checked on &lt;strong&gt;August 18, 2026&lt;/strong&gt;. The official Python SDK, &lt;code&gt;polymarket-client&lt;/code&gt;, is currently in beta; the older &lt;code&gt;py-clob-client&lt;/code&gt; repository has been archived and its README explicitly says it should not be used for new integrations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A useful &lt;strong&gt;Polymarket trading bot&lt;/strong&gt; is not simply a Python loop that fetches a price and submits an order.&lt;/p&gt;

&lt;p&gt;The difficult part is building the system around the order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;discovering a market that is actually tradable,&lt;/li&gt;
&lt;li&gt;identifying the correct outcome token,&lt;/li&gt;
&lt;li&gt;maintaining a current view of the order book,&lt;/li&gt;
&lt;li&gt;converting a model signal into an executable order,&lt;/li&gt;
&lt;li&gt;respecting market tick-size and minimum-size constraints,&lt;/li&gt;
&lt;li&gt;controlling exposure,&lt;/li&gt;
&lt;li&gt;handling partial fills and cancellations,&lt;/li&gt;
&lt;li&gt;recovering from network failures,&lt;/li&gt;
&lt;li&gt;and proving that the bot behaved correctly before allowing it to trade real capital.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Polymarket's current developer documentation exposes separate market-data, trading, account, and real-time workflows, while the official Python SDK provides &lt;code&gt;PublicClient&lt;/code&gt; and &lt;code&gt;SecureClient&lt;/code&gt; abstractions for those workflows.&lt;/p&gt;

&lt;p&gt;This article builds the architecture behind a production-oriented Python bot rather than presenting a fictional "profitable strategy."&lt;/p&gt;

&lt;p&gt;The strategy used in the examples is deliberately simple: &lt;strong&gt;buy an outcome only when a hypothetical model probability exceeds the executable market price by a configurable edge threshold&lt;/strong&gt;. The edge is illustrative; it is not a claim that the strategy is profitable.&lt;/p&gt;




&lt;h1&gt;
  
  
  What You'll Learn
&lt;/h1&gt;

&lt;p&gt;By the end of this guide, you will understand how to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Choose the current Polymarket Python SDK.&lt;/li&gt;
&lt;li&gt;Discover active markets.&lt;/li&gt;
&lt;li&gt;Map a market to its outcome token IDs.&lt;/li&gt;
&lt;li&gt;Read order-book information.&lt;/li&gt;
&lt;li&gt;Build a signal engine.&lt;/li&gt;
&lt;li&gt;Add position and exposure limits.&lt;/li&gt;
&lt;li&gt;Construct and submit orders safely.&lt;/li&gt;
&lt;li&gt;Separate strategy, risk, and execution.&lt;/li&gt;
&lt;li&gt;Use WebSockets for real-time market information.&lt;/li&gt;
&lt;li&gt;Handle retries, throttling, stale data, and partial fills.&lt;/li&gt;
&lt;li&gt;Test a bot without immediately risking capital.&lt;/li&gt;
&lt;li&gt;Monitor production behavior.&lt;/li&gt;
&lt;li&gt;Extend the architecture toward market making, arbitrage research, or external-signal strategies.&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  1. Understand the Polymarket Developer Stack
&lt;/h1&gt;

&lt;p&gt;A useful mental model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    ┌─────────────────────┐
                    │   Market Discovery  │
                    │  Gamma / SDK data   │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │    Market Filter    │
                    │ tradable/liquidity  │
                    └──────────┬──────────┘
                               │
             ┌─────────────────┴─────────────────┐
             │                                   │
             ▼                                   ▼
    ┌─────────────────┐                 ┌─────────────────┐
    │ REST / snapshots│                 │    WebSocket    │
    │   market state  │                 │ live book data  │
    └────────┬────────┘                 └────────┬────────┘
             │                                   │
             └─────────────────┬─────────────────┘
                               ▼
                    ┌─────────────────────┐
                    │   Signal Engine     │
                    │ fair value / edge   │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │    Risk Engine      │
                    │ size / exposure /   │
                    │ stale-data checks   │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │ Execution Engine    │
                    │ sign / submit /     │
                    │ cancel / reconcile  │
                    └──────────┬──────────┘
                               │
                               ▼
                    ┌─────────────────────┐
                    │ Order / Position    │
                    │ State + Monitoring  │
                    └─────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polymarket's current documentation describes trading as signed orders submitted to the CLOB, followed by matching and settlement on Polygon. The trading workflow is explicitly separated into account setup, outcome selection, order placement, and order management.&lt;/p&gt;

&lt;p&gt;That separation should also exist in your code.&lt;/p&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; put market discovery, strategy logic, signing, and risk management into one 300-line &lt;code&gt;while True&lt;/code&gt; loop.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. Which Python SDK Should You Use?
&lt;/h1&gt;

&lt;p&gt;This is one of the most important current-version details.&lt;/p&gt;

&lt;p&gt;The historical &lt;code&gt;py-clob-client&lt;/code&gt; was widely used by Python bot tutorials, but the official repository was archived on &lt;strong&gt;May 25, 2026&lt;/strong&gt;, and its README now says the client is no longer maintained and should not be used for new or existing integrations. Polymarket recommends migrating to the unified &lt;code&gt;py-sdk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The new official repository is:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Polymarket/py-sdk?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Python SDK — GitHub&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It provides a unified Python interface for public data, authenticated accounts, trading, builder attribution, and wallet workflows. The package is currently beta and uses the package name &lt;code&gt;polymarket-client&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The current SDK exposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PublicClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PublicClient&lt;/code&gt; is appropriate for public market information, while &lt;code&gt;SecureClient&lt;/code&gt; is used for authenticated account, trading, and wallet workflows.&lt;/p&gt;

&lt;p&gt;The SDK currently requires Python 3.11 or newer according to its package metadata.&lt;/p&gt;

&lt;p&gt;Install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python &lt;span class="nt"&gt;-m&lt;/span&gt; venv .venv
&lt;span class="nb"&gt;source&lt;/span&gt; .venv/bin/activate

pip &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--pre&lt;/span&gt; polymarket-client
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For reproducible production deployments, pin the exact SDK version you have tested rather than floating to whatever beta release happens to be latest.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Project Structure
&lt;/h1&gt;

&lt;p&gt;A practical project can start small:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;polymarket-bot/
├── pyproject.toml
├── .env
├── .gitignore
├── src/
│   └── bot/
│       ├── __init__.py
│       ├── config.py
│       ├── market.py
│       ├── strategy.py
│       ├── risk.py
│       ├── execution.py
│       ├── state.py
│       └── main.py
└── tests/
    ├── test_strategy.py
    ├── test_risk.py
    └── test_execution.py
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key design principle is dependency direction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Data ─────► Strategy
                      │
                      ▼
                    Risk
                      │
                      ▼
                  Execution
                      │
                      ▼
                    State
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strategy should not know how a private key is stored.&lt;/p&gt;

&lt;p&gt;The execution layer should not decide whether a market is attractive.&lt;/p&gt;

&lt;p&gt;The risk layer should be able to reject a perfectly valid strategy signal.&lt;/p&gt;

&lt;p&gt;That separation makes testing dramatically easier.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Configuration and Secret Management
&lt;/h1&gt;

&lt;p&gt;Never hard-code a private key.&lt;/p&gt;

&lt;p&gt;Use environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;POLYMARKET_PRIVATE_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;POLYMARKET_DEPOSIT_WALLET&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"0x..."&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;POLYMARKET_DRY_RUN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For local development, a &lt;code&gt;.env&lt;/code&gt; file can be convenient, but it must be excluded from Git:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.env
.venv/
__pycache__/
*.pyc
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A configuration object keeps the rest of the application independent of the environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Settings&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;dry_run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;

    &lt;span class="nd"&gt;@classmethod&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;from_env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Settings&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_PRIVATE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_DEPOSIT_WALLET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_PRIVATE_KEY is missing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_DEPOSIT_WALLET is missing&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;dry_run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_DRY_RUN&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lower&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a real deployment, secrets should preferably come from a secret manager rather than a plaintext &lt;code&gt;.env&lt;/code&gt; file.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. Discover a Tradable Market
&lt;/h1&gt;

&lt;p&gt;Market discovery is the first place where many beginner bots go wrong.&lt;/p&gt;

&lt;p&gt;A market being visible does &lt;strong&gt;not&lt;/strong&gt; automatically mean your strategy should trade it.&lt;/p&gt;

&lt;p&gt;Your discovery pipeline should eventually filter for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;market status,&lt;/li&gt;
&lt;li&gt;whether orders are being accepted,&lt;/li&gt;
&lt;li&gt;outcome structure,&lt;/li&gt;
&lt;li&gt;available token IDs,&lt;/li&gt;
&lt;li&gt;minimum order size,&lt;/li&gt;
&lt;li&gt;minimum price increment,&lt;/li&gt;
&lt;li&gt;liquidity,&lt;/li&gt;
&lt;li&gt;spread,&lt;/li&gt;
&lt;li&gt;time to resolution,&lt;/li&gt;
&lt;li&gt;and whatever additional constraints your strategy requires.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The official SDK supports market lookup by ID, slug, or Polymarket URL. It also provides market objects containing trading information such as minimum tick size and minimum order size.&lt;/p&gt;

&lt;p&gt;A simple public-data example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;PublicClient&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;find_markets&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;PublicClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;list_markets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;page_size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;first_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;__name__&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;__main__&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;find_markets&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important point is that market discovery should produce &lt;strong&gt;structured market objects&lt;/strong&gt;, not arbitrary strings copied from a webpage.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. Outcome Tokens Matter More Than the Market URL
&lt;/h1&gt;

&lt;p&gt;Your trading engine ultimately needs an outcome token ID.&lt;/p&gt;

&lt;p&gt;For a binary market, the current Polymarket documentation exposes the YES and NO outcome token IDs through the market object.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;yes_token_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outcomes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;
&lt;span class="n"&gt;no_token_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;outcomes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;yes_token_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;no_token_id&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;RuntimeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Market has no tradable outcome token IDs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This distinction is critical:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market
  │
  ├── metadata
  ├── question
  ├── resolution information
  └── outcomes
        ├── YES token ID
        └── NO token ID
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not confuse:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;market ID,&lt;/li&gt;
&lt;li&gt;event ID,&lt;/li&gt;
&lt;li&gt;condition ID,&lt;/li&gt;
&lt;li&gt;outcome token ID,&lt;/li&gt;
&lt;li&gt;wallet address,&lt;/li&gt;
&lt;li&gt;order ID.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They represent different things.&lt;/p&gt;

&lt;p&gt;A robust internal model should make those distinctions explicit.&lt;/p&gt;




&lt;h1&gt;
  
  
  7. Read the Order Book
&lt;/h1&gt;

&lt;p&gt;The market price alone is not enough for an execution engine.&lt;/p&gt;

&lt;p&gt;Suppose your model says:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fair probability = 0.63
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That does not mean you can automatically buy at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.63
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to know what liquidity is actually available.&lt;/p&gt;

&lt;p&gt;The current SDK's public client exposes CLOB market data and order-book models, while Polymarket's WebSocket market channel can stream book snapshots and price changes.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your strategy should work with a normalized representation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Quote&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;best_bid&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the strategy does not care whether that quote came from REST, WebSocket state, a replay file, or a test fixture.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. The Simplest Useful Strategy Model
&lt;/h1&gt;

&lt;p&gt;A good educational bot does not need a sophisticated prediction model.&lt;/p&gt;

&lt;p&gt;Define:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model_probability = p_model
executable_price = p_market

edge = p_model - p_market
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a BUY strategy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;trade if edge &amp;gt; minimum_edge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;generate_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;minimum_edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_probability&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;minimum_edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BUY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is deliberately incomplete.&lt;/p&gt;

&lt;p&gt;A production model would also consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;spread,&lt;/li&gt;
&lt;li&gt;depth,&lt;/li&gt;
&lt;li&gt;expected slippage,&lt;/li&gt;
&lt;li&gt;fees,&lt;/li&gt;
&lt;li&gt;stale market data,&lt;/li&gt;
&lt;li&gt;probability calibration,&lt;/li&gt;
&lt;li&gt;model uncertainty,&lt;/li&gt;
&lt;li&gt;time to resolution,&lt;/li&gt;
&lt;li&gt;correlation with other positions,&lt;/li&gt;
&lt;li&gt;adverse selection,&lt;/li&gt;
&lt;li&gt;and execution probability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The purpose is to demonstrate the architecture, not imply a profitable trading signal.&lt;/p&gt;




&lt;h1&gt;
  
  
  9. Why "Model Probability &amp;gt; Market Price" Is Not Enough
&lt;/h1&gt;

&lt;p&gt;Suppose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Model probability: 0.62
Best ask:          0.59
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The apparent edge is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0.62 - 0.59 = 0.03
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is not necessarily a 3-cent profit opportunity.&lt;/p&gt;

&lt;p&gt;You still need to account for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gross edge
- trading fees
- spread effects
- expected slippage
- model error
- execution uncertainty
- adverse selection
= expected net edge
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polymarket currently charges taker fees on certain markets. The official fee documentation says fees are determined per market at match time, makers are not charged fees, and the fee formula depends on the traded share price and market-specific fee rate.&lt;/p&gt;

&lt;p&gt;That means a strategy should not use one universal hard-coded fee assumption.&lt;/p&gt;

&lt;p&gt;A safer abstraction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;expected_net_edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;model_probability&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;executable_price&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;estimated_fee&lt;/span&gt;
    &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;estimated_slippage&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only then should the risk engine evaluate the trade.&lt;/p&gt;




&lt;h1&gt;
  
  
  10. Respect Tick Size and Minimum Order Size
&lt;/h1&gt;

&lt;p&gt;One of the most common implementation errors is treating price and size as arbitrary decimals.&lt;/p&gt;

&lt;p&gt;Polymarket's current order documentation states that price must follow the market's minimum price increment and size must satisfy the market's minimum order size.&lt;/p&gt;

&lt;p&gt;The SDK's own examples obtain these values from the selected market:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimum_tick_size&lt;/span&gt;
&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimum_order_size&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than assuming universal values.&lt;/p&gt;

&lt;p&gt;A production strategy should therefore quantize its desired price.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ROUND_DOWN&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;round_down_to_tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;units&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;tick&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to_integral_value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;rounding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;ROUND_DOWN&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;units&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;tick&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;round_down_to_tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;desired_price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;trading&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimum_tick_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should perform the same kind of validation for size.&lt;/p&gt;

&lt;p&gt;Do not discover an attractive signal and only afterward find that the proposed order violates the market's trading constraints.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. Authentication With the Current Python SDK
&lt;/h1&gt;

&lt;p&gt;The current unified SDK exposes &lt;code&gt;SecureClient.create()&lt;/code&gt; for authenticated workflows.&lt;/p&gt;

&lt;p&gt;The official SDK example uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;

&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_PRIVATE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_DEPOSIT_WALLET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SDK's implementation indicates that client creation derives or validates API credentials and establishes the authenticated transports required for secure CLOB operations.&lt;/p&gt;

&lt;p&gt;A minimal setup looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;

&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_client&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;private_key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_PRIVATE_KEY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;environ&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;POLYMARKET_DEPOSIT_WALLET&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;private_key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep authentication isolated from strategy code.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. Creating an Order Is Not the Same as Posting It
&lt;/h1&gt;

&lt;p&gt;This distinction is extremely important.&lt;/p&gt;

&lt;p&gt;The official Python SDK includes a &lt;code&gt;create_limit_order()&lt;/code&gt; workflow that creates and signs an order locally. The SDK's example explicitly states that this does &lt;strong&gt;not&lt;/strong&gt; submit the order. Actual trading requires a posting method such as &lt;code&gt;place_limit_order()&lt;/code&gt; or &lt;code&gt;post_order()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That separation is valuable for testing.&lt;/p&gt;

&lt;p&gt;You can have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Strategy
   ↓
Risk
   ↓
create_limit_order()
   ↓
Signed order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without immediately doing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST → live exchange
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you a natural dry-run boundary.&lt;/p&gt;




&lt;h1&gt;
  
  
  13. Example Limit Order Flow
&lt;/h1&gt;

&lt;p&gt;The current SDK example follows this general pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;build_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;SecureClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_limit_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BUY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The returned object is a signed order representation.&lt;/p&gt;

&lt;p&gt;For actual execution, use the SDK's current posting method rather than assuming that signing automatically submits the order.&lt;/p&gt;

&lt;p&gt;A production execution layer should therefore expose two distinct operations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExecutionEngine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;prepare_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;submit_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="bp"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That design makes dry-run testing much safer.&lt;/p&gt;




&lt;h1&gt;
  
  
  14. Dry-Run Mode
&lt;/h1&gt;

&lt;p&gt;Before allowing a bot to submit real orders, implement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DRY RUN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as a first-class execution mode.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ExecutionEngine&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dry_run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dry_run&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;dry_run&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create_limit_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dry_run&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;DRY RUN:&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;order&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;place_limit_order&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact live-call signature should be pinned against the SDK version you deploy.&lt;/p&gt;

&lt;p&gt;The important architectural property is that changing from simulation to execution should happen in &lt;strong&gt;one controlled location&lt;/strong&gt;, not throughout the codebase.&lt;/p&gt;




&lt;h1&gt;
  
  
  15. WebSockets for Real-Time Market Data
&lt;/h1&gt;

&lt;p&gt;Polling is easy to understand:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET book
sleep
GET book
sleep
GET book
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But a real-time trading system benefits from event-driven data.&lt;/p&gt;

&lt;p&gt;Polymarket documents a WebSocket market channel at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wss://ws-subscriptions-clob.polymarket.com/ws/market
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The market channel can deliver events including full book snapshots, price changes, last trade prices, best bid/ask updates, tick-size changes, and market lifecycle events.&lt;/p&gt;

&lt;p&gt;The documented channels also include user order/trade activity, sports data, and RTDS.&lt;/p&gt;

&lt;p&gt;A sensible architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                  WebSocket
                      │
                      ▼
             ┌────────────────┐
             │ Local Book     │
             │ State          │
             └───────┬────────┘
                     │
                     ▼
              Signal Engine
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The REST API can remain useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;initialization,&lt;/li&gt;
&lt;li&gt;snapshots,&lt;/li&gt;
&lt;li&gt;recovery,&lt;/li&gt;
&lt;li&gt;account queries,&lt;/li&gt;
&lt;li&gt;order management,&lt;/li&gt;
&lt;li&gt;and reconciliation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not make your strategy depend on one network stream being perfect forever.&lt;/p&gt;




&lt;h1&gt;
  
  
  16. Maintain Local State
&lt;/h1&gt;

&lt;p&gt;A production bot should maintain explicit state.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;field&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;BotState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;positions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_factory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;open_orders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_factory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;last_market_update&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;field&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;default_factory&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;realized_pnl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a WebSocket event arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;event
  ↓
validate
  ↓
update local state
  ↓
evaluate signal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When an order update arrives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;order event
  ↓
update order state
  ↓
update position state
  ↓
recalculate exposure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not assume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;submit order = position changed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are different states.&lt;/p&gt;




&lt;h1&gt;
  
  
  17. Risk Management Should Be a Separate Layer
&lt;/h1&gt;

&lt;p&gt;A strategy generates an opinion.&lt;/p&gt;

&lt;p&gt;Risk management decides whether that opinion is allowed to become an order.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;risk_allows&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;current_exposure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;proposed_notional&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_exposure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;current_exposure&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;proposed_notional&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;max_exposure&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But real risk controls should go further.&lt;/p&gt;

&lt;p&gt;Useful limits include:&lt;/p&gt;

&lt;h3&gt;
  
  
  Per-market exposure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maximum dollars/shares in one market
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Global exposure
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maximum portfolio exposure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Order-size limit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maximum size per individual order
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Open-order limit
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maximum number of outstanding orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Loss guard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;disable new entries after a configured loss threshold
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Stale-data guard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do not trade if market data is older than X seconds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Duplicate-signal guard
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;do not repeatedly submit the same signal
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Emergency kill switch
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cancel orders
stop strategy
remain offline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The kill switch is not an optional feature.&lt;/p&gt;




&lt;h1&gt;
  
  
  18. A Better Decision Pipeline
&lt;/h1&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="nf"&gt;buy&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Update
      │
      ▼
Is market tradable?
      │
      ▼
Is data fresh?
      │
      ▼
Is order book valid?
      │
      ▼
Calculate model fair value
      │
      ▼
Calculate executable edge
      │
      ▼
Estimate costs
      │
      ▼
Risk checks
      │
      ▼
Size order
      │
      ▼
Validate tick/size
      │
      ▼
Submit
      │
      ▼
Reconcile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pipeline is the difference between a script and a trading system.&lt;/p&gt;




&lt;h1&gt;
  
  
  19. Handling Rate Limits
&lt;/h1&gt;

&lt;p&gt;Polymarket documents API throttling across its Gamma, Data, CLOB, authentication, and trading APIs. The documented CLOB limits vary by endpoint, with separate burst and sustained limits for trading endpoints.&lt;/p&gt;

&lt;p&gt;For example, the current documentation lists:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLOB general requests: 9,000 requests / 10 seconds&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/book&lt;/code&gt;: 1,500 / 10 seconds&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;/price&lt;/code&gt;: 1,500 / 10 seconds&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /order&lt;/code&gt;: 3,500 / 10 seconds burst and 36,000 / 10 minutes sustained&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;DELETE /order&lt;/code&gt;: 3,000 / 10 seconds burst and 30,000 / 10 minutes sustained.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are &lt;strong&gt;platform limits&lt;/strong&gt;, not targets.&lt;/p&gt;

&lt;p&gt;A good bot should use substantially less than its theoretical allowance.&lt;/p&gt;

&lt;p&gt;Implement exponential backoff:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;retry_delay&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="n"&gt;attempt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;jitter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniform&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.25&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;jitter&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then retry only errors that are actually safe to retry.&lt;/p&gt;

&lt;p&gt;Do not blindly retry order submissions.&lt;/p&gt;

&lt;p&gt;That can create duplicate orders if the first request succeeded but the response was lost.&lt;/p&gt;




&lt;h1&gt;
  
  
  20. The Most Dangerous Failure: Unknown Order State
&lt;/h1&gt;

&lt;p&gt;Imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bot → POST order
       │
       ├── exchange accepts order
       │
       └── network connection dies
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your bot receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happened?&lt;/p&gt;

&lt;p&gt;You don't know.&lt;/p&gt;

&lt;p&gt;The order might be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rejected,&lt;/li&gt;
&lt;li&gt;accepted and resting,&lt;/li&gt;
&lt;li&gt;partially filled,&lt;/li&gt;
&lt;li&gt;completely filled,&lt;/li&gt;
&lt;li&gt;or cancelled elsewhere.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A naive retry could submit a second order.&lt;/p&gt;

&lt;p&gt;The correct response is reconciliation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST
 │
 ├── response → record order ID
 │
 └── timeout
       │
       ▼
   reconcile
       │
       ▼
 query known order/account state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is why order IDs and persistent state matter.&lt;/p&gt;




&lt;h1&gt;
  
  
  21. Limit Orders vs Market Orders
&lt;/h1&gt;

&lt;p&gt;Polymarket currently documents both limit and market orders. A limit order specifies a price and can remain on the book, while a market order is intended to trade against available liquidity.&lt;/p&gt;

&lt;p&gt;Use a limit order when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;price control matters,&lt;/li&gt;
&lt;li&gt;you can tolerate waiting,&lt;/li&gt;
&lt;li&gt;spread is important,&lt;/li&gt;
&lt;li&gt;execution certainty is less important.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use a market-style order when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;immediate execution matters,&lt;/li&gt;
&lt;li&gt;the strategy has a sufficiently strong edge,&lt;/li&gt;
&lt;li&gt;available liquidity has been evaluated,&lt;/li&gt;
&lt;li&gt;and slippage is explicitly modeled.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is universally superior.&lt;/p&gt;

&lt;p&gt;For a bot, the real question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What execution behavior does the strategy require?&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  22. Time-in-Force and Stale Quotes
&lt;/h1&gt;

&lt;p&gt;The current documentation supports GTC and GTD behavior for limit orders. GTD orders have documented expiration constraints, including a one-minute security threshold before their stated expiration and a minimum future expiration requirement.&lt;/p&gt;

&lt;p&gt;This matters for automated trading.&lt;/p&gt;

&lt;p&gt;Suppose your strategy wants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Buy at 0.42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;but the signal becomes invalid after 10 seconds.&lt;/p&gt;

&lt;p&gt;A long-lived GTC order could remain exposed after the original thesis has disappeared.&lt;/p&gt;

&lt;p&gt;Your execution policy therefore needs to answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;How long is this quote valid?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That answer belongs to the strategy/execution contract.&lt;/p&gt;




&lt;h1&gt;
  
  
  23. Practical Example: A Complete Signal Pipeline
&lt;/h1&gt;

&lt;p&gt;Here is a compact educational version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;decimal&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MarketSnapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;


&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;
    &lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Strategy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;minimum_edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;order_size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimum_edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;minimum_edge&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order_size&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;MarketSnapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model_probability&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;best_ask&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;edge&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;minimum_edge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;token_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;side&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;BUY&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;price&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;order_size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;edge&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;RiskManager&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;__init__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_exposure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_exposure&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max_exposure&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;approve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;current_exposure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;

        &lt;span class="n"&gt;notional&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;

        &lt;span class="nf"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="n"&gt;current_exposure&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;notional&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;max_exposure&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the application becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;approve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;current_exposure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;

&lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what is missing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;strategy → client.place_order()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The strategy does not directly place orders.&lt;/p&gt;

&lt;p&gt;That is intentional.&lt;/p&gt;




&lt;h1&gt;
  
  
  24. Production Architecture
&lt;/h1&gt;

&lt;p&gt;A more serious system could look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;flowchart TD
    A[Market Discovery] --&amp;gt; B[Market Registry]
    B --&amp;gt; C[WebSocket Market Feed]
    C --&amp;gt; D[Local Order Book]
    D --&amp;gt; E[Signal Engine]
    E --&amp;gt; F[Cost Model]
    F --&amp;gt; G[Risk Engine]
    G --&amp;gt; H[Execution Engine]
    H --&amp;gt; I[CLOB]
    I --&amp;gt; J[Order Events]
    J --&amp;gt; K[State Reconciliation]
    K --&amp;gt; L[Portfolio State]
    L --&amp;gt; G

    M[External Data] --&amp;gt; E
    N[Metrics] --&amp;gt; O[Monitoring]
    D --&amp;gt; N
    E --&amp;gt; N
    H --&amp;gt; N
    K --&amp;gt; N
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This architecture has an important property:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;the bot can recover state independently of the strategy.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If your strategy process crashes, you should still be able to determine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which orders exist,&lt;/li&gt;
&lt;li&gt;what positions exist,&lt;/li&gt;
&lt;li&gt;what markets are being watched,&lt;/li&gt;
&lt;li&gt;and whether the bot is safe to restart.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  25. Performance Engineering
&lt;/h1&gt;

&lt;p&gt;Performance should be measured rather than guessed.&lt;/p&gt;

&lt;p&gt;Do not begin with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I need a 1 ms bot."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Begin with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Where does time actually go?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Measure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;market event received
       ↓
event parsed
       ↓
local book updated
       ↓
signal generated
       ↓
risk check
       ↓
order signed
       ↓
request sent
       ↓
exchange response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record timestamps for each stage.&lt;/p&gt;

&lt;p&gt;Then calculate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;feed → signal latency
signal → submit latency
submit → acknowledgement latency
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The WebSocket market channel is appropriate for reducing dependence on repeated REST polling, but it does not eliminate network, processing, or exchange-side latency. Polymarket's documentation describes the channel as near-real-time rather than promising a fixed end-to-end latency.&lt;/p&gt;

&lt;p&gt;Avoid optimizing prematurely.&lt;/p&gt;

&lt;p&gt;For most early bots, the biggest performance gains come from:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;avoiding unnecessary polling,&lt;/li&gt;
&lt;li&gt;keeping connections alive,&lt;/li&gt;
&lt;li&gt;reducing redundant API calls,&lt;/li&gt;
&lt;li&gt;maintaining local state,&lt;/li&gt;
&lt;li&gt;eliminating blocking work from the hot path,&lt;/li&gt;
&lt;li&gt;and measuring the actual critical path.&lt;/li&gt;
&lt;/ol&gt;




&lt;h1&gt;
  
  
  26. Don't Put Logging on the Hot Path
&lt;/h1&gt;

&lt;p&gt;This is easy to overlook.&lt;/p&gt;

&lt;p&gt;Avoid doing expensive operations such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;huge_object&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;database&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;commit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;large_book&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;for every market update.&lt;/p&gt;

&lt;p&gt;Instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market feed
    │
    ├──► hot strategy path
    │
    └──► async logging/metrics pipeline
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A lightweight queue works well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;queue&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;SimpleQueue&lt;/span&gt;

&lt;span class="n"&gt;metrics_queue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;SimpleQueue&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;


&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;record_metric&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;metrics_queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A separate worker can batch and persist metrics.&lt;/p&gt;




&lt;h1&gt;
  
  
  27. Security
&lt;/h1&gt;

&lt;p&gt;A trading bot has two major security surfaces:&lt;/p&gt;

&lt;h3&gt;
  
  
  Credentials
&lt;/h3&gt;

&lt;p&gt;Protect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;private keys,&lt;/li&gt;
&lt;li&gt;API credentials,&lt;/li&gt;
&lt;li&gt;builder credentials,&lt;/li&gt;
&lt;li&gt;wallet information.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Trading authority
&lt;/h3&gt;

&lt;p&gt;Even if a private key never leaks, a software bug can still lose money.&lt;/p&gt;

&lt;p&gt;Therefore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;enforce maximum order size,&lt;/li&gt;
&lt;li&gt;enforce maximum exposure,&lt;/li&gt;
&lt;li&gt;validate token IDs,&lt;/li&gt;
&lt;li&gt;validate market state,&lt;/li&gt;
&lt;li&gt;reject impossible prices,&lt;/li&gt;
&lt;li&gt;reject stale data,&lt;/li&gt;
&lt;li&gt;implement a kill switch,&lt;/li&gt;
&lt;li&gt;separate dry-run from live mode,&lt;/li&gt;
&lt;li&gt;restrict production credentials,&lt;/li&gt;
&lt;li&gt;and audit every order.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Never log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PRIVATE_KEY
API_SECRET
seed phrase
signed credential material
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Be careful with exceptions as well.&lt;/p&gt;

&lt;p&gt;An exception object can contain request information or serialized credentials if a poorly designed dependency includes them.&lt;/p&gt;




&lt;h1&gt;
  
  
  28. Testing Strategy
&lt;/h1&gt;

&lt;p&gt;Do not begin testing with real money.&lt;/p&gt;

&lt;p&gt;A useful testing pyramid is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                 ┌───────────────┐
                 │ Live / tiny   │
                 │ controlled    │
                 └───────┬───────┘
                         │
                 ┌───────┴───────┐
                 │ Integration   │
                 └───────┬───────┘
                         │
                 ┌───────┴───────┐
                 │ Replay tests  │
                 └───────┬───────┘
                         │
                 ┌───────┴───────┐
                 │ Unit tests    │
                 └───────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Unit tests
&lt;/h2&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;probability calculations,&lt;/li&gt;
&lt;li&gt;edge calculations,&lt;/li&gt;
&lt;li&gt;price rounding,&lt;/li&gt;
&lt;li&gt;position limits,&lt;/li&gt;
&lt;li&gt;order sizing,&lt;/li&gt;
&lt;li&gt;stale-data checks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;test_signal_requires_minimum_edge&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;0.51&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;assert&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Replay tests
&lt;/h2&gt;

&lt;p&gt;Save real market-data events and replay them through the strategy.&lt;/p&gt;

&lt;p&gt;This is much more useful than testing only synthetic values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration tests
&lt;/h2&gt;

&lt;p&gt;Test:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication,&lt;/li&gt;
&lt;li&gt;market discovery,&lt;/li&gt;
&lt;li&gt;order construction,&lt;/li&gt;
&lt;li&gt;cancellation,&lt;/li&gt;
&lt;li&gt;reconciliation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The official Python SDK repository itself distinguishes integration tests from metered tests and warns that tests which place orders, spend funds, or mutate live state require explicit opt-in.&lt;/p&gt;

&lt;p&gt;That is a good pattern to copy.&lt;/p&gt;




&lt;h1&gt;
  
  
  29. Backtesting Prediction-Market Strategies
&lt;/h1&gt;

&lt;p&gt;Traditional OHLC backtesting is often insufficient.&lt;/p&gt;

&lt;p&gt;A prediction-market backtest should model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;timestamp
token
bid levels
ask levels
trade events
available depth
your order size
execution assumption
fees
position
resolution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you only backtest against:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;last_price
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can dramatically overestimate execution quality.&lt;/p&gt;

&lt;p&gt;A better simulator asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If my bot submitted this order at this timestamp, how much of it could realistically have filled?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For market-making strategies, you also need queue-position assumptions.&lt;/p&gt;

&lt;p&gt;For taker strategies, you need depth-aware slippage.&lt;/p&gt;




&lt;h1&gt;
  
  
  30. Monitoring and Observability
&lt;/h1&gt;

&lt;p&gt;A production bot should expose metrics such as:&lt;/p&gt;

&lt;h3&gt;
  
  
  Market-data metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;websocket_connected
book_update_age
messages_per_second
reconnect_count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Strategy metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signals_generated
signals_rejected
edge_distribution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Execution metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;orders_submitted
orders_rejected
orders_filled
partial_fills
cancel_count
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Risk metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current_exposure
maximum_exposure
open_orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  System metrics
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;process_uptime
CPU
memory
network errors
API errors
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should also log structured events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"event"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"order_submitted"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"token_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"side"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"BUY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0.52"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"size"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"10"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"strategy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"probability_edge"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"dry_run"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Never assume your logs are only for debugging.&lt;/p&gt;

&lt;p&gt;They become your trading audit trail.&lt;/p&gt;




&lt;h1&gt;
  
  
  31. Failure Modes You Should Expect
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Stale market data
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; The strategy acts on an old book.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Attach timestamps to market state and reject stale data.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Duplicate orders
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; A timeout is interpreted as failure and the bot submits again.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Reconcile order state before retrying an uncertain submission.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Invalid price precision
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Strategy generates a price that violates tick size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Quantize against the market's current minimum tick size.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Invalid order size
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Size is below the market minimum.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Validate before signing.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Assuming every market has the same fee
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Cost model is wrong.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Read current market fee configuration where applicable. Polymarket says fees are determined per market at match time.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Using an obsolete SDK
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Tutorials tell you to build everything around &lt;code&gt;py-clob-client&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Check the current official SDK first. The historical repository is archived, and Polymarket now recommends the unified Python SDK.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Treating order creation as submission
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Bot believes an order was sent when it only created a signed object.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Keep &lt;code&gt;create&lt;/code&gt; and &lt;code&gt;place/post&lt;/code&gt; operations separate.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Polling everything
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; Unnecessary API traffic and stale snapshots.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Use the real-time market channel where appropriate and reserve REST for snapshots, recovery, account state, and execution workflows.&lt;/p&gt;




&lt;h1&gt;
  
  
  32. Advanced Improvement: External Signal Feeds
&lt;/h1&gt;

&lt;p&gt;A stronger strategy architecture can consume external information:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;External Feed
     │
     ▼
Feature Engineering
     │
     ▼
Probability Model
     │
     ▼
Polymarket Market
     │
     ▼
Execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples could include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;financial prices,&lt;/li&gt;
&lt;li&gt;weather data,&lt;/li&gt;
&lt;li&gt;sports data,&lt;/li&gt;
&lt;li&gt;economic releases,&lt;/li&gt;
&lt;li&gt;news/event data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key is not simply receiving another feed.&lt;/p&gt;

&lt;p&gt;The model must answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What probability does this information imply?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then compare it against an executable Polymarket price.&lt;/p&gt;




&lt;h1&gt;
  
  
  33. Advanced Improvement: Market Making
&lt;/h1&gt;

&lt;p&gt;A market-making bot changes the objective.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"I think YES is underpriced."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you might estimate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fair_value
inventory
spread
adverse_selection_risk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then quote:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bid = fair_value - spread
ask = fair_value + spread
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;while controlling inventory.&lt;/p&gt;

&lt;p&gt;The strategy becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fair value
    │
    ├──► Bid quote
    │
    └──► Ask quote
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Polymarket currently documents market-making and maker-rebate programs separately, and the current fee documentation states that makers are not charged the applicable taker fee.&lt;/p&gt;

&lt;p&gt;That does &lt;strong&gt;not&lt;/strong&gt; mean market making is automatically profitable. Inventory risk, adverse selection, stale quotes, and execution costs remain.&lt;/p&gt;




&lt;h1&gt;
  
  
  34. Advanced Improvement: Event-Driven State Machines
&lt;/h1&gt;

&lt;p&gt;For more complex bots, model orders as explicit states:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATED
   │
   ▼
SIGNED
   │
   ▼
SUBMITTED
   │
   ├───────────────┐
   ▼               ▼
OPEN            REJECTED
   │
   ├───────┐
   ▼       ▼
PARTIAL   CANCELLED
   │
   ▼
FILLED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much safer than scattered booleans such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;order_sent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;span class="n"&gt;order_filled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A state machine makes impossible transitions easier to detect.&lt;/p&gt;




&lt;h1&gt;
  
  
  35. Advanced Improvement: Reconciliation Loop
&lt;/h1&gt;

&lt;p&gt;Even with WebSockets, periodically reconcile your local state against authoritative API data.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Continuous WebSocket state
           │
           ▼
      Local state
           │
           │
     periodic check
           ▼
     REST/API state
           │
           ▼
      reconciliation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;local_open_orders != remote_open_orders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;stop new trading until the discrepancy is understood.&lt;/p&gt;

&lt;p&gt;A trading bot should fail &lt;strong&gt;closed&lt;/strong&gt;, not fail open.&lt;/p&gt;




&lt;h1&gt;
  
  
  36. A Practical Production Loop
&lt;/h1&gt;

&lt;p&gt;Putting the components together:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;run_cycle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;market&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;is_stale&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;evaluate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;snapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;model_probability&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;signal&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;risk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;approve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;current_exposure&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;current_exposure&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="n"&gt;execution&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This looks almost boring.&lt;/p&gt;

&lt;p&gt;That is a good sign.&lt;/p&gt;

&lt;p&gt;Production trading infrastructure should be boring at the boundaries.&lt;/p&gt;

&lt;p&gt;The complexity belongs inside well-defined components, not in unpredictable interactions between them.&lt;/p&gt;




&lt;h1&gt;
  
  
  37. Current Polymarket API Details Worth Keeping in Mind
&lt;/h1&gt;

&lt;p&gt;As of the documentation checked for this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Polymarket provides a unified official Python SDK named &lt;code&gt;polymarket-client&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The SDK is currently beta.&lt;/li&gt;
&lt;li&gt;The historical &lt;code&gt;py-clob-client&lt;/code&gt; repository is archived and its README recommends migration.&lt;/li&gt;
&lt;li&gt;The official Python SDK exposes &lt;code&gt;PublicClient&lt;/code&gt;, &lt;code&gt;AsyncPublicClient&lt;/code&gt;, &lt;code&gt;SecureClient&lt;/code&gt;, and &lt;code&gt;AsyncSecureClient&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Polymarket provides WebSocket channels for market and user activity.&lt;/li&gt;
&lt;li&gt;Current trading documentation supports limit and market orders.&lt;/li&gt;
&lt;li&gt;Limit orders must respect the market's tick size and minimum order size.&lt;/li&gt;
&lt;li&gt;Fees are market-dependent and applied at match time where enabled.&lt;/li&gt;
&lt;li&gt;API throttling applies across the platform and trading endpoints have their own burst/sustained limits.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These details can change.&lt;/p&gt;

&lt;p&gt;For a production bot, treat the official documentation as part of your deployment dependency.&lt;/p&gt;




&lt;h1&gt;
  
  
  Frequently Asked Questions
&lt;/h1&gt;

&lt;h2&gt;
  
  
  What is a Polymarket trading bot?
&lt;/h2&gt;

&lt;p&gt;A Polymarket trading bot is software that automatically consumes market information, evaluates a trading rule or model, manages risk, and submits or manages orders through Polymarket's developer interfaces.&lt;/p&gt;

&lt;p&gt;A useful bot is an execution system, not merely a price scraper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I build a Polymarket trading bot with Python?
&lt;/h2&gt;

&lt;p&gt;Yes. Polymarket currently maintains an official Python SDK, &lt;code&gt;polymarket-client&lt;/code&gt;, which provides public and authenticated client workflows. The SDK is currently beta.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is &lt;code&gt;py-clob-client&lt;/code&gt; still the recommended Python SDK?
&lt;/h2&gt;

&lt;p&gt;No. The historical &lt;code&gt;py-clob-client&lt;/code&gt; repository was archived in May 2026, and its README says it is no longer maintained and recommends migrating to the unified SDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Does a trading bot guarantee profit?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;Automation changes execution and consistency; it does not create an economic edge.&lt;/p&gt;

&lt;p&gt;A strategy can lose money because of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;incorrect probabilities,&lt;/li&gt;
&lt;li&gt;spread,&lt;/li&gt;
&lt;li&gt;fees,&lt;/li&gt;
&lt;li&gt;slippage,&lt;/li&gt;
&lt;li&gt;adverse selection,&lt;/li&gt;
&lt;li&gt;low liquidity,&lt;/li&gt;
&lt;li&gt;execution failures,&lt;/li&gt;
&lt;li&gt;and changing market conditions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Should I use REST or WebSockets?
&lt;/h2&gt;

&lt;p&gt;Use them for different jobs.&lt;/p&gt;

&lt;p&gt;WebSockets are well suited to continuously changing market information. REST remains useful for snapshots, recovery, account information, and trading operations. Polymarket documents both real-time WebSocket channels and REST-based APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  How much money do I need to start?
&lt;/h2&gt;

&lt;p&gt;There is no universally correct amount.&lt;/p&gt;

&lt;p&gt;Start with an amount whose complete loss would be acceptable to you, and prioritize dry-run, replay, and integration testing before live trading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I start with market making or directional trading?
&lt;/h2&gt;

&lt;p&gt;For a first bot, directional probability-based execution is usually easier to reason about.&lt;/p&gt;

&lt;p&gt;Market making introduces additional problems such as inventory management, adverse selection, quote cancellation, and execution quality.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can I run the bot on a VPS?
&lt;/h2&gt;

&lt;p&gt;Yes, provided the deployment satisfies your operational and security requirements.&lt;/p&gt;

&lt;p&gt;The important properties are stable networking, secret protection, process supervision, logging, monitoring, and a recovery strategy—not simply choosing a particular hosting provider.&lt;/p&gt;




&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Building a &lt;strong&gt;Polymarket trading bot in Python&lt;/strong&gt; is fundamentally an engineering problem before it is a strategy problem.&lt;/p&gt;

&lt;p&gt;The minimum useful architecture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Market Discovery
      ↓
Market Data
      ↓
Signal
      ↓
Cost Model
      ↓
Risk
      ↓
Execution
      ↓
Reconciliation
      ↓
Monitoring
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The most important implementation lessons are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use the current official SDK rather than copying an obsolete tutorial.&lt;/li&gt;
&lt;li&gt;Separate market discovery from execution.&lt;/li&gt;
&lt;li&gt;Trade outcome token IDs, not URLs or arbitrary market identifiers.&lt;/li&gt;
&lt;li&gt;Respect tick-size and minimum-order constraints.&lt;/li&gt;
&lt;li&gt;Model executable prices rather than theoretical prices.&lt;/li&gt;
&lt;li&gt;Account for fees, spread, slippage, and adverse selection.&lt;/li&gt;
&lt;li&gt;Use WebSockets for appropriate real-time market workflows.&lt;/li&gt;
&lt;li&gt;Treat uncertain order submissions as reconciliation problems.&lt;/li&gt;
&lt;li&gt;Build dry-run and replay testing before live execution.&lt;/li&gt;
&lt;li&gt;Put hard risk limits between every strategy signal and the exchange.&lt;/li&gt;
&lt;li&gt;Monitor the bot as an operational system.&lt;/li&gt;
&lt;li&gt;Re-check Polymarket's documentation whenever the platform or SDK changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The strategy is replaceable.&lt;/p&gt;

&lt;p&gt;The infrastructure is what lets you safely test increasingly sophisticated strategies.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trading-risk disclaimer:&lt;/strong&gt; This article is educational and technical, not financial advice. Automated prediction-market trading can result in partial or total loss of capital. No strategy described here is guaranteed to be profitable. Validate strategies with historical/replay data and controlled testing before risking meaningful capital.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Related Articles
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. How to Read Polymarket Order Books With Python
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;read Polymarket order books with Python&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; This is the natural next step after market discovery and introduces depth, spread, liquidity, and executable pricing.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Polymarket WebSocket API: Build a Real-Time Market Data Feed
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;Polymarket WebSocket market data&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Readers who understand REST-based polling can move toward event-driven market-data architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Polymarket Order Execution in Python
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;Polymarket order execution in Python&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Deepens the execution section with signing, posting, cancellation, order lifecycle, and reconciliation.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. How to Build a Polymarket Market-Making Bot
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;build a Polymarket market-making bot&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Creates a strategy-level progression from directional execution to liquidity provision.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Polymarket Trading Bot Risk Management
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;Polymarket bot risk management&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Expands the most important production layer: exposure, sizing, kill switches, stale-data protection, and portfolio limits.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. How to Backtest Polymarket Trading Strategies
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;backtest Polymarket trading strategies&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Connects live bot architecture to historical simulation and execution-aware research.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Polymarket API Authentication With Python
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;Polymarket API authentication&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Gives readers a dedicated security and credential-management tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Polymarket Bot Monitoring and Observability
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Suggested anchor:&lt;/strong&gt; &lt;code&gt;monitor a Polymarket trading bot&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why link it:&lt;/strong&gt; Extends the production section into metrics, alerting, state reconciliation, and operational reliability.&lt;/p&gt;




&lt;h1&gt;
  
  
  Useful Resources
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Official Polymarket
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use this for the live product, markets, account interface, and market context.&lt;/p&gt;

&lt;h2&gt;
  
  
  Official Polymarket Documentation
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.polymarket.com/?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This should be the primary technical reference for API behavior, trading workflows, market data, authentication, fees, and SDK changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Market Discovery
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.polymarket.com/market-data/discover-markets?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket Market Discovery Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful for understanding how to discover and filter markets before trading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Python SDK
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Polymarket/py-sdk?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Official Polymarket Python SDK&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The current unified Python SDK for Polymarket integrations. It is currently beta.&lt;/p&gt;

&lt;h2&gt;
  
  
  WebSocket Market Data
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.polymarket.com/market-data/websocket/overview?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket WebSocket Overview&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful when moving from REST polling to real-time market-data processing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relevant DEV.to Resource
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dev.to/bluewhale-quant-lab/building-a-low-latency-polymarket-trading-bot-in-python-py-clob-client-websocket-4il8?utm_source=chatgpt.com"&gt;Building a Low-Latency Polymarket Trading Bot in Python — DEV.to&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Useful for discussing engineering considerations around WebSockets and execution architecture. Its latency measurements are author-specific and should not be treated as Polymarket guarantees.&lt;/p&gt;

&lt;h2&gt;
  
  
  Relevant YouTube Tutorial
&lt;/h2&gt;

&lt;p&gt;Useful as a practical visual walkthrough for developers who prefer seeing a complete bot assembled end-to-end. It is supplementary to the official documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Official Polymarket X
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://x.com/Polymarket?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket on X&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use official social channels for product announcements, but verify technical claims against the documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polymarket Developer Resources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/Polymarket?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Polymarket GitHub Organization&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The official GitHub organization is useful for tracking SDKs, developer tooling, and other open-source components.&lt;/p&gt;




&lt;h1&gt;
  
  
  About the Author
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;[Bo$onaX]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I write about Polymarket trading bots, prediction-market infrastructure, algorithmic trading, Python automation, Web3 development, and quantitative strategies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contact:&lt;/strong&gt;&lt;br&gt;
X: [&lt;a href="https://x.com/@xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/@xxniiinxx&lt;/a&gt;]&lt;br&gt;
Telegram: [&lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;]&lt;/p&gt;

</description>
      <category>polymarket</category>
      <category>ai</category>
      <category>trading</category>
      <category>python</category>
    </item>
    <item>
      <title>How to Build a Polymarket Trading Bot (After 50 ms Taker Delay Edition)</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Mon, 17 Aug 2026 23:02:28 +0000</pubDate>
      <link>https://dev.to/xniiinx/how-to-build-a-polymarket-trading-bot-after-50-ms-taker-delay-edition-3mi8</link>
      <guid>https://dev.to/xniiinx/how-to-build-a-polymarket-trading-bot-after-50-ms-taker-delay-edition-3mi8</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Polymarket has steadily tightened the latency environment on crypto markets. The original 500 ms taker delay was removed in February 2026. A residual 250 ms delay remained for a while, and on &lt;strong&gt;August 17, 2026 at 11:00 AM UTC&lt;/strong&gt; that delay was cut to &lt;strong&gt;50 ms&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This change further reduces the protective buffer market makers previously enjoyed when cancelling stale quotes. Combined with dynamic taker fees, maker rebates, and the move to Chainlink TWAP resolution on short-duration crypto markets, the meta continues to favor &lt;strong&gt;fast, fee-aware makers&lt;/strong&gt; over pure taker latency-arbitrage bots.&lt;/p&gt;

&lt;p&gt;The new reality: if you cannot cancel/replace in well under 100 ms end-to-end (ideally closer to 50–70 ms), your resting orders will be adversely selected more often.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Changed (Recent Timeline)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;500 ms taker delay removed (Feb 18, 2026)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Instant matching for takers; makers lost the half-second window to pull quotes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;250 ms residual taker delay + lock-in behavior (June 2026)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Once a taker order entered the delay window it became non-cancellable until the delay expired.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Taker delay reduced to 50 ms (August 17, 2026, 11:00 AM UTC)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Official announcement from @PolymarketDevs. Crypto markets now execute taker fills after only a 50 ms delay. Liquidity and market quality will be monitored and may be adjusted further.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Dynamic taker fees + maker rebates (ongoing since early 2026, refined in CLOB V2)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Current crypto formula (approx.):&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   fee = C × 0.07 × p × (1 − p)  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Peak ~$1.75 per 100 shares at 50 ¢. Makers pay zero fees and receive ~20 % of collected taker fees as daily USDC rebates (fee-curve weighted).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TWAP resolution on 5-min / 15-min / 4-hour crypto markets (August 2026)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Settlement uses Chainlink time-weighted average price (currently 60 s lookback on 5-min markets). Last-second single-tick sniping is largely dead; bots must model the averaging window.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;CLOB V2 (April 2026)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;code&gt;feeRateBps&lt;/code&gt; removed from the signed order payload — fees are applied at match time. Order structure simplified.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The New Meta: Still Be a Maker (but even faster)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Zero fees + daily rebates remain the cleanest edge.
&lt;/li&gt;
&lt;li&gt;50 ms taker delay means the adverse-selection window is now tiny. Your cancel/replace loop must be extremely tight.
&lt;/li&gt;
&lt;li&gt;Colocation (Amsterdam region is known to be closest to the CLOB) + WebSocket + low-level language (Rust preferred) is close to mandatory for competitive market-making.
&lt;/li&gt;
&lt;li&gt;Taker strategies only work if you have a genuine information edge larger than the fee curve + the residual 50 ms risk.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to Build a Compliant Bot (August 2026 Architecture)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core Requirements
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Real-time WebSocket order-book and user-channel streams (REST is too slow).
&lt;/li&gt;
&lt;li&gt;End-to-end cancel → replace cycle target: &lt;strong&gt;&amp;lt; 70–80 ms&lt;/strong&gt; (ideally under the new 50 ms delay).
&lt;/li&gt;
&lt;li&gt;Fee-aware position sizing and edge calculation (use the current 0.07 rate curve).
&lt;/li&gt;
&lt;li&gt;TWAP-aware signal generation for short crypto markets.
&lt;/li&gt;
&lt;li&gt;Proper approvals, private-key management, and rate-limit awareness (volume-based tiers now live).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step-by-Step Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Private key &amp;amp; approvals&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Same as before: export your EOA private key and approve the exchange contracts for USDC / conditional tokens (one-time).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Client choice&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official: &lt;code&gt;py-clob-client&lt;/code&gt; or TypeScript / Rust SDKs (now stable).
&lt;/li&gt;
&lt;li&gt;Performance: &lt;code&gt;polyfill-rs&lt;/code&gt;, official Rust SDK, or a full HFT framework.
Prefer the lowest-latency stack you can reliably maintain.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Connect via WebSocket&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Subscribe to market channels for order-book depth and the user channel for fills/cancels. Do not poll REST for critical path logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Order construction (post-CLOB V2)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Fees are no longer part of the signed payload. Sign and post clean limit orders. Query any remaining market-specific parameters if needed, but the old &lt;code&gt;feeRateBps&lt;/code&gt; field is gone.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Maker quoting on both sides&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Post resting limit orders on YES and NO (or the relevant outcomes). Aim to earn rebates while keeping inventory under control.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Ultra-fast cancel/replace loop&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Monitor external price feed (Binance / Chainlink TWAP streams) + Polymarket book.
&lt;/li&gt;
&lt;li&gt;On any meaningful move: cancel → immediately replace.
&lt;/li&gt;
&lt;li&gt;With only 50 ms of taker delay left, any cycle longer than ~80–100 ms will get picked off regularly.
&lt;/li&gt;
&lt;li&gt;Colocate in Amsterdam if possible; residential or distant VPS is no longer viable for serious market-making.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Example Strategy Adjustments for 5-Minute BTC Markets (post-TWAP)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Markets resolve on a 60-second Chainlink TWAP.
&lt;/li&gt;
&lt;li&gt;Deterministic direction is still often visible well before close, but you now model the &lt;em&gt;average&lt;/em&gt; over the lookback window rather than a single last tick.
&lt;/li&gt;
&lt;li&gt;Near the end of the window (T-10 to T-5 s):

&lt;ul&gt;
&lt;li&gt;Compute expected TWAP direction from live feeds.
&lt;/li&gt;
&lt;li&gt;Post aggressive maker orders on the winning side (e.g., 90–95 ¢) only if your modeled edge exceeds fees + residual latency risk.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Continue earning maker rebates on any resting volume throughout the market.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common Mistakes That Still Kill Bots
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Relying on REST polling.
&lt;/li&gt;
&lt;li&gt;Cancel/replace loops slower than ~80 ms.
&lt;/li&gt;
&lt;li&gt;Ignoring the current fee curve when calculating edge.
&lt;/li&gt;
&lt;li&gt;Running from high-latency locations.
&lt;/li&gt;
&lt;li&gt;Treating the market as single-tick settlement (it is now TWAP).
&lt;/li&gt;
&lt;li&gt;Not merging YES/NO positions or managing inventory.
&lt;/li&gt;
&lt;li&gt;Attempting pure taker arb without a large enough edge after fees.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using AI Correctly
&lt;/h2&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; ask an LLM “build me a Polymarket bot.” It will regurgitate outdated 2025/early-2026 code.  &lt;/p&gt;

&lt;p&gt;Instead give it the current constraints:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Write a maker bot for Polymarket 5-minute BTC markets using the official Rust/Python CLOB client. Use WebSocket order-book + Binance/Chainlink TWAP feeds. Target full cancel/replace under 70 ms. Fees are applied at match time (0.07 × p × (1-p) curve). Post maker quotes on both sides, skew inventory, and respect the 50 ms taker delay environment.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Always back-test against the live fee curve and the current TWAP window.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;p&gt;The bots that win in late 2026 are still the best liquidity providers — just faster ones.  &lt;/p&gt;

&lt;p&gt;The reduction from 250 ms → 50 ms taker delay removes almost the last meaningful protective buffer. Speed, fee awareness, TWAP modeling, and disciplined risk controls are now non-negotiable.&lt;/p&gt;

&lt;p&gt;Build maker bots. Stay under 70 ms. Earn the rebates. Monitor the official @PolymarketDevs channel for further adjustments.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Support team links&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Telegram: &lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;X: &lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Polymarket: &lt;a href="https://polymarket.com/@bosona" rel="noopener noreferrer"&gt;https://polymarket.com/@bosona&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvfswu4z2kssjvz8hzv4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvfswu4z2kssjvz8hzv4y.png" alt=" " width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Useful links&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official announcement: &lt;a href="https://x.com/PolymarketDevs/status/2089295325660172578" rel="noopener noreferrer"&gt;https://x.com/PolymarketDevs/status/2089295325660172578&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docs: &lt;a href="https://docs.polymarket.com/" rel="noopener noreferrer"&gt;https://docs.polymarket.com/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Fees: &lt;a href="https://docs.polymarket.com/trading/fees" rel="noopener noreferrer"&gt;https://docs.polymarket.com/trading/fees&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Maker Rebates: &lt;a href="https://docs.polymarket.com/market-makers/maker-rebates" rel="noopener noreferrer"&gt;https://docs.polymarket.com/market-makers/maker-rebates&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  rust #python #polymarket #trading #bot #arbitrage #copytrading #marketmaker #polymarkettradingbot #polymarketcopytradingbot #polymarketbot #tradingbot #copytradingbot #arbitragebot
&lt;/h1&gt;

</description>
      <category>polymarket</category>
      <category>trading</category>
      <category>bot</category>
      <category>strategy</category>
    </item>
    <item>
      <title>Is Price Action Analysis The Same As Technical Analysis in Polymarket Crypto Up/Down Markets?</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Fri, 14 Aug 2026 14:53:41 +0000</pubDate>
      <link>https://dev.to/xniiinx/is-price-action-analysis-the-same-as-technical-analysis-in-polymarket-crypto-updown-markets-23ci</link>
      <guid>https://dev.to/xniiinx/is-price-action-analysis-the-same-as-technical-analysis-in-polymarket-crypto-updown-markets-23ci</guid>
      <description>&lt;p&gt;&lt;strong&gt;Is Price Action Analysis the Same as Technical Analysis in Polymarket Crypto Up/Down Markets?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Why pure price action outperforms indicator-heavy technical analysis for short-term binary crypto prediction markets&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Is price action analysis the same as technical analysis when trading Polymarket’s Crypto Up/Down markets? The answer is “yes and no.”&lt;/p&gt;

&lt;p&gt;Technical analysis is generally defined as a methodology for forecasting the direction of prices through the study of past market data, primarily price and volume. On Polymarket, this definition applies directly to binary Crypto Up/Down markets (e.g., “Will Bitcoin be higher or lower at the end of the hour/day?”), where the sole goal is predicting short-term directional moves in assets like BTC, ETH, or others.&lt;/p&gt;

&lt;p&gt;However, technical analysis as commonly practiced often includes a wide array of “technical studies”—indicators, oscillators, and complex patterns—anything that isn’t pure fundamental or news-driven data.&lt;/p&gt;

&lt;p&gt;Are all of these technical studies, such as RSI, MACD, Stochastic, or elaborate chart pattern overlays, really necessary or effective for Polymarket Crypto Up/Down trading? Why do some traders become convinced that loading charts with indicators is the path to consistent wins on these binary markets, while others rely solely on raw price action? Here’s a clear breakdown tailored to these short-term prediction markets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why All Technical Analysis Methods Are Not Created Equal for Crypto Up/Down Markets
&lt;/h3&gt;

&lt;p&gt;While technical analysis has its place, pure price action traders who focus on reading the raw movement of crypto prices do not subscribe to the idea that “any technical study is a good study.” Instead, the focus stays on a handful of simple, effective price-based principles. There is no need to force what appears on a Bitcoin or Ethereum chart into matching textbook indicator setups or multi-indicator confluence systems that many popular trading approaches promote.&lt;/p&gt;

&lt;p&gt;Crypto Up/Down markets on Polymarket resolve based on a specific price at a fixed time (hourly, daily, etc.). Relying heavily on lagging indicators or secondary technical tools that largely ignore the actual price action of the underlying crypto often leads to overcomplication and long-term underperformance. These markets move fast, and hindsight-fitted indicator systems frequently fail in live conditions.&lt;/p&gt;

&lt;p&gt;Many common technical analysis tools introduce what can be called “noise.” Indicators such as RSI, Stochastic, MACD, Bollinger Bands, and countless others are simply mathematical derivatives of price. If the goal is to predict whether Bitcoin will finish higher or lower in the next hour or day, analyzing a derivative of price adds unnecessary variables. Why not read the raw price action of the crypto itself?&lt;/p&gt;

&lt;p&gt;Adding these extra layers clutters the charts, the decision-making process, and the mind. For Polymarket Crypto Up/Down trading, this is especially counterproductive. All that is needed to form a directional view is the raw, natural price data that any crypto market supplies for free. There is no requirement for complex “systems” or indicator packs—raw price action is sufficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Price Action Analysis Is the Best Technical Analysis Method for Polymarket Crypto Up/Down Markets
&lt;/h3&gt;

&lt;p&gt;After filtering the noise common in technical analysis resources, what remains effective and logical for these binary markets is pure price action: the movement of price on a clean, indicator-free chart of the underlying cryptocurrency.&lt;/p&gt;

&lt;p&gt;In this context, price action means focusing exclusively on the raw candlestick chart of BTC, ETH, or the relevant crypto. Key elements include watching levels of support and resistance, identifying the short-term market bias and trend, and observing how price is behaving relative to the timeframe of the Polymarket contract (e.g., the next hour or the daily close). This is done by visually reading the chart rather than relying on third-party indicators or secondary studies.&lt;/p&gt;

&lt;p&gt;A practical approach uses specific price bar patterns or candlestick signals for timing entries into the “Up” or “Down” side of a Polymarket market. First map the market using price action, then wait patiently for a confluence of factors to align before committing capital.&lt;/p&gt;

&lt;h3&gt;
  
  
  A Simple and Effective Confluence Framework: T.L.S.
&lt;/h3&gt;

&lt;p&gt;A straightforward framework for Crypto Up/Down markets is &lt;strong&gt;T.L.S.&lt;/strong&gt;—Trend, Level, Signal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trend&lt;/strong&gt;: Is the short-term direction of the crypto clearly bullish or bearish on the relevant timeframe?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Level&lt;/strong&gt;: Is price interacting with a clear support or resistance level that has previously influenced price?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Signal&lt;/strong&gt;: Is there a clear price action signal (such as a strong rejection candle, pin bar, or engulfing pattern) forming at that level in the direction of the bias?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Look for at least two of these three factors to align. For example, an uptrend + a bounce from a key support level + a bullish rejection candle can create a higher-probability setup to buy the “Up” side of a Polymarket Crypto market. The same logic applies in reverse for “Down” opportunities. When multiple factors line up near the resolution window of the market, the odds improve.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep It Simple
&lt;/h3&gt;

&lt;p&gt;Technical analysis for Polymarket Crypto Up/Down markets does not need to be more complicated than identifying the dominant short-term trend, marking key chart levels, and waiting for clear price action signals. Anyone claiming otherwise is usually either selling complexity or overcomplicating a process that works best when kept simple.&lt;/p&gt;

&lt;p&gt;Price action remains the cleanest and most direct form of technical analysis for these markets. Strip away the indicators, read the raw crypto price movement, and trade the confluence.&lt;/p&gt;

</description>
      <category>trading</category>
      <category>crypto</category>
      <category>polymarket</category>
      <category>technicalanalysis</category>
    </item>
    <item>
      <title>I Built a Live Trading Bot in Python. Here's What Actually Works (Polymarket TWAP Edition).</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Thu, 13 Aug 2026 15:24:03 +0000</pubDate>
      <link>https://dev.to/xniiinx/i-built-a-live-trading-bot-in-python-heres-what-actually-works-polymarket-twap-edition-22ob</link>
      <guid>https://dev.to/xniiinx/i-built-a-live-trading-bot-in-python-heres-what-actually-works-polymarket-twap-edition-22ob</guid>
      <description>&lt;p&gt;Build a Python trading bot with Claude AI, Polymarket CLOB integration, and live Polymarket TWAP (Chainlink) signals. Paper trading to production in one guide.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I built a production algorithmic trading system using Python, Claude Code for development, Polymarket’s CLOB API for execution, and Polymarket’s Real-Time Data Streaming (RTDS) Chainlink TWAP feeds for signals. This guide covers the full architecture: signal generation from 30s/60s TWAP updates, position management, exit strategies, and the paper-to-live progression that prevented costly mistakes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
01 A production trading bot needs five core modules: signal generation, position execution, exit management, state persistence, and health monitoring&lt;br&gt;&lt;br&gt;
02 Claude Code wrote 95% of the 4,000-line codebase autonomously, including the asyncio event loop, database layer, and deployment scripts&lt;br&gt;&lt;br&gt;
03 Paper trading with at least 30 signals before going live prevented two strategy failures that would have cost real money&lt;br&gt;&lt;br&gt;
04 The biggest technical challenge was not the trading logic but state recovery after process restarts&lt;br&gt;&lt;br&gt;
05 Polymarket’s CLOB API requires careful order book analysis because liquidity varies dramatically between markets — and TWAP-resolved markets demand even tighter depth checks around resolution windows&lt;/p&gt;
&lt;h2&gt;
  
  
  Why this matters
&lt;/h2&gt;

&lt;p&gt;I built a production algorithmic trading system using Python, Claude Code for development, Polymarket’s CLOB API for execution, and Polymarket’s public RTDS WebSocket for live Chainlink TWAP price updates (30-second and 60-second windows). This guide covers the full architecture: signal generation from TWAP streams, position management, exit strategies, and the paper-to-live progression that prevented costly mistakes.&lt;/p&gt;

&lt;p&gt;A production Python trading bot needs five core modules to run continuously without losing state: signal generation, position management, exit strategies, state persistence, and health monitoring. I built this system using Python and Claude Code across a 4,000-line codebase, with Polymarket RTDS Chainlink TWAP feeds for signals and the CLOB for execution. Paper trading at least 30 signals over 6 weeks before going live prevented two strategy failures — a liquidity trap near TWAP settlement windows and a signal-timing issue during low-liquidity hours — that would have cost real money.&lt;/p&gt;
&lt;h2&gt;
  
  
  System Architecture Overview
&lt;/h2&gt;

&lt;p&gt;When I started building a trading bot, I expected the hard part to be the trading logic. It wasn’t. The hard part was building a system that could run continuously for weeks without losing state, crashing silently, or entering impossible positions — especially once Polymarket switched crypto up/down markets to TWAP-based resolution (5-minute markets on 30s TWAP, 15-minute and 4-hour markets on 60s TWAP).&lt;/p&gt;

&lt;p&gt;A production trading bot needs five core modules that work together:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Signal Generation&lt;/strong&gt; — Monitors live Chainlink TWAP updates via Polymarket RTDS and generates trade signals
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Position Management&lt;/strong&gt; — Executes trades, tracks holdings, and prevents overlapping positions
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit Strategies&lt;/strong&gt; — Knows when to close positions and takes profits or cuts losses
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;State Persistence&lt;/strong&gt; — Survives process crashes, power failures, and restarts
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Health Monitoring&lt;/strong&gt; — Detects stuck orders, orphaned positions, and API failures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each module can fail independently, so the system needs to handle partial failures gracefully. A TWAP signal can fail without crashing position management. An API call can timeout without losing the position state. The monitoring system watches everything and alerts when something goes wrong.&lt;/p&gt;

&lt;p&gt;The entire codebase is about 4,000 lines of Python. Claude Code wrote 95% of it, including the most complex parts: the asyncio event loop, the database schema and queries, and the deployment scripts.&lt;/p&gt;

&lt;p&gt;Note: The repo is private for now, but I'm planning to open source the core trading logic once it's hardened further.&lt;/p&gt;
&lt;h3&gt;
  
  
  How Does Signal Generation Work?
&lt;/h3&gt;

&lt;p&gt;Signals are the input to the entire system. My signals come from Polymarket’s RTDS Chainlink TWAP feeds (no Chainlink credentials required).&lt;/p&gt;

&lt;p&gt;Polymarket RTDS delivers real-time 30-second and 60-second Chainlink TWAP updates over a public WebSocket. I subscribe to topics such as &lt;code&gt;crypto_prices_twap_thirty&lt;/code&gt; and &lt;code&gt;crypto_prices_twap_sixty&lt;/code&gt; for pairs like &lt;code&gt;btc/usd&lt;/code&gt;, &lt;code&gt;eth/usd&lt;/code&gt;, etc. I watch consecutive TWAP prints and detect momentum breakouts when the latest TWAP moves more than 2-sigma relative to the recent window of TWAP values. When a TWAP breakout occurs, I look for corresponding Polymarket up/down prediction markets that are still underpriced relative to the new TWAP trajectory.&lt;/p&gt;

&lt;p&gt;The key insight is that prediction-market prices still lag the official TWAP updates by 15–60 seconds in many cases, creating a small window to position ahead of the eventual resolution source.&lt;/p&gt;
&lt;h4&gt;
  
  
  The TWAP Momentum Window
&lt;/h4&gt;

&lt;p&gt;Here’s how the signal generation actually works in code (using the official &lt;code&gt;polymarket-client&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AsyncPublicClient&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;polymarket.streams&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;CryptoPricesChainlinkTwapSpec&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;collections&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;detect_twap_breakout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twap_history&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;current_twap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;float&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Watch recent Chainlink TWAP values (30s or 60s window) and detect 2-sigma breakouts.
    Returns signal strength (0-1) if breakout detected.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twap_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;values&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;list&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twap_history&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;mean&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;variance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nf"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;std_dev&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;variance&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;std_dev&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

    &lt;span class="n"&gt;z_score&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;current_twap&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;mean&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;std_dev&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;z_score&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;2.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Upside breakout on TWAP
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;z_score&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# Cap at 3-sigma
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;

&lt;span class="c1"&gt;# Example subscription loop
&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;stream_twap_signals&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="n"&gt;history&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;deque&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maxlen&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="nc"&gt;AsyncPublicClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nc"&gt;CryptoPricesChainlinkTwapSpec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;window_seconds&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;symbols&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;btc/usd&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;stream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                &lt;span class="n"&gt;twap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;float&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="n"&gt;strength&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;detect_twap_breakout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;twap&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;strength&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
                    &lt;span class="c1"&gt;# Emit signal to position manager queue
&lt;/span&gt;                    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;signal_queue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;put&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;symbol&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;twap&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;twap&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;window_s&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;window_seconds&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;strength&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;strength&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ts&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timestamp&lt;/span&gt;
                    &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When a signal fires, the system calculates how many standard deviations the latest TWAP has moved above the recent mean of TWAP prints. A 2-sigma TWAP move is rare; when it lines up with an underpriced Polymarket market that resolves on the same TWAP feed, the edge becomes real.&lt;/p&gt;

&lt;p&gt;The efficiency gap exists because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Official Chainlink TWAP updates arrive via RTDS (fast and authoritative)
&lt;/li&gt;
&lt;li&gt;Retail prediction-market traders react more slowly to the new TWAP level
&lt;/li&gt;
&lt;li&gt;Markets that resolve on the exact same 30s/60s TWAP still show temporary mispricing in the order book&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This isn’t an edge that lasts forever. As more bots subscribe to the same public RTDS feed, the 15–60 second window compresses. But for now, it’s consistent enough to trade.&lt;/p&gt;

&lt;p&gt;Signals feed into a queue. The position manager processes signals one at a time, ensuring we never accidentally open two positions on the same market.&lt;/p&gt;

&lt;h3&gt;
  
  
  How Does Position Management Work?
&lt;/h3&gt;

&lt;p&gt;Once a TWAP signal arrives, the position manager decides: do we take this trade, or skip it?&lt;/p&gt;

&lt;p&gt;The decision logic checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do we already have a position in this market? If yes, skip.
&lt;/li&gt;
&lt;li&gt;Is the order book deep enough to execute at reasonable prices? If no, skip.
&lt;/li&gt;
&lt;li&gt;Has this market been active for more than 24 hours? Recent markets are illiquid.
&lt;/li&gt;
&lt;li&gt;Are we at our maximum concurrent positions? If yes, skip.
&lt;/li&gt;
&lt;li&gt;Is the market’s resolution window (5m / 15m / 4h) still far enough from the TWAP settlement window that we have room to exit?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If all checks pass, the position manager places a limit order on the Polymarket CLOB. The CLOB is Polymarket’s central limit order book. It’s lower latency than the REST API but requires understanding the order book structure — especially critical now that resolution is driven by the same TWAP feeds we are monitoring.&lt;/p&gt;

&lt;p&gt;The position manager tracks every open position in SQLite. Each position stores:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Market ID and outcome tokens
&lt;/li&gt;
&lt;li&gt;Entry price and quantity
&lt;/li&gt;
&lt;li&gt;Timestamp and signal strength (from TWAP z-score)
&lt;/li&gt;
&lt;li&gt;Current mark-to-market value
&lt;/li&gt;
&lt;li&gt;Status (open, closing, closed)
&lt;/li&gt;
&lt;li&gt;Linked TWAP window (30s or 60s) and symbol
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This database survives process restarts. On startup, the position manager reads the database and reconstructs the exact state it was in before the crash.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Exit Strategies Actually Work?
&lt;/h3&gt;

&lt;p&gt;The hardest part of algorithmic trading is exits. Most retail traders focus on entries but skip profitable or know when to close positions. It’s the difference between “cool idea” and “actual profit.”&lt;/p&gt;

&lt;p&gt;I use three exit types:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Profit target&lt;/strong&gt; — Close 50% of position at 2% profit, rest at 5% profit
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stop loss&lt;/strong&gt; — Close entire position if it drops 3% below entry
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Time decay / TWAP proximity&lt;/strong&gt; — If a position hasn’t moved in 4 hours, or if the market is approaching its TWAP resolution window with no edge left, close it (markets that aren’t moving are wasting capital)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The exit manager runs every minute, checks all open positions against the latest RTDS TWAP and market mid, and executes exits that meet criteria. It places exit orders as limit orders too, so we get the best available prices.&lt;/p&gt;

&lt;h4&gt;
  
  
  The Math on Asymmetric Position Sizing
&lt;/h4&gt;

&lt;p&gt;Here’s why the split profit target works. Say I enter a position at $0.45 on a binary market with $100 per trade:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Winning trades (55% of the time):&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Exit 50% at $0.459 (2% profit): +$0.90
&lt;/li&gt;
&lt;li&gt;Exit remaining 50% at $0.4725 (5% profit): +$2.25
&lt;/li&gt;
&lt;li&gt;Total on winner: +$3.15 (3.15% return on $100)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Losing trades (45% of the time):&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stop loss hits at $0.4365 (3% below entry): -$3.00
&lt;/li&gt;
&lt;li&gt;Total on loser: -$3.00 (-3% return on $100)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Expected value calculation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EV = (0.55 × $3.15) + (0.45 × -$3.00)
EV = $1.73 + (-$1.35)
EV = +$0.38 per $100 bet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s positive EV at a 55% win rate. Drop to 54% and the math flips negative. This is why signal quality (TWAP z-score strength) matters more than quantity. A 60% win rate turns $0.38 per $100 into $0.60 per $100. Signal strength compounds.&lt;/p&gt;

&lt;p&gt;The split exit structure protects against reversal. If the market hits 2% and I’ve already cashed out half, the second half can either hit 5% or get stopped out. Either way, I’ve locked 50% of the winning outcome. That’s risk management.&lt;/p&gt;

&lt;p&gt;The asymmetry is deliberate. I lose 3% on losers but capture 2-5% on winners because prices on TWAP-resolved markets still bounce. A tight 1% stop gets triggered by noise. A 3% stop lets the position breathe.&lt;/p&gt;

&lt;h4&gt;
  
  
  State Tracking for Reliable Exits
&lt;/h4&gt;

&lt;p&gt;The position database tracks exit status for each open position:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;positions&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;market_id&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;entry_price&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;entry_qty&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;entry_time&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;stop_loss_price&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="c1"&gt;-- 0.4365 for 0.45 entry&lt;/span&gt;
    &lt;span class="n"&gt;target_one_price&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;-- 0.459 (2% profit)&lt;/span&gt;
    &lt;span class="n"&gt;target_two_price&lt;/span&gt; &lt;span class="nb"&gt;REAL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="c1"&gt;-- 0.4725 (5% profit)&lt;/span&gt;
    &lt;span class="n"&gt;exit_status&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="c1"&gt;-- 'open', 'half_closed', 'closing', 'closed'&lt;/span&gt;
    &lt;span class="n"&gt;target_one_filled_at&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;target_two_filled_at&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;twap_window&lt;/span&gt; &lt;span class="nb"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="c1"&gt;-- 30 or 60&lt;/span&gt;
    &lt;span class="n"&gt;linked_symbol&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt;         &lt;span class="c1"&gt;-- e.g. 'btc/usd'&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On every minute, the exit manager reads the latest RTDS TWAP and current market price and compares against these thresholds. When target one hits, it updates exit_status to ‘half_closed’ and records the fill time. This prevents double-exits and ensures the second half of the position doesn’t exit prematurely.&lt;/p&gt;

&lt;p&gt;Limit orders are crucial here. Market orders on Polymarket can slip 0.5-1% depending on order book depth. A limit order at target_one_price of $0.459 sits on the book until filled. If the market only reaches $0.458, the order stays open. If it bounces to $0.461, it fills at $0.459 (better than market order at $0.461). Over 100 trades, limit order precision saves 0.3-0.5% in aggregate slippage.&lt;/p&gt;

&lt;p&gt;The real lesson: don’t set stop losses too tight on TWAP-resolved prediction markets. Binary outcomes mean prices bounce around more than equity markets. A 1% stop gets triggered by noise. 3% gives the position room to breathe while still protecting against real reversals.&lt;/p&gt;

&lt;p&gt;The trickiest exit is time decay near the TWAP window. As the market approaches resolution, prices converge hard to the TWAP path. If I’m long and the market isn’t moving with the TWAP, the time decay works against me. Exiting stale positions frees capital for new TWAP signals.&lt;/p&gt;

&lt;p&gt;One thing that surprised me: the time-decay / TWAP-proximity exit generated more total profit than the pure profit-target exit. Not because individual exits were bigger, but because freeing stale capital meant the bot could take 2-3 more trades per day. Capital velocity matters more than any single trade’s P&amp;amp;L.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do You Transition from Paper Trading to Live?
&lt;/h2&gt;

&lt;p&gt;I paper-traded for 6 weeks before going live. Paper trading means simulating trades without real money, just tracking P&amp;amp;L against live RTDS TWAP feeds and CLOB order books.&lt;/p&gt;

&lt;p&gt;Paper trading revealed two strategy failures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Liquidity trap near TWAP windows&lt;/strong&gt; — The culprit was insidious: entry prices looked good because I was catching markets right after a TWAP update, when stale limit orders still sat on the books. But exit? Nightmare. On markets with under $50K order book depth, especially in the final minutes before the 30s/60s TWAP settlement, I’d win the entry at $0.45 then get forced out at $0.42 because no one was buying. The tight spread at entry reversed hard at exit. Across 30 paper trades, this cost pattern showed up 7 times. Each time: entry P&amp;amp;L looked profitable (+2-3%), but the exit slippage erased it. One trade: up $2.25 on 50% exit at 2% profit, then the final 50% couldn’t execute near target. Ended up closing at $0.41 (-4% from entry) because the order book evaporated near the TWAP window. That single trade went from +$3 to -$1. Multiply that by 7 failed exits across the paper period, and I’m looking at roughly $2,000 in prevented losses once I added the liquidity + proximity check.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The fix was a simple gate before position entry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;check_market_liquidity_and_twap_window&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;twap_window&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Only enter if order book has sufficient depth AND we are not too close to the TWAP resolution window.
    Skip if spread &amp;gt; 1% of mid-price or total depth &amp;lt; threshold.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;order_book&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;polymarket&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_order_book&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order_book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;order_book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;price&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;best_bid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;best_ask&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;
    &lt;span class="n"&gt;spread_pct&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;best_ask&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;best_bid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;

    &lt;span class="n"&gt;total_depth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qty&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;qty&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;order_book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;bids&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; \
                  &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;qty&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;qty&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;order_book&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;asks&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;spread_pct&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Spread too wide
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;total_depth&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;  &lt;span class="c1"&gt;# Not enough size to exit
&lt;/span&gt;        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="c1"&gt;# Extra guard: skip if market closes within 2× the TWAP window
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nf"&gt;seconds_to_resolution&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;market_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;twap_window&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This single filter would have prevented 7 bad trades and saved ~$2,000 in real losses.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Signal timing on thin TWAP books&lt;/strong&gt; — The second failure was time-dependent. TWAP signals arriving during European market hours (roughly 2-8 AM UTC, when US traders sleep) got filled at punishment prices. Same TWAP move, same market, but the order book was thin and slow-moving. I’d get a 30s/60s TWAP breakout at 5 AM UTC. By the time I placed the order, retail traders on Polymarket hadn’t woken up yet. Bid-ask spread was 0.5-1% instead of 0.2%. Fills were 200-300 basis points worse than signals arriving during US peak hours (12pm-11pm UTC). Over the 30 paper trades, only 6 arrived during European dead hours, but those 6 had 0.5-1% worse fills than identical TWAP signals during US hours. That’s roughly $1,500 in prevented slippage if I’d filtered those out.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The time-of-day filter was even simpler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;is_peak_trading_hour&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;
    Only process TWAP signals during peak US trading hours.
    12pm-11pm UTC captures most US market activity.
    &lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;now_utc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;datetime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;utcnow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;current_hour&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;now_utc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;hour&lt;/span&gt;

    &lt;span class="c1"&gt;# Peak hours: 12pm-11pm UTC (7am-6pm EST)
&lt;/span&gt;    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="mi"&gt;12&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;current_hour&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;should_process_signal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;is_peak_trading_hour&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;False&lt;/span&gt;  &lt;span class="c1"&gt;# Skip this TWAP signal
&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="bp"&gt;True&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. One hour check prevented $1,500 in unnecessary slippage by avoiding markets where the book moves like molasses around live TWAP updates.&lt;/p&gt;

&lt;p&gt;Both failures would have cost real money live. The 6-week cost in time was worth it.&lt;/p&gt;

&lt;p&gt;I ran at least 30 paper trades before going live. That’s the minimum to see the major failure modes once you’re trading against the official Chainlink TWAP feeds. Anything less and you’re just guessing.&lt;/p&gt;

&lt;p&gt;Find us on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Youtube: &lt;a href="https://youtube.com/@bosonax" rel="noopener noreferrer"&gt;https://youtube.com/@bosonax&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Telegram: &lt;a href="https://t.me/bosonax" rel="noopener noreferrer"&gt;https://t.me/bosonax&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;X: &lt;a href="https://x.com/xxniiinxx" rel="noopener noreferrer"&gt;https://x.com/xxniiinxx&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Python #trading #bot #Polymarket #Chainlink #TWAP #algorithmic #CLOB #API #prediction #markets #crypto #bot #paper #trading #live #trading #asyncio #Claude #Code #RTDS #order #book #exit #strategies #signal #generation #risk #management #TWAP #resolution
&lt;/h1&gt;

</description>
      <category>polymarket</category>
      <category>twap</category>
      <category>trading</category>
      <category>strategy</category>
    </item>
    <item>
      <title>What Is Price Action? - Price Action Trading Introduction</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Tue, 11 Aug 2026 15:12:22 +0000</pubDate>
      <link>https://dev.to/xniiinx/what-is-price-action-price-action-trading-introduction-2df8</link>
      <guid>https://dev.to/xniiinx/what-is-price-action-price-action-trading-introduction-2df8</guid>
      <description>&lt;p&gt;&lt;strong&gt;What is Price Action? - Price Action Trading Explained&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Price action trading is a methodology for financial market speculation which consists of the analysis of basic price movement across time. It's used by many retail traders and often by institutional traders and hedge fund managers to make predictions on the future direction of the price of a security or financial market.&lt;/p&gt;

&lt;p&gt;Put simply, price action is how price changes, i.e., the 'action' of price. It's most easily observed in markets with high liquidity and volatility, but really anything that is bought or sold in a free market will generate price action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnyfa00lzv94kjzlkboc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frnyfa00lzv94kjzlkboc.png" alt=" " width="639" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Price action trading ignores the fundamental factors that influence a market's movement, and instead it looks primarily at the market's price history, that is to say its price movement across a period of time. Thus, price action is a form of technical analysis, but what differentiates it from most forms of technical analysis is that its main focus is on the relationship of a market's current price to its past or recent prices, as opposed to 'second-hand' values that are derived from that price history.&lt;/p&gt;

&lt;p&gt;In other words, price action trading is a 'pure' form of technical analysis since it includes no second-hand, price-derived indicators. Price action traders are solely concerned with the first-hand data a market generates about itself; its price movement over time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Price action analysis allows a trader to make sense of a market's price movement and provides him or her with explanations that serve as a way for the trader to build a mental scenario to describe the current market structure. Experienced price action traders often attribute their unique mental understanding and 'gut feel' of a market as the main reason for their profitable trading.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Price action traders make use of the past history of a market's price movement, most typically focusing on the recent price action of the last 3 to 6 months, with a lighter focus on more distant price history. This price history includes swing highs and swing lows in a market, as well as support and resistance levels.&lt;/p&gt;

&lt;p&gt;A trader can use a market's price action to try and describe the human thought process behind a market's movement. Every participant in a market will leave price action 'clues' on a market's price chart as they trade their markets; these clues can then be interpreted and used to try and predict the next move in a market.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Price Action Trading - Keeping it Simple&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Price action traders often use the phrase "Keep It Simple Stupid" in reference to the fact that trading is something many people over-complicate by clouding their charts with numerous technical indicators and generally over-analyzing a market.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Price action trading is also sometimes referred to as 'clean chart trading', 'naked trading', or 'raw or natural trading', in reference to trading from a simple price action only price chart.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The simple stripped-down approach of price action trading means there are no indicators on a trader's charts and no economic events or news is used in making one's trading decisions. The sole focus is on a market's price action, and the belief amongst price action traders is that this price action reflects all the variables (news events, economic data etc.) that influence a market and cause it to move. Therefore, the implication is that it's much simpler to just analyze a market and trade from its price action, rather than trying to decipher and sort the many different variables affecting a market each day.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Price Action Trading Strategies (Patterns)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Price action patterns, also called price action 'triggers', 'setups' or 'signals', are really the most important aspect of price action trading, because it's these patterns that provide a trader with strong clues as to what price might do next. Examples of some simple price action trading strategies include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside bar pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A two-bar pattern consisting of the inside bar and the prior bar (usually called the "mother bar"). The inside bar is contained completely within the high to low range of the mother bar. This strategy is commonly used as a breakout pattern in trending markets, but it can also be traded as a reversal signal if it forms at a key chart level.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5e82wq2d71qbywypgyj4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5e82wq2d71qbywypgyj4.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pin bar pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consists of a single candlestick and shows rejection of price and a reversal in the market. It works well in trending markets, range-bound markets, and can also be traded counter-trend from a key support or resistance level. The pin bar implies that price might move opposite from the direction the tail is pointing, as the tail shows rejection of price and a reversal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4x4b3exthd4u5glig36q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4x4b3exthd4u5glig36q.png" alt=" " width="799" height="447"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fakey pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Consists of a false breakout of an inside bar pattern. If an inside bar pattern breaks out briefly but then reverses and closes back within the range of the mother bar or inside bar, you have a fakey. It's called a "fakey" because it fakes you out - the market looks like it's breaking one way but then comes back in the opposite direction. Fakeys work well with trends, against trends from key levels, and in trading ranges.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnjyp8wgewljlqxrs9mbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnjyp8wgewljlqxrs9mbr.png" alt=" " width="800" height="817"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trading with Price Action Patterns&lt;/strong&gt;&lt;br&gt;
The article provides real-world chart examples (described in text), including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bearish fakey sell signal in a downtrend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fknirwilkcz1vzay06jrf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fknirwilkcz1vzay06jrf.png" alt=" " width="800" height="634"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A bullish fakey pin bar combo setup in an upward market.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqi0m1ba0cmq0v9f5sylf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqi0m1ba0cmq0v9f5sylf.png" alt=" " width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Inside bar and inside pin bar combo setups in trending markets.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3tbonrwgzl1dlcm9fg0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3tbonrwgzl1dlcm9fg0z.png" alt=" " width="800" height="615"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pin bar buy signals with long tails that led to large up moves.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhcdbwq4b6s4zikgy12za.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhcdbwq4b6s4zikgy12za.png" alt=" " width="800" height="637"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Trading Price Action Patterns with Confluence&lt;/strong&gt;&lt;br&gt;
Trading with price action signals is not only about the signal itself, but also about where the signal forms on the chart. The best signals form at 'confluent' points (where multiple factors align), such as a pin bar in the direction of an uptrend at a support level. The more confluent factors supporting a signal, the higher-probability it is considered to be.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F67528mus3qv0nlz56r73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F67528mus3qv0nlz56r73.png" alt=" " width="800" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;
The article states that readers now have a solid basic understanding of what price action is and how to trade it, and encourages expanding knowledge further. It promotes the author's price action trading course for more in-depth strategies and professional insights.&lt;/p&gt;

&lt;h1&gt;
  
  
  Howto #Crypto #Polymarket #Trading #Strategy
&lt;/h1&gt;

</description>
      <category>polymarket</category>
      <category>strategy</category>
      <category>crypto</category>
      <category>trading</category>
    </item>
    <item>
      <title>Polymarket Crypto Up/Down Markets Are Switching to Chainlink TWAP — Here’s How It Would Have Changed the Last 150 Markets Per Asset</title>
      <dc:creator>Bo$onaX</dc:creator>
      <pubDate>Mon, 03 Aug 2026 20:40:21 +0000</pubDate>
      <link>https://dev.to/xniiinx/polymarket-crypto-updown-markets-are-switching-to-chainlink-twap-heres-how-it-would-have-2adp</link>
      <guid>https://dev.to/xniiinx/polymarket-crypto-updown-markets-are-switching-to-chainlink-twap-heres-how-it-would-have-2adp</guid>
      <description>&lt;h3&gt;
  
  
  What’s changing on August 7
&lt;/h3&gt;

&lt;p&gt;Starting &lt;strong&gt;August 7, 2026 at 00:00 UTC&lt;/strong&gt;, Polymarket’s crypto up/down markets will stop resolving against a single snapshot price at market close.&lt;/p&gt;

&lt;p&gt;Instead, resolution will use a &lt;strong&gt;Chainlink-computed Time-Weighted Average Price (TWAP)&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;5-minute markets&lt;/strong&gt; → 30-second Chainlink TWAP
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;15-minute markets&lt;/strong&gt; → 60-second Chainlink TWAP
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;4-hour markets&lt;/strong&gt; → 60-second Chainlink TWAP
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;target price (price-to-beat)&lt;/strong&gt; stays exactly the same. Only the closing reference changes.&lt;/p&gt;

&lt;p&gt;This is a deliberate move to protect market integrity and reduce the impact of last-second price spikes or thin liquidity at the exact close. Polymarket is also adding &lt;strong&gt;$1M in liquidity rewards&lt;/strong&gt; across the affected markets throughout August.&lt;/p&gt;

&lt;p&gt;Chainlink mainnet TWAP feeds are already live. Polymarket’s Real-Time Data Streaming (RTDS) WebSocket for TWAP is scheduled for &lt;strong&gt;August 4&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Official docs: &lt;a href="https://docs.polymarket.com/market-data/chainlink-twap" rel="noopener noreferrer"&gt;Chainlink TWAP Prices on Polymarket&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Historical impact: How many outcomes would have flipped?
&lt;/h3&gt;

&lt;p&gt;I pulled the last 50 closed markets for each interval (5m / 15m / 4h) across the major assets and compared:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Snapshot close&lt;/strong&gt; (current resolution method)
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chainlink TWAP&lt;/strong&gt; (new resolution method)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Across 150 recent markets per asset, TWAP would have flipped the outcome in:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Asset&lt;/th&gt;
&lt;th&gt;Flips&lt;/th&gt;
&lt;th&gt;Max absolute difference&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;BTC&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;6.18 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ETH&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;7.05 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;XRP&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;8.43 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SOL&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;9.59 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DOGE&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;11.77 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BNB&lt;/td&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;11.13 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HYPE&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;11.67 bps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The differences are small in absolute terms (most under 12 basis points), but in binary up/down markets that can be enough to flip the result when price is right at the target.&lt;/p&gt;

&lt;h3&gt;
  
  
  Visuals from the analysis
&lt;/h3&gt;

&lt;p&gt;Here are the charts comparing Target (yellow), Snapshot close (blue), and TWAP (teal) for the last 50 markets of each interval:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BTC:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3n3mikpa1v3r0z6b1xr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3n3mikpa1v3r0z6b1xr3.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ETH:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd8jp241rjxjqm3mvhcta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd8jp241rjxjqm3mvhcta.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SOL:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq35z7vkmu8y475upi96r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq35z7vkmu8y475upi96r.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;XRP:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3b2wgzstcnaxz0emfz0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3b2wgzstcnaxz0emfz0.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;BNB: / DOGE: / HYPE:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbg0rx7pvcbuv4d21qfbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbg0rx7pvcbuv4d21qfbv.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffnlludfpuzv6k3qx3w45.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffnlludfpuzv6k3qx3w45.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6pkzyev1x9qg2d9r8lfi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6pkzyev1x9qg2d9r8lfi.png" alt=" " width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source data came from the Vatic API (&lt;code&gt;/api/v1/twap/recent&lt;/code&gt;). Snapshot close = Chainlink report at market end. TWAP = Chainlink-computed 30s/60s Data Streams report.&lt;/p&gt;




&lt;h3&gt;
  
  
  Why this matters for traders and builders
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Last-second sniping becomes less effective.&lt;/strong&gt; A single tick at the exact close no longer decides the market.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bots and strategies that rely on the final snapshot need to adapt.&lt;/strong&gt; You’ll want the TWAP value (or a running approximation) in the final 30–60 seconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Edge cases near the target price become more interesting.&lt;/strong&gt; Small differences that previously didn’t matter can now flip outcomes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developers get cleaner, more robust oracle data.&lt;/strong&gt; Chainlink Data Streams + upcoming Polymarket RTDS give low-latency access to the exact resolution reference.&lt;/li&gt;
&lt;/ol&gt;




&lt;h3&gt;
  
  
  Getting the data
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Chainlink Data Streams&lt;/strong&gt; (available now)&lt;br&gt;&lt;br&gt;
Use your existing credentials. Feed IDs for 30s and 60s TWAP are on &lt;a href="https://data.chain.link/streams" rel="noopener noreferrer"&gt;data.chain.link/streams&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Polymarket RTDS&lt;/strong&gt; (live August 4)&lt;br&gt;&lt;br&gt;
No credentials required. Topic: &lt;code&gt;prices.crypto.chainlink.twap&lt;/code&gt; with &lt;code&gt;windowSeconds: 30 | 60&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vatic API&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
We’re adding full support so you can pull in one place:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Target price / price-to-beat
&lt;/li&gt;
&lt;li&gt;Snapshot close
&lt;/li&gt;
&lt;li&gt;Chainlink TWAP resolution reference
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Get API keys: &lt;a href="https://platform.vatic.trading/landing" rel="noopener noreferrer"&gt;https://platform.vatic.trading/landing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lowest-latency target price streaming + WebSocket guides are already available.&lt;/p&gt;




&lt;h3&gt;
  
  
  Bottom line
&lt;/h3&gt;

&lt;p&gt;The change is modest in basis-point terms but meaningful for binary market outcomes. Most historical markets would have resolved the same way. A non-trivial minority would have flipped — especially on the more volatile assets.&lt;/p&gt;

&lt;p&gt;If you’re running market-making, arb, or directional bots on Polymarket crypto up/down, now is the time to switch your resolution reference from snapshot to TWAP.&lt;/p&gt;

&lt;p&gt;Questions or want the raw data behind the charts? Drop a comment or reach out.&lt;/p&gt;

</description>
      <category>polymarket</category>
      <category>chainlink</category>
      <category>predictionmarkets</category>
      <category>twap</category>
    </item>
  </channel>
</rss>
