New: the v3.1 preview. Faster queries and smaller downloads, three sample hours to test. Tell us whether it is ready to roll out. Try the preview
Polymarket Orderbook Archive archive.pendulumflow.com

v3.1 preview

OK you grubby data degens, I have been hard at work on v3.1 and hope you like it. Faster queries and smaller downloads for you. More compute and complexity in delivery for me. You are welcome.

The ask: test it and tell me whether it is ready to roll out or needs changes. Post in Discord or use the feedback form.

Three complete hours, 2026-10-11 00:00 to 03:00 UTC. They are the same hours as in /v3/, so you can put the two side by side. v3 stays the live format until the feedback is in. The README has the full reader notes, what we tested and how fast it ran. Start with quickstart.py: it needs only DuckDB and reads an hour straight from these links.

Why so many files: each hour is one file per category, so a question about one market or one category reads one or two event files (plus their provenance files if you want those). The hour's manifest.json lists them all, and the quickstart reads it for you.

Coming in a few days: a small per-hour twin check, so you can confirm that the mirrored rows you rebuild match ours. The large mirror_dropped audit lists will then stop being published; we keep checking every hour.

One more, remembered while writing this: v3.1 will also carry each recorder's own record of its connection: every disconnect and reconnect, with the gaps between them stated outright rather than left for you to infer, plus a short summary per recorder for each hour. We have been recording these since 6 October. They are not in this sample yet.

A quarter of the download

The event files for an hour are about 25% of the v3 file: 519 MB instead of 2.17 GB for the biggest hour so far. wakamex spotted that every price change shows up on both tokens and that the bookkeeping columns were most of the bytes, and David found the same twins in best bid and ask and in books. Thanks both.

More detail

Three things make it smaller. With the provenance files, every v3 row and column comes back, except book snapshots identical to the token's previous book, which add nothing.

  • Mirrored rows kept once. In a two-outcome market every update to one token is mirrored on the other (price 1 - p, sides swapped). When the mirror is exact we keep one copy and set mirror_dropped = true. That was about 44% of the rows in these hours. Only exact mirrors are dropped: if anything differs, both rows stay.
  • Repeat books dropped. A book snapshot identical to the token's previous book adds nothing.
  • Bookkeeping moved out. Which machines saw each row, receive times and sequence numbers now live in separate provenance files, so you only download them if you want them. Event and provenance files together are about 70% of v3 (1.54 GB against 2.17 GB for hour 00), and most questions need only the event files.
Hourv3v3.1 event filesv3.1 provenanceRows, v3 to v3.1
002.17 GB519 MB1.02 GB180 M to 90 M
012.11 GB503 MB990 MB177 M to 89 M
021.93 GB464 MB908 MB163 M to 82 M

Faster queries, by design

Each hour is split into one file per category (17 of them; sports is big enough to come in two parts), each sorted by market, token and time, in bigger groups with half the rows. Engines skip the row groups that cannot match. The row-group size came from Kuinox's benchmarks across four engines, so thanks Kuinox.

More detail

Every Parquet file is split into row groups, and each group records the smallest and largest value of every column. A query engine reads those few bytes first and skips any group that cannot hold what you asked for. v3 was already sorted by market, token and time. v3.1 goes further in three ways: each category is its own file, so a whole category is one or two files; groups are about four times larger, so an engine makes fewer, bigger reads; and the file holds half the rows and only the columns most queries need, so there is less to read in the first place.

Group size is a trade-off. Too small and an engine makes thousands of tiny reads; too big and it reads more than it needs. Kuinox rewrote a v3 hour at sizes from 100 thousand to 10 million rows per group and timed DuckDB, Polars, DataFusion and chDB on each. Small groups were 5 to 7 times slower in chDB. We settled on about a million rows per group, cut only where the category changes. Timings on hour 01 in DuckDB:

Queryv3v3.1
One market, local copy0.037 s0.005 s (its category's files)
Latest best bid and ask per token, local copy0.64 s0.39 s
One whole category, local copyno category column0.018 s
One market, over the internet3.7 s0.24 s (its category's files)

Over the internet, read only the category you need: market_categories.parquet gives every market's category. Reading every file of an hour costs many requests and runs into the rate limit.

Your numbers will differ. Tell us what you see in your engine.

Just the data you want, at the detail you choose

Pick the slice (a category, a market, a token) and the detail (trades only, top of book, or full depth) and read only that. In hour 01, trades are 54 thousand of 88.7 million rows. Daniel Sapkota asked for exactly this: "I want all temperature books". That is now one filter on the Weather category.

More detail

Pick the slice. Because of the layout above, a filter on category, market or token reads only the groups that hold it, and a time window inside one of those narrows it further. Crypto is 8.4 million of the 88.7 million rows in hour 01, so a Crypto-only query reads about a tenth of the file. Engines that read Parquet over HTTP, such as DuckDB and Polars, fetch only those parts, so you can query an hour without downloading all of it. For repeated work, download the hour once and query it locally.

Pick the detail. The event_type column sets the resolution. Rows in hour 01, by type:

If you wantReadRows in hour 01
Trades onlylast_trade_price54 thousand
Top of book over timebest_bid_ask8.0 million
Full depthbook plus price_change80.6 million
Market lifecyclenew_market, market_resolved, tick_size_change36 thousand

Pick the depth and the interval. For the order book itself, the quickstart's book_snapshots gives a token's book at any interval you choose (every second, minute, 10 minutes) and to any depth (the top N levels or the full book), straight from these files with DuckDB. It matched our replay engine on every level we compared, and one token over a whole hour takes about 5 seconds at one-second snapshots ten levels deep.

Pick one side or both, carefully. In a two-outcome market almost every update to the second token (complement_token in markets.parquet) is stored as a mirrored row of the first. A plain filter on the second token's id sees about 1% of its rows. Query by market and rebuild the mirrored rows with the quickstart's expand_twins. With the provenance files passed in, it gives exactly the rows and columns v3 had for that market, except dropped repeat books.

Pick the extras. Receive times, sequence numbers and which machines saw each row sit in the provenance file, and the opening state and reference prices have their own files. Download them only if your question needs them.

Start at any hour

Each hour ships the state of every market at its first second, as far as our recording knows it (a token we never saw a full book for is marked unknown), so you can replay or backtest from that hour without downloading the hours before it.

More detail

opening_state.parquet gives every token's state at hh:00:00: the full book where we have one, best bid and ask, last trade and tick size. The books come from the same replay engine that rebuilds books from these files, carried forward from our own recording of the previous hours, and marked derived = true. Book times are the top of the hour for now; the last trade carries its own time.

To check it, we compare every real book that arrives during the hour with our carried book for that token at that moment. They matched 98.4% to 98.8% of the time across these hours. The misses are messages missed earlier, which stay wrong until the next real book corrects them. A token we have never seen a full book for gets best bid and ask and its last trade, with the book marked unknown (null); an empty list means the venue's book really was empty.

The prices crypto markets settle on

Chainlink and Binance prices for the crypto Up or Down markets, plus the 30 and 60 second TWAPs they actually settle on. raph asked for the Chainlink streams behind these markets, and Aldous Huxley has offered Chainlink history back to December 2025, so earlier hours can get these too. Thanks raph and Aldous.

More detail

reference_prices.parquet holds the Chainlink (8 coins) and Binance (6 coins) prices Polymarket streams, about one a second. Since August, the 5 minute markets settle on a 30 second Chainlink TWAP, and the 15 minute and 4 hour markets on a 60 second one. With these you can see exactly what a market settled against, and backtest anything that trades into the close.

Polymarket does not publish the TWAP formula, so we worked it out from Chainlink's own TWAP prints. It is the plain average of the one-per-second Chainlink price over the window. Our rebuild matched Chainlink's value in every complete window we tested (3,456 of 3,456 at 30 seconds, 1,884 of 1,884 at 60). These three hours predate our recording of the TWAP stream, so their TWAP rows are rebuilt and marked derived. About 2% of seconds never arrive on the Chainlink stream, and the missing_seconds column counts them in each window.

The signed order behind each fill

Each hour now also has an order-intent.parquet: the full signed order behind each on-chain fill on Polymarket's two main exchange contracts, read from their mined matchOrders calls on Polygon. Abomination81's ideas around mempools led us here.

More detail

One row is one order in a settlement transaction: the transaction hash (tx_hash), the fill's log index (fill_log_index), the order_hash, the order's wallet (maker), whether it was the taker (is_taker), the amounts, the fee, and the order's own timestamp client_timestamp_ms. Join per fill on tx_hash and fill_log_index, not on the hash alone: one transaction holds a taker and several makers. Fills on the newer combinatorial contract are listed from their logs only, without the order (about 0.5% of fills in hour 00). Each hour's order-intent.manifest.json gives the block range, the match rate and what every row kind means, and the README has more.

Three things to know before you join it to the event files:

  • Join venue hour H against on-chain hours H and H+1. A fill lands in a block a few seconds after the venue's trade message, so trades near the end of an hour settle in the next hour's blocks.
  • token_id is text, asset_id is bytes. Here token_id is the decimal uint256 as text; the event files' asset_id is the same number as 32 bytes, big-endian. In Python, bytes.fromhex(f"{int(token_id):064x}") converts it.
  • client_timestamp_ms is the signer's, and 0 means unset. Whoever signs the order sets it, and it is not when the order was signed or sent. A 0 means the signer left it unset: about 1% of order rows in hour 00, from 12 wallets. Treat it as missing.

Book-equivalent, and checked

Join the provenance file and expand the mirrored rows, and you get back everything v3 told you. The only rows not rebuilt are book snapshots identical to the token's previous book, which add nothing.

More detail

Every hour passed 19 checks before going up, with one more check not run in this preview. They cover row counts, ordering, nulls, schema and layout. They also confirm that every dropped mirror rebuilds exactly, and that the drops can be recomputed from the source independently. Each hour's verify_report.json lists them. We also ran 23 user-style tests on each hour against v3: every row comes back, four busy markets rebuild exactly on all 28 v3 columns, and books replayed minute by minute match. The scripts and results are in user-tests/, so you can run them yourself. How to expand the mirrored rows is in the README, and markets.parquet gives each market's two tokens.

Where v3.1 started

Abomination81 shared seven recommendations, drawn from what their own Polymarket recorder keeps and ours did not. Two are in this sample: the Chainlink and Binance prices in reference_prices.parquet (raph asked for them too). Another, a log of every connection with explicit gap intervals, has been recorded on all our recorders since 6 October and is due to be published with v3.1. Their ideas around mempools also helped us come up with a method for recording Order Intent, the signed orders behind on-chain fills. It is in this sample now, one file per hour (above). Thanks, Abomination81.

What to tell us

How long the downloads took, how fast your queries ran and in which engine, whether the opening state and the mirror expansion were easy to use, and anything you want added. Discord or the feedback form.

Help us find bloat. Some trimming is already decided for when v3.1 goes live (the README lists it: millisecond receive times, no public audit lists, no derivable spread column), bringing event and provenance files to about 56% of v3. If there is a column or file you never use, or would happily trade for a smaller download, tell us.

The files

FileSize
README.md23.5 KiB
SHA256SUMS.txt16.5 KiB
quickstart.py29.9 KiB
2026-10-11/market_categories.parquet8.3 MiB
2026-10-11/markets.parquet24.5 MiB
user-tests/http-results-2026-10-11T01.json3.8 KiB
user-tests/http_tests.py7.1 KiB
user-tests/results-2026-10-11T00.json5.6 KiB
user-tests/results-2026-10-11T01.json5.6 KiB
user-tests/results-2026-10-11T02.json5.6 KiB
user-tests/user_tests.py12.3 KiB
Hour 2026-10-11T00: 47 files
FileSize
2026-10-11/2026-10-11T00.ai.parquet11.7 MiB
2026-10-11/2026-10-11T00.ai.provenance.parquet26.1 MiB
2026-10-11/2026-10-11T00.book_dropped.parquet2.9 MiB
2026-10-11/2026-10-11T00.business.parquet933.6 KiB
2026-10-11/2026-10-11T00.business.provenance.parquet2.1 MiB
2026-10-11/2026-10-11T00.crypto.parquet43.2 MiB
2026-10-11/2026-10-11T00.crypto.provenance.parquet85.0 MiB
2026-10-11/2026-10-11T00.earnings.parquet77.4 KiB
2026-10-11/2026-10-11T00.earnings.provenance.parquet97.5 KiB
2026-10-11/2026-10-11T00.economy.parquet4.4 MiB
2026-10-11/2026-10-11T00.economy.provenance.parquet9.7 MiB
2026-10-11/2026-10-11T00.elections.parquet57.8 MiB
2026-10-11/2026-10-11T00.elections.provenance.parquet129.2 MiB
2026-10-11/2026-10-11T00.esports.parquet10.6 MiB
2026-10-11/2026-10-11T00.esports.provenance.parquet26.5 MiB
2026-10-11/2026-10-11T00.finance.parquet5.2 MiB
2026-10-11/2026-10-11T00.finance.provenance.parquet11.5 MiB
2026-10-11/2026-10-11T00.geopolitics.parquet9.8 MiB
2026-10-11/2026-10-11T00.geopolitics.provenance.parquet20.4 MiB
2026-10-11/2026-10-11T00.manifest.json102.7 KiB
2026-10-11/2026-10-11T00.mirror_dropped.p1.parquet381.4 MiB
2026-10-11/2026-10-11T00.mirror_dropped.p2.parquet369.6 MiB
2026-10-11/2026-10-11T00.mirror_dropped.p3.parquet148.7 MiB
2026-10-11/2026-10-11T00.opening_state.parquet62.0 MiB
2026-10-11/2026-10-11T00.opening_state_report.json7.7 KiB
2026-10-11/2026-10-11T00.order-intent.manifest.json2.9 KiB
2026-10-11/2026-10-11T00.order-intent.parquet10.7 MiB
2026-10-11/2026-10-11T00.politics.parquet7.1 MiB
2026-10-11/2026-10-11T00.politics.provenance.parquet15.7 MiB
2026-10-11/2026-10-11T00.pop-culture.parquet8.3 MiB
2026-10-11/2026-10-11T00.pop-culture.provenance.parquet17.9 MiB
2026-10-11/2026-10-11T00.reference_prices.parquet1.6 MiB
2026-10-11/2026-10-11T00.science.parquet724.8 KiB
2026-10-11/2026-10-11T00.science.provenance.parquet1.4 MiB
2026-10-11/2026-10-11T00.sports.p1.parquet214.2 MiB
2026-10-11/2026-10-11T00.sports.p1.provenance.parquet379.8 MiB
2026-10-11/2026-10-11T00.sports.p2.parquet90.5 MiB
2026-10-11/2026-10-11T00.sports.p2.provenance.parquet188.5 MiB
2026-10-11/2026-10-11T00.tech.parquet2.3 MiB
2026-10-11/2026-10-11T00.tech.provenance.parquet5.2 MiB
2026-10-11/2026-10-11T00.uncategorised.parquet13.2 MiB
2026-10-11/2026-10-11T00.uncategorised.provenance.parquet25.4 MiB
2026-10-11/2026-10-11T00.verify_report.json2.8 KiB
2026-10-11/2026-10-11T00.weather.parquet11.4 MiB
2026-10-11/2026-10-11T00.weather.provenance.parquet22.6 MiB
2026-10-11/2026-10-11T00.world.parquet3.0 MiB
2026-10-11/2026-10-11T00.world.provenance.parquet6.2 MiB
Hour 2026-10-11T01: 47 files
FileSize
2026-10-11/2026-10-11T01.ai.parquet11.6 MiB
2026-10-11/2026-10-11T01.ai.provenance.parquet25.7 MiB
2026-10-11/2026-10-11T01.book_dropped.parquet2.3 MiB
2026-10-11/2026-10-11T01.business.parquet899.0 KiB
2026-10-11/2026-10-11T01.business.provenance.parquet2.0 MiB
2026-10-11/2026-10-11T01.crypto.parquet42.6 MiB
2026-10-11/2026-10-11T01.crypto.provenance.parquet83.6 MiB
2026-10-11/2026-10-11T01.earnings.parquet77.4 KiB
2026-10-11/2026-10-11T01.earnings.provenance.parquet94.2 KiB
2026-10-11/2026-10-11T01.economy.parquet4.4 MiB
2026-10-11/2026-10-11T01.economy.provenance.parquet9.7 MiB
2026-10-11/2026-10-11T01.elections.parquet54.6 MiB
2026-10-11/2026-10-11T01.elections.provenance.parquet120.1 MiB
2026-10-11/2026-10-11T01.esports.parquet12.8 MiB
2026-10-11/2026-10-11T01.esports.provenance.parquet31.8 MiB
2026-10-11/2026-10-11T01.finance.parquet5.4 MiB
2026-10-11/2026-10-11T01.finance.provenance.parquet11.8 MiB
2026-10-11/2026-10-11T01.geopolitics.parquet10.0 MiB
2026-10-11/2026-10-11T01.geopolitics.provenance.parquet21.0 MiB
2026-10-11/2026-10-11T01.manifest.json102.5 KiB
2026-10-11/2026-10-11T01.mirror_dropped.p1.parquet381.4 MiB
2026-10-11/2026-10-11T01.mirror_dropped.p2.parquet369.6 MiB
2026-10-11/2026-10-11T01.mirror_dropped.p3.parquet127.8 MiB
2026-10-11/2026-10-11T01.opening_state.parquet61.6 MiB
2026-10-11/2026-10-11T01.opening_state_report.json7.9 KiB
2026-10-11/2026-10-11T01.order-intent.manifest.json2.9 KiB
2026-10-11/2026-10-11T01.order-intent.parquet10.0 MiB
2026-10-11/2026-10-11T01.politics.parquet7.3 MiB
2026-10-11/2026-10-11T01.politics.provenance.parquet16.2 MiB
2026-10-11/2026-10-11T01.pop-culture.parquet8.3 MiB
2026-10-11/2026-10-11T01.pop-culture.provenance.parquet18.4 MiB
2026-10-11/2026-10-11T01.reference_prices.parquet1.6 MiB
2026-10-11/2026-10-11T01.science.parquet736.1 KiB
2026-10-11/2026-10-11T01.science.provenance.parquet1.5 MiB
2026-10-11/2026-10-11T01.sports.p1.parquet211.3 MiB
2026-10-11/2026-10-11T01.sports.p1.provenance.parquet378.2 MiB
2026-10-11/2026-10-11T01.sports.p2.parquet78.8 MiB
2026-10-11/2026-10-11T01.sports.p2.provenance.parquet160.8 MiB
2026-10-11/2026-10-11T01.tech.parquet2.4 MiB
2026-10-11/2026-10-11T01.tech.provenance.parquet5.3 MiB
2026-10-11/2026-10-11T01.uncategorised.parquet12.4 MiB
2026-10-11/2026-10-11T01.uncategorised.provenance.parquet24.1 MiB
2026-10-11/2026-10-11T01.verify_report.json2.8 KiB
2026-10-11/2026-10-11T01.weather.parquet13.6 MiB
2026-10-11/2026-10-11T01.weather.provenance.parquet27.9 MiB
2026-10-11/2026-10-11T01.world.parquet2.9 MiB
2026-10-11/2026-10-11T01.world.provenance.parquet6.0 MiB
Hour 2026-10-11T02: 47 files
FileSize
2026-10-11/2026-10-11T02.ai.parquet11.7 MiB
2026-10-11/2026-10-11T02.ai.provenance.parquet26.4 MiB
2026-10-11/2026-10-11T02.book_dropped.parquet2.9 MiB
2026-10-11/2026-10-11T02.business.parquet1.1 MiB
2026-10-11/2026-10-11T02.business.provenance.parquet2.4 MiB
2026-10-11/2026-10-11T02.crypto.parquet41.0 MiB
2026-10-11/2026-10-11T02.crypto.provenance.parquet82.6 MiB
2026-10-11/2026-10-11T02.earnings.parquet71.8 KiB
2026-10-11/2026-10-11T02.earnings.provenance.parquet79.5 KiB
2026-10-11/2026-10-11T02.economy.parquet4.3 MiB
2026-10-11/2026-10-11T02.economy.provenance.parquet9.6 MiB
2026-10-11/2026-10-11T02.elections.parquet55.6 MiB
2026-10-11/2026-10-11T02.elections.provenance.parquet124.8 MiB
2026-10-11/2026-10-11T02.esports.parquet11.0 MiB
2026-10-11/2026-10-11T02.esports.provenance.parquet26.2 MiB
2026-10-11/2026-10-11T02.finance.parquet5.1 MiB
2026-10-11/2026-10-11T02.finance.provenance.parquet11.0 MiB
2026-10-11/2026-10-11T02.geopolitics.parquet9.7 MiB
2026-10-11/2026-10-11T02.geopolitics.provenance.parquet20.1 MiB
2026-10-11/2026-10-11T02.manifest.json102.6 KiB
2026-10-11/2026-10-11T02.mirror_dropped.p1.parquet381.3 MiB
2026-10-11/2026-10-11T02.mirror_dropped.p2.parquet370.8 MiB
2026-10-11/2026-10-11T02.mirror_dropped.p3.parquet55.3 MiB
2026-10-11/2026-10-11T02.opening_state.parquet62.1 MiB
2026-10-11/2026-10-11T02.opening_state_report.json7.9 KiB
2026-10-11/2026-10-11T02.order-intent.manifest.json2.9 KiB
2026-10-11/2026-10-11T02.order-intent.parquet10.5 MiB
2026-10-11/2026-10-11T02.politics.parquet7.0 MiB
2026-10-11/2026-10-11T02.politics.provenance.parquet15.5 MiB
2026-10-11/2026-10-11T02.pop-culture.parquet8.4 MiB
2026-10-11/2026-10-11T02.pop-culture.provenance.parquet19.0 MiB
2026-10-11/2026-10-11T02.reference_prices.parquet1.6 MiB
2026-10-11/2026-10-11T02.science.parquet723.1 KiB
2026-10-11/2026-10-11T02.science.provenance.parquet1.5 MiB
2026-10-11/2026-10-11T02.sports.p1.parquet215.2 MiB
2026-10-11/2026-10-11T02.sports.p1.provenance.parquet380.8 MiB
2026-10-11/2026-10-11T02.sports.p2.parquet41.7 MiB
2026-10-11/2026-10-11T02.sports.p2.provenance.parquet85.4 MiB
2026-10-11/2026-10-11T02.tech.parquet2.3 MiB
2026-10-11/2026-10-11T02.tech.provenance.parquet5.0 MiB
2026-10-11/2026-10-11T02.uncategorised.parquet12.2 MiB
2026-10-11/2026-10-11T02.uncategorised.provenance.parquet23.6 MiB
2026-10-11/2026-10-11T02.verify_report.json2.8 KiB
2026-10-11/2026-10-11T02.weather.parquet12.4 MiB
2026-10-11/2026-10-11T02.weather.provenance.parquet25.4 MiB
2026-10-11/2026-10-11T02.world.parquet2.9 MiB
2026-10-11/2026-10-11T02.world.provenance.parquet6.1 MiB

Credit the collector: pendulumflow for V3, PMXT for V1 and V2, AG6 for their V2 archive. Ours and PMXT's are CC BY 4.0; AG6 states no licence. How to cite.

Serving these bytes is not endorsing them. We are not affiliated with Polymarket.

For AI readers: llms.txt, what this archive holds and the questions it cannot answer.

https://x.com/PendulumFlow

Join the Pendulum Flow Discord: other people who build on prediction-market data, comparing notes and sharing tooling and findings.