venue 5-share minimum: skip honestly instead of firing doomed orders; lag tile = median + basis

Polymarket rejects any order under 5 shares regardless of value ('Size
(1.47) lower than the minimum: 5'). That is a PRICE-dependent dollar
floor the $-only gate could not see: at the live book's $1 braked stake
only <=20c markets are reachable, so every 40-90c signal fired an order
that could not succeed (12 'invalid amount' + 13 size rejections in 3d).
gate_buy now blocks with the shares needed and the dollars required.
Lag tile: median not mean (one 269s rollout outlier made a 3s bot read
25s) + a 'basis' field so an empty 24h window is labeled lifetime.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jaxperro
2026-07-27 19:15:09 -04:00
parent b833632fb1
commit 3ecceda782
2 changed files with 30 additions and 1 deletions
+13 -1
View File
@@ -1746,6 +1746,13 @@ class Copybot:
# without copies (2026-07-13 user report). n = lifetime copies,
# n24 = fills in the window.
"lag": (lambda t: {"n": lag.get("n", 0), "n24": t[0],
# window empty -> we show the LIFETIME mean, so
# SAY so; the tile used to label it "24h" and
# quietly report a number dragged by the retired
# poll era (2026-07-27 user report)
"basis": ("24h" if t[1] is not None
else "lifetime" if lag.get("n")
else "none"),
"avg_s": (round(t[1], 1) if t[1] is not None
else (round(lag["sum_s"] / lag["n"], 1)
if lag.get("n") else None)),
@@ -2347,7 +2354,12 @@ class Copybot:
if not rec:
return 0, None, None
n = len(rec)
return n, sum(r[1] for r in rec) / n, sum(r[2] for r in rec) / n
# MEDIAN, not mean (2026-07-27): one 269s early-rollout outlier made a
# 3s bot read as 25s. The tile is a health signal, not an accounting
# total, so the typical fill is the honest summary.
lags = sorted(r[1] for r in rec)
med = lags[n // 2] if n % 2 else (lags[n // 2 - 1] + lags[n // 2]) / 2
return n, med, sum(r[2] for r in rec) / n
def summary(self, cycle):
bank = self.cfg["bankroll_usd"]
+17
View File
@@ -33,6 +33,12 @@ CLOB_API = "https://clob.polymarket.com"
POLYGON_CHAIN_ID = 137
CONFIRM_PHRASE = "TRADE LIVE"
# Polymarket rejects orders under this many shares regardless of dollar
# value ("Size (1.47) lower than the minimum: 5", observed live 2026-07-27).
# It makes the real floor PRICE-dependent: a 90c market needs $4.50, a 20c
# market $1.00 — which is why a $1-stake book can only trade deep longshots.
MIN_SHARES = 5.0
DEFAULT_CONFIG = {
"mode": "paper", # "paper" or "live"
"poll_seconds": 12, # how often to check each wallet
@@ -431,6 +437,17 @@ class CopyTrader:
if allowed < r["min_order_usd"]:
return 0.0, (f"capped to ${allowed:.2f} < min order "
f"${r['min_order_usd']:.2f} (caps)")
# VENUE SHARE MINIMUM (2026-07-27): Polymarket rejects any order
# under MIN_SHARES shares — "Size (1.47) lower than the minimum: 5"
# — which is a PRICE-dependent dollar floor the $-only gate above
# cannot see. At a $1 stake that caps us to <=20c markets; every
# 40-90c signal fired a doomed order and booked a venue rejection.
# Skip honestly instead, and say what the bet would have needed.
need = MIN_SHARES * price
if allowed < need - 1e-9:
return 0.0, (f"below venue {MIN_SHARES:g}-share minimum: "
f"${allowed:.2f} at {price:.2f} = "
f"{allowed / price:.2f} shares (needs ${need:.2f})")
return allowed, None
# -- process one of their trades --