Peer-recorded market data for perp DEXs and prediction markets

The whole archive, from your laptop.

270.6 GB of parquet, 7.2 billion rows, 28 venues. Your agent queries it through our MCP with nothing to provision and nothing to download, and gets back bars, returns, volatility and volume already computed, so the Python you write starts at the analysis. When your agent knows the call, one answer costs it 14k to 15k tokens and about ten seconds; an agent working the parquet itself spent 39k to 74k on the same numbers, after the files were downloaded. On multi-step research the parquet agent won, and we publish that too.

28 venues sellable today · catalogue snapshot through 2026-10-20

run_query · edgex/trades:ETHUSDC · 2026-09-27
// call
{
  "dataset": "edgex/trades",
  "instrument": "ETHUSDC",
  "sql": "WITH r AS (SELECT ln(close / lag(close) OVER…"
}
// response: ETH realised vol, 1-minute returns, annualised
{
  "columns": ["rv"],
  "rows": [[0.26607035797344336]],
  "table_t": "1-minute bars"
}
This call, known in advance: 14,589 tokens An agent working the parquet to the same number: 73,532
40venues recorded
28with data we can sell
152venue × data-type feeds
270.6 GBsellable parquet catalogued
7.23Bsellable rows

Recomputed from the catalogue on every build: 66 days, 2026-07-28 → 2026-10-20 UTC.

  • 17 Perp / spot DEX
  • 12 Centralized exchange (derived data only)
  • 6 Prediction market
  • 5 Not a market venue
What you get

Three claims, in the order they matter.

01

Archive-scale work, from the laptop you already have.

270.6 GB

Your agent works across 28 venues and 7.2 billion rows with nothing to provision, nothing to download and no disk to clear first. One call reads up to 60 million rows server-side and hands back bars, returns, volatility or cross-venue volume. Nothing upstream records candles, so bars are built from every trade at query time. Not a terabyte yet: 531.4 GB recorded in all, growing daily.

02

You write the query. It runs next to the data.

1 call · 27–48 lines

The aggregate comes back, not the rows, so finding files, casting epochs and dropping duplicate trades are already done. For one number: one call and 14k to 15k tokens, against 27 to 48 lines and 39k to 74k tokens over the parquet. On research it is mixed, and we show it: Funding carry across five perp venues, 1 lines of code through the MCP against 169; Cross-venue lead-lag and price dislocation, 54 lines of code through the MCP against 113; Seven-venue BTC volume share and realised volatility, 78 lines of code through the MCP against 140. The MCP was the cheaper route on one of three research tasks; on the others every result it pulled landed in the agent's context.

Not a fixed menu of precomputed numbers: run_query takes your own read-only SQL, joins several venues in one call, and returns the result rather than the rows. So half the work arrives done and the other half is yours to define — on an archive you never downloaded. The limit, plainly: that SQL runs over 1-minute bars, not over raw ticks, and the bounds it runs under are published below. If your logic needs every individual trade, that is the paid download, and it is the honest place for the line to fall.

See the code →

03

Recorded by peers, not by one machine.

Every venue here is recorded by several independent machines at once, each with its own connection, and the archive is what they saw after cross-checking each other. One node's outage is another node's ordinary minute. That is also how you can earn it rather than buy it: run a peer, and what it records is yours while the shared record gains a witness it did not have. It is peer-to-peer in the recording, not in the delivery — when you download, the bytes come from our object store, and we would rather say so than let the word do work it has not earned.

04

Free up to a quota, because it is cheap to serve.

An aggregate costs CPU on a machine we already run. Bulk raw files cost egress and storage on the way out, and that is what we charge for. The free quota is where the line honestly falls, not a loss-leader and not a trial that expires.

Footnote. Why the MCP answers rather than hands over rows, and why some data is sold only as derived data: the computation happens next to the archive. For centralized exchanges that is the legal line — their raw ticks are licensed by the exchange, so we sell only what is derived from them (liquidations, funding, open interest). It is also why every call carries a published limit. When you need the rows themselves, for the venues where we may sell them, that is what the subscription is for.

Not an adjective: the code

What your agent actually writes, next to what the same number costs from parquet.

Both are copied from real runs of the same model on the same question, not written for this page. Copy the left one into any agent connected to the MCP.

What your agent writes One call. The answer comes back computed.
{
  "dataset": "edgex/trades",
  "instrument": "ETHUSDC",
  "start": "2026-09-27T00:00:00Z",
  "end": "2026-09-28T00:00:00Z",
  "sql": "WITH r AS (SELECT ln(close / lag(close) OVER (ORDER BY ts)) AS lr FROM t) SELECT stddev_samp(lr) * sqrt(525600) AS rv FROM r"
}

Returned rv = 0.2661 from 13 shards read server-side. 14,589 tokens, 10 s, nothing downloaded. Transcript

The same number from raw parquet Command 5 of 8, after the files were on disk.
cd /tmp/peerfeed-a21/archive/edgex; P=/tmp/peerfeed-a21/venv/bin/python; $P -c "
import duckdb
print(duckdb.sql(\"select distinct contractName, contractId from 'trades/parquet/2026/09/27/*.parquet' where contractName ilike '%ETH%'\"))
print(duckdb.sql(\"select filename, min(time), max(time), count(*), count(distinct ticketId) from read_parquet('trades/parquet/2026/09/2[678]/*.parquet', filename=true) where contractName='ETHUSD' group by 1 order by 1\").df().to_string())
"

48 lines of shell and Python across 8 commands: the ones before this found the files, read the schema, picked the symbol and checked for duplicate trades. 73,532 tokens, 37 s, with 234.2 MB of parquet already downloaded. Same answer. Transcript

This is the case we win. When the agent had to find the call itself, it was cheaper than the parquet agent on none of three single numbers and on one of three research tasks — every run, both sides.

Measured 2026-09-29

Real research, run end to end both ways. We still lose most of it on tokens.

The same agent ran each task twice: through this MCP, and over the parquet on its own disk with DuckDB. Every turn is counted, including the exploration and the mistakes. Through the MCP it answered one of three research tasks correctly, the parquet agent three; the MCP was the cheaper route on one. Where the MCP wins clearly is narrower: a number your agent already knows how to ask for, with nothing to download. This run re-measures both routes after the server began stating what its three-trade floor withheld. The previous run measured the same routes before that change. The previous run stays published.

Research taskThrough the MCPAgent over the parquet
TokensWallAnswerTokensWallAnswer
Funding carry across five perp venues 165,47553 scorrect 296,714134 scorrect
Cross-venue lead-lag and price dislocation, BTC, one day 614,489129 spartly wrong 134,22388 scorrect
Seven-venue BTC volume share and realised volatility, one week 963,396185 spartly wrong 328,034156 scorrect

The parquet agent started with the data already on disk; obtaining it is our paid product and is not in its token count. Since the previous run, on the MCP side — dearer than before by more than that noise: T2. Every transcript, both sides, and why we lost →

Fewer wrong answers

The handling that cost us weeks, applied before your agent sees a number.

Raw market data is wrong in ways that do not raise errors. These are from our own archive. In our end-to-end runs a strong agent working the parquet caught every one it met, and our MCP got two research answers short of correct; every error is listed with the measurement.

Epoch units

Timestamps that declare milliseconds and store nanoseconds

Some venue streams write nanosecond epochs into a column typed as milliseconds. Read as declared, 1789516741100071262 lands in the year ~58,700, or the scan aborts on the unit overflow. Cast it by hand and you get plausible dates on some shards and garbage on the next, because the unit is declared per file.

What the MCP does: Each dataset carries its verified time column and its semantics. Where the exchange time is unusable the bars are timed by our observation clock and labelled ts_semantics: observation, so you know which clock you are reading.

Stale events

A ten-month-old price inside today's shard

One venue's trade stream carries events whose exchange time decodes to 2025-11-05 inside a 2026-09-16 shard. Bucket by observation time and that old price lands in a current bar and moves its high or low. Nothing in the rows flags it.

What the MCP does: That dataset is withheld from the MCP until the question is settled upstream. An answer we cannot stand behind is refused rather than served.

Dedup keys

Content keys that merge distinct trades

On one venue, keying trades by (symbol, time, price, size) would have collapsed 36.12% of 29,743,595 rows: distinct trades that share a millisecond, a price and a size. The venue's trade id finds 58 true duplicate groups instead. Worse, a key field that is missing is filled with a constant, not an error, so one mark-price feed keyed on a timestamp it did not carry silently became one record per market per minute.

What the MCP does: The aggregator deduplicates on an identity measured against real rows, and the MCP does it again on the venue's trade id, so a trade held in four shards is counted once. Our first research run found dYdX trades held up to four times in the archive and the server it used counted every copy (2.9× too much notional); counted once it is $58.5M, matching the reference. The archive fix is deployed for new data, but shards written before it still hold the copies, so the MCP's own dedup is what removes them. (In our latest run the agent summed minute bars instead and came back 4% short on dYdX: that was public mode's three-trade floor, not a duplicate, and it is graded as a loss below — see the floor's own entry, because 4% is the small half of what it does.)

File layout

295,735 files for one day of one feed

Partitioning an order-book feed by market turned one day into up to 295,735 files averaging about 10 KiB. An agent that lists a month of it opens millions of objects before it reads a row. New data has been written one file per two-hour shard since 2026-09-15; the history before it has not been rewritten yet.

What the MCP does: Shards are resolved from an index, never by listing directories, and one call opens at most 400 of them.

All six, and what the MCP does about each →

Pricing

Ask, mine, or subscribe. Pick one.

Three ways to reach the same data, not a ladder of tiers. Most people should start by asking; the other two are for when you need the rows themselves.

1 · Ask

Query through the MCP

Free up to a quota

Metered by rows scanned; paid past the quota

Every venue we sell is reachable. Nothing is held back for a higher tier: the only thing that changes as you use more is the meter.

Pick this if your question has an answer smaller than its data: a bar series, a statistic, a comparison.

How the MCP works →
2 · Mine

Run a node, keep what you record

Your machine's uptime

No keys, no funds, no exchange account

Run the open-source node on the venues you care about and you get the data you record. The archive gets an independent witness for those same minutes, which is what makes the merged record trustworthy.

Pick this if you have a machine that stays up and a short list of venues you need deeply.

The node and the credit rules →
3 · Subscribe

Buy access you cannot mine

From $49 / month

Or $3–4 per GB, no subscription

This tier exists for one reason: you need more than you can record yourself. No spare machine, venues you do not run, or history from before your node started.

Pick this if you need the raw rows on your own machine, or more venues and history than you can run.

See the plans →
Why more than one node

Why a second node is worth anything at all

1–4 minone node sees nothing, every 3 hours
0 minboth nodes blind at once
93.6%of merged records held by node A
97.9%held by node B

Measured on PeerFeed's own two recorders over a 179-minute window on 2026-09-02, across 9 major venues and 1,609 (venue, minute) pairs: one node recorded nothing at all — every venue at once — for 1 minute; the other for 4 minutes, including a burst of 4 consecutive minutes on one venue. The number of minutes where BOTH nodes were blind was zero. Across the same window, 30 feeds and 16.87 M records, one node held 93.6% of the merged record set and the other 97.9% — neither held all of it.

A solo recorder goes fully blind for 1-4 minutes every 3 hours and cannot tell, because its own logs look healthy. Two independent nodes cover each other. That gap is the product, and filling it is what a founder is paid for. Every node someone runs for their own data is another independent witness for the same minutes. Run one →