Skip to content

polymarket clob book: orderbook table shows worst prices first (best bid/ask buried at bottom) #75

@Nexory

Description

@Nexory

polymarket clob book <token> prints the bids and asks tables in raw API order (src/output/clob/books.rs:34-66). The API returns:

  • bids in ascending price order (lowest bid first)
  • asks in descending price order (highest ask first)

The CLI just iterates result.bids.iter() / result.asks.iter() straight into a tabled::Table, so what the user sees is:

Bids:
┌───────┬────────────┐
│ Price │ Size       │
├───────┼────────────┤
│ 0.001 │ 1218691.83 │   ← worst bid (top)
│ 0.002 │ 538822.20  │
│ ...   │            │
│ 0.008 │ 3905.98    │   ← BEST bid (bottom)
└───────┴────────────┘

Asks:
┌───────┬────────────┐
│ Price │ Size       │
├───────┼────────────┤
│ 0.999 │ 3139845.17 │   ← worst ask (top)
│ ...   │            │
│ 0.009 │ 312.07     │   ← BEST ask (bottom)
└───────┴────────────┘

(reproduced against the BTC $150k by June 30 market; same ordering verified against 2 other high-volume markets — the API behavior is consistent.)

Both best prices end up at the bottom of their respective tables, which is the opposite of what a CLI user usually wants to see first. The non-obvious ordering is also documented in Polymarket/rs-clob-client#330, which calls out the same mismatch in the V1 Rust SDK.

JSON output (OutputFormat::Json) should keep the API order so programmatic consumers stay backward-compatible — this is only about the human-facing table.

Suggested fix

Option A — minimal change (best-first per side): reverse bids (already-correct asks stay as-is so the best ask sits at the bottom adjacent to the best bid):

let rows: Vec<Row> = result.bids.iter().rev()  // best bid first
    .map(|o| Row { price: ..., size: ... })
    .collect();

Option B — depth-ladder layout: print asks first (descending → best ask at bottom of asks), then bids reversed (descending → best bid at top of bids), so the spread sits in the middle:

Asks:
  0.999
  ...
  0.009   ← best ask
──────── spread
Bids:
  0.008   ← best bid
  ...
  0.001

This matches the convention used by TradingView, Binance, Kraken, and most other exchange UIs.

Happy to send a small PR with whichever option fits the project direction.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions