<?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: BlueWhale-Quant-Lab</title>
    <description>The latest articles on DEV Community by BlueWhale-Quant-Lab (@bluewhale-quant-lab).</description>
    <link>https://dev.to/bluewhale-quant-lab</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3962470%2F1edf261b-05ad-48cc-ac61-6658c360ff8e.png</url>
      <title>DEV Community: BlueWhale-Quant-Lab</title>
      <link>https://dev.to/bluewhale-quant-lab</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bluewhale-quant-lab"/>
    <language>en</language>
    <item>
      <title>Fixing Polymarket's "invalid amounts" error on the CLOB (py-clob-client)</title>
      <dc:creator>BlueWhale-Quant-Lab</dc:creator>
      <pubDate>Mon, 01 Jun 2026 14:05:03 +0000</pubDate>
      <link>https://dev.to/bluewhale-quant-lab/fixing-polymarkets-invalid-amounts-error-on-the-clob-py-clob-client-2j16</link>
      <guid>https://dev.to/bluewhale-quant-lab/fixing-polymarkets-invalid-amounts-error-on-the-clob-py-clob-client-2j16</guid>
      <description>&lt;h1&gt;
  
  
  Fixing Polymarket's "invalid amounts" error on the CLOB (py-clob-client)
&lt;/h1&gt;

&lt;p&gt;If you've posted an order to Polymarket's CLOB with &lt;code&gt;py-clob-client&lt;/code&gt; and gotten&lt;br&gt;
back a flat &lt;strong&gt;&lt;code&gt;invalid amounts&lt;/code&gt;&lt;/strong&gt; — even though your size looks fine and you&lt;br&gt;
rounded it to two decimals — here's what's actually going on, and a one-line fix.&lt;/p&gt;
&lt;h2&gt;
  
  
  The undocumented rule
&lt;/h2&gt;

&lt;p&gt;A CLOB order carries two integer amounts (scaled by 1e6). Both must be whole&lt;br&gt;
multiples of &lt;code&gt;10000&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="n"&gt;makerAmount&lt;/span&gt; &lt;span class="o"&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;size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt;     &lt;span class="c1"&gt;# multiple of 10000
&lt;/span&gt;&lt;span class="n"&gt;takerAmount&lt;/span&gt; &lt;span class="o"&gt;=&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;1_000_000&lt;/span&gt;     &lt;span class="c1"&gt;# multiple of 10000
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;round(size, 2)&lt;/code&gt; isn't enough. Concrete example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;price = 0.82, size = 6.25
makerAmount = 0.82 * 6.25 * 1e6 = 5_125_000
5_125_000 % 10000 = 5000   -&amp;gt;  invalid amounts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The catch: the &lt;em&gt;valid step for size depends on the price&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix
&lt;/h2&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;math&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;size_step_units&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="c1"&gt;# in 1/10000-share units
&lt;/span&gt;    &lt;span class="n"&gt;p_int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&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="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="n"&gt;maker_step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gcd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p_int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1_000_000&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;maker_step&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gcd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;maker_step&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="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;round_for_fok&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="n"&gt;p&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="mf"&gt;0.01&lt;/span&gt;&lt;span class="p"&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;0.99&lt;/span&gt;&lt;span class="p"&gt;,&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="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;size_step_units&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;units&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&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;size&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;step&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;,&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;units&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;round_for_fok(0.82, 6.25)&lt;/code&gt; → &lt;code&gt;(0.82, 6.0)&lt;/code&gt;, and now both amounts are valid. I&lt;br&gt;
packaged this (plus a &lt;code&gt;$1&lt;/code&gt; / 5-share minimum-order check) as a tiny MIT tool:&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/BlueWhale-Quant-Lab/polymarket-clob-order-amount-tick-size" rel="noopener noreferrer"&gt;https://github.com/BlueWhale-Quant-Lab/polymarket-clob-order-amount-tick-size&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Two more traps on the daily markets
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;invalid tick size&lt;/code&gt;&lt;/strong&gt; — the daily ("...on June 1") markets use a &lt;strong&gt;0.001&lt;/strong&gt;
tick, not 0.01. Hard-coding &lt;code&gt;tick_size="0.01"&lt;/code&gt; gets them rejected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 10-share minimum step&lt;/strong&gt; — at prices like &lt;code&gt;0.999&lt;/code&gt;, the smallest &lt;em&gt;valid&lt;/em&gt;
size step is &lt;strong&gt;10 shares&lt;/strong&gt;, so a sub-10-share order at that price is impossible.
You either round up or move the price.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And if you &lt;em&gt;rest&lt;/em&gt; GTC orders, flooring the size loses shares to the fee skim and&lt;br&gt;
can leave your two legs unbalanced (No &amp;gt; Yes); you want nearest-rounding with a&lt;br&gt;
±tick price search instead. Those are in the PRO build&lt;br&gt;
&lt;a href="https://bluewhalequantlab.gumroad.com/l/polymarket-clob-order-amount-tick-size-pro" rel="noopener noreferrer"&gt;here&lt;/a&gt;,&lt;br&gt;
but the free tool above fixes the common &lt;code&gt;invalid amounts&lt;/code&gt; case for everyone.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(This is order-amount math — not order placement, signing, or any profit claim.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>crypto</category>
      <category>trading</category>
    </item>
    <item>
      <title>How to get a Polymarket event slug (and the CLOB token IDs) for Up/Down markets</title>
      <dc:creator>BlueWhale-Quant-Lab</dc:creator>
      <pubDate>Mon, 01 Jun 2026 13:37:41 +0000</pubDate>
      <link>https://dev.to/bluewhale-quant-lab/how-to-get-a-polymarket-event-slug-and-the-clob-token-ids-for-updown-markets-6o4</link>
      <guid>https://dev.to/bluewhale-quant-lab/how-to-get-a-polymarket-event-slug-and-the-clob-token-ids-for-updown-markets-6o4</guid>
      <description>&lt;h1&gt;
  
  
  How to get a Polymarket event slug (and the CLOB token IDs) for Up/Down markets
&lt;/h1&gt;

&lt;p&gt;If you've tried to automate anything around Polymarket's crypto &lt;strong&gt;"Up or Down"&lt;/strong&gt;&lt;br&gt;
markets, you've probably hit this wall: the Gamma API will happily return an&lt;br&gt;
event &lt;strong&gt;if you already know its slug&lt;/strong&gt; —&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://gamma-api.polymarket.com/events?slug=btc-updown-5m-1780319100
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;— but nothing documents how to &lt;strong&gt;build&lt;/strong&gt; that slug in the first place. Searching&lt;br&gt;
&lt;em&gt;"polymarket event slug"&lt;/em&gt;, &lt;em&gt;"polymarket get market by slug"&lt;/em&gt;, or &lt;em&gt;"polymarket clob&lt;br&gt;
token id"&lt;/em&gt; turns up almost nothing. Here's the format, and a small open-source&lt;br&gt;
tool that does it for you.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why the slug matters
&lt;/h2&gt;

&lt;p&gt;On Polymarket the slug is the key that unlocks everything else:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;slug ──/events?slug=──▶ event ──▶ markets[0].clobTokenIds ──▶ order book / price
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No slug, no market id, no CLOB token id, no condition id. So building the slug&lt;br&gt;
deterministically is step one of any read or trade automation.&lt;/p&gt;
&lt;h2&gt;
  
  
  The easy case: 5-minute and 15-minute markets
&lt;/h2&gt;

&lt;p&gt;These two timeframes use a plain UTC timestamp:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{asset}-updown-{tf}-{unix_timestamp}

btc-updown-5m-1780319100
eth-updown-15m-1780318800
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;t_start&lt;/code&gt; is just a UTC floor:&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;get_t_start&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tf&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;dur&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;5m&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;15m&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;900&lt;/span&gt;&lt;span class="p"&gt;}[&lt;/span&gt;&lt;span class="n"&gt;tf&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="nf"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;//&lt;/span&gt; &lt;span class="n"&gt;dur&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;dur&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it — no timezone, no daylight saving. There's a tiny MIT-licensed tool&lt;br&gt;
that builds these and (optionally) calls Gamma to hand you the token IDs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python polymarket_slug.py btc 5m &lt;span class="nt"&gt;--resolve&lt;/span&gt;
&lt;span class="c"&gt;# slug   : btc-updown-5m-1780319100&lt;/span&gt;
&lt;span class="c"&gt;# title  : Bitcoin Up or Down - June 1, 9:05AM-9:10AM ET&lt;/span&gt;
&lt;span class="c"&gt;# tokens : ['632187004239...', '502984638552...']&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repo: &lt;strong&gt;&lt;a href="https://github.com/BlueWhale-Quant-Lab/polymarket-updown-event-slug-generator" rel="noopener noreferrer"&gt;https://github.com/BlueWhale-Quant-Lab/polymarket-updown-event-slug-generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The hard case: 1h / 4h / 1d
&lt;/h2&gt;

&lt;p&gt;The hourly, 4-hour, and daily markets are where naive code silently 404s:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The boundaries are Eastern Time.&lt;/strong&gt; Hard-code a UTC-5 offset and every slug
breaks for ~8 months of the year once US daylight saving (EDT, UTC-4) kicks in.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 1d market runs noon-ET → noon-ET&lt;/strong&gt; — not a UTC day, not an ET-midnight
day. &lt;em&gt;"...on March 5"&lt;/em&gt; = &lt;em&gt;Mar 4 noon ET → Mar 5 noon ET&lt;/em&gt;, and the slug carries
the &lt;strong&gt;settlement&lt;/strong&gt; date: &lt;code&gt;bitcoin-up-or-down-on-march-5-2026&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The 1h format drifted.&lt;/strong&gt; Polymarket has shipped it both with and without the
year (&lt;code&gt;bitcoin-up-or-down-june-1-9am-et&lt;/code&gt; vs &lt;code&gt;...-june-1-2026-9am-et&lt;/code&gt;), so robust
code has to try both and validate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Watch for zombie slugs:&lt;/strong&gt; across a year boundary the same date can resolve to
&lt;em&gt;last year's CLOSED&lt;/em&gt; market (depth 0). Filter &lt;code&gt;closed&lt;/code&gt;/&lt;code&gt;inactive&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The free tool sticks to the two deterministic timeframes on purpose. If you need&lt;br&gt;
1h/4h/1d done correctly (DST-safe, format-change-proof, with the noon-ET boundary&lt;br&gt;
and dynamic tickSize handled), there's a complete version here:&lt;br&gt;
&lt;a href="https://bluewhalequantlab.gumroad.com/l/polymarket-updown-market-slug-generator-pro" rel="noopener noreferrer"&gt;Polymarket Up/Down slug generator — PRO&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-up
&lt;/h2&gt;

&lt;p&gt;The slug is a small thing that blocks a lot of Polymarket automation simply&lt;br&gt;
because the format isn't written down anywhere. For 5m/15m it's a one-line UTC&lt;br&gt;
floor; for 1h/4h/1d it's an Eastern-Time minefield. Grab the open-source generator&lt;br&gt;
and save yourself the reverse-engineering:&lt;br&gt;
&lt;strong&gt;&lt;a href="https://github.com/BlueWhale-Quant-Lab/polymarket-updown-event-slug-generator" rel="noopener noreferrer"&gt;https://github.com/BlueWhale-Quant-Lab/polymarket-updown-event-slug-generator&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: this is about building a data primitive and reading public market data —&lt;br&gt;
not placing orders or predicting prices.)&lt;/em&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>crypto</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
