SDK package and version
polymarket (py-sdk) — source inspected at main, not installed. Reproduction below is against the Gamma API directly, so it does not depend on the SDK version.
Runtime
Python 3.13, macOS
What happened?
list_markets() accepts order: str | None with no documented values. The natural guess is the model attribute name — order="volume" — but the Gamma API does not order that field numerically.
Every value on the order=volume page starts with the digit 9, the largest being 999.94, against a true maximum of about 83,453,020 in the same filter set. order=liquidity behaves the same way: top value 999.96 against a true maximum of about 2,902,308.
volume and liquidity come back as JSON strings; volumeNum and liquidityNum as numbers. That appears to explain it. I can't tell the mechanism from outside — I only know the returned order isn't numeric, and the numeric twins order correctly.
Why this is easy to hit from the SDK
The filter parameters already distinguish the numeric fields — volume_num_min, volume_num_max, liquidity_num_min, liquidity_num_max — so the SDK treats volumeNum as the numeric field for filtering. There is no equivalent signal for ordering: order is an unvalidated string, and the visible model attribute is volume. In models/gamma/market.py both are declared Decimal | None, so the distinction isn't apparent there either.
A reasonable call therefore returns the wrong markets silently rather than raising.
What else I checked
I verified the surrounding invariants before concluding the ordering was the outlier. Across samples of 800–1000 live markets:
volume and volumeNum agree numerically — no mismatches
liquidity and liquidityNum agree — no mismatches
len(outcomes) == len(clobTokenIds) holds
- offset pagination returns no duplicate or missing ids, under both
order=volume and order=volumeNum
volumeNumMin filtering agrees with the returned values
- closed and archived markets showed no malformed records
Paginator terminates on the server's has_more flag, so omitted markets cannot truncate iteration early
All of those held. The ordering is the only thing that didn't.
One related note
About 5% of low-volume active markets in my sample returned no clobTokenIds. Per the list_markets docstring these are omitted from results. Pagination stays correct, but the caller gets no signal that anything was skipped — worth a line in the docstring for anyone reconciling counts.
Suggested fix
Document the accepted order values in the list_markets docstring, and note that volumeNum/liquidityNum order numerically while volume/liquidity do not. A short comment on the metrics model would help too. This would also fit naturally into #219.
Happy to open a PR for the docstring if that's useful.
Minimal reproduction
Q="active=true&closed=false"
# 1. field types
curl -s "https://gamma-api.polymarket.com/markets?$Q&limit=1" | python3 -c "
import sys,json; m=json.load(sys.stdin)[0]
print({k: type(m[k]).__name__ for k in ('volume','volumeNum','liquidity','liquidityNum')})"
# -> {'volume': 'str', 'volumeNum': 'float', 'liquidity': 'str', 'liquidityNum': 'float'}
# 2. order by "volume"
curl -s "https://gamma-api.polymarket.com/markets?$Q&limit=10&order=volume&ascending=false" \
| python3 -c "import sys,json;print([m['volume'] for m in json.load(sys.stdin)])"
# -> ['99.995453','999.942321','99.99405','999.935914','99.99','999.8','9.996466', ...]
# 3. order by "volumeNum", same filters
curl -s "https://gamma-api.polymarket.com/markets?$Q&limit=1&order=volumeNum&ascending=false" \
| python3 -c "import sys,json;print(json.load(sys.stdin)[0]['volumeNum'])"
# -> 83453020.65649901
# 4. same pattern for liquidity
curl -s "https://gamma-api.polymarket.com/markets?$Q&limit=10&order=liquidity&ascending=false" \
| python3 -c "import sys,json;print([m['liquidity'] for m in json.load(sys.stdin)])"
curl -s "https://gamma-api.polymarket.com/markets?$Q&limit=1&order=liquidityNum&ascending=false" \
| python3 -c "import sys,json;print(json.load(sys.stdin)[0]['liquidityNum'])"
# -> top value 999.9617 vs true maximum 2902308.31206
Expected behavior, actual behavior, or logs
No response
SDK package and version
polymarket (py-sdk) — source inspected at main, not installed. Reproduction below is against the Gamma API directly, so it does not depend on the SDK version.
Runtime
Python 3.13, macOS
What happened?
list_markets()acceptsorder: str | Nonewith no documented values. The natural guess is the model attribute name —order="volume"— but the Gamma API does not order that field numerically.Every value on the
order=volumepage starts with the digit 9, the largest being 999.94, against a true maximum of about 83,453,020 in the same filter set.order=liquiditybehaves the same way: top value 999.96 against a true maximum of about 2,902,308.volumeandliquiditycome back as JSON strings;volumeNumandliquidityNumas numbers. That appears to explain it. I can't tell the mechanism from outside — I only know the returned order isn't numeric, and the numeric twins order correctly.Why this is easy to hit from the SDK
The filter parameters already distinguish the numeric fields —
volume_num_min,volume_num_max,liquidity_num_min,liquidity_num_max— so the SDK treatsvolumeNumas the numeric field for filtering. There is no equivalent signal for ordering:orderis an unvalidated string, and the visible model attribute isvolume. Inmodels/gamma/market.pyboth are declaredDecimal | None, so the distinction isn't apparent there either.A reasonable call therefore returns the wrong markets silently rather than raising.
What else I checked
I verified the surrounding invariants before concluding the ordering was the outlier. Across samples of 800–1000 live markets:
volumeandvolumeNumagree numerically — no mismatchesliquidityandliquidityNumagree — no mismatcheslen(outcomes) == len(clobTokenIds)holdsorder=volumeandorder=volumeNumvolumeNumMinfiltering agrees with the returned valuesPaginatorterminates on the server'shas_moreflag, so omitted markets cannot truncate iteration earlyAll of those held. The ordering is the only thing that didn't.
One related note
About 5% of low-volume active markets in my sample returned no
clobTokenIds. Per thelist_marketsdocstring these are omitted from results. Pagination stays correct, but the caller gets no signal that anything was skipped — worth a line in the docstring for anyone reconciling counts.Suggested fix
Document the accepted
ordervalues in thelist_marketsdocstring, and note thatvolumeNum/liquidityNumorder numerically whilevolume/liquiditydo not. A short comment on the metrics model would help too. This would also fit naturally into #219.Happy to open a PR for the docstring if that's useful.
Minimal reproduction
Expected behavior, actual behavior, or logs
No response