Methodology

Three eras, collected across fifteen years by three different programs, sharing a shape and almost nothing else. This page describes each one and lists what is wrong with it. Nothing below is a disclaimer written to be skipped. The zero counts, the truncated cents and the three different definitions of order book depth all change what an analysis is allowed to conclude, so they are published with the same care as the data.

Every era stores one row per sample, keyed on dateline, a unix timestamp in whole seconds. There is no fixed grid in any of them. Treat every series as an irregular one and key on the timestamp, never on row position.

The depth column is a different measurement in each era. Fifty cents of book in 2011, sixty levels a side in 2014, two percent of price today. They are three answers to one question and they are not one series. The chapter at the bottom is the one to read before any cross-era work, and it is the most important thing on this page.

The 2011 MtGox series

One venue, one pair, 177,585 rows of MtGox BTC/USD top of book at four to five second cadence, logged in September and October 2011. MtGox was where most of the world's bitcoin changed hands at the time and it failed in February 2014, so this book cannot be collected again at any price. The program that wrote it was a trading bot, not a collector, which is where several of the oddities below come from.

RunRowsFirst (UTC)Last (UTC)Notes
1173,7302011-09-21 13:59:262011-09-30 05:10:128.6 days. Three stalls over a minute, longest 259 s.
23,8552011-10-19 19:25:482011-10-20 01:18:19Six hours. Fifteen stalls over a minute, longest 314 s.
Between the two runs there is a hole of 19.6 days with no rows at all. The bot was switched off, so that is an absence of collection and not an absence of market. Prices ran from $2.08 to $5.88 on the midpoint across the whole series.

Columns

Eight: dateline, bid and ask (MtGox best bid and best ask), mean (their midpoint), spread, then bidscore and askscore with their log ratio diff. There is no trade price anywhere in this era, and no volume column.

The depth scores are distance-weighted sums within fifty cents, floored

For each side the bot walked the book outwards from the best price, summed the resting volume at every level within $0.50 of it, weighted each level by

1 / (1 + |price - best|)²

and floored the total to a whole number. That is bidscore and askscore. At the $2 to $6 this era traded at, fifty cents is eight to twenty-five percent of price, so the window is wide in relative terms and it widens as the price falls. The weighting means a level at the touch counts for four times as much as one fifty cents out. Both scores are non-zero on every row and neither is normalised, so their magnitude reflects how much bitcoin was resting near the touch that day rather than anything comparable across eras.

diff is the natural log of the ratio between the larger score and the smaller, signed negative when the bid side is the heavier one. That sign convention is the opposite of the 2014 and modern book_ratio columns, where positive means bid-heavy, and unlike them it is unbounded rather than running from -1 to +1. It is stored as the bot computed it, to three decimals. Recomputing it from the two stored scores lands within a few thousandths but not exactly, so the stored column is the record.

Because it is a log ratio and not a band ratio, no ratio series is published for this era and the chart explorer's imbalance view switches itself off on it. Drawing it beside the 2014 line would be two different measurements sharing an axis and a colour.

Four decimals is all there ever was

The source columns are MySQL float(6,4) for the four prices and float(5,3) for diff: single precision, rounded to a fixed number of decimals when written. The four decimals in the published files are therefore the full precision that was ever recorded, not a truncation applied on the way out, and there is nothing finer to recover. The import parsed the original dump text rather than restoring it into a database first, so the digits you download are the digits the 2011 dump printed.

No fabricated rows, and two columns that are legitimately zero

This collector wrote no row at all when the MtGox depth call failed, so this era carries none of the placeholder contamination the 2014 one does. bid, ask, mean, bidscore and askscore are non-zero on every one of the 177,585 rows.

Two columns do read zero, and both are readings. spread is 0.0000 on 4,776 rows, where the book was locked or all but locked, and diff is 0.000 on 44 rows, where the two depth scores came out level. One wrinkle worth knowing: spread was computed from the raw book prices rather than from the rounded bid and ask in the same row, so on a few hundred rows it reads 0.0000 where ask - bid works out to 0.0001, and on seven rows the stored ask sits below the stored bid. Recompute the spread from bid and ask if the derived number matters more to you than the recorded one.

The chart price is the midpoint

There is no tape in this series, only the book, so the chart JSON's last field carries the bucket's closing mean. Every surface that shows it says so. If you need traded prices for autumn 2011, this is not the file.

The bot's own trading state is not published

The source table also holds lastprice, closeposition and target. Those are the bot's position and its intentions, zero on every row where it held nothing, and they describe one trader rather than the market. They were dropped at import and are not in the published files. The bot's trade log survives too, in a separate recovery, and it is not published either.

Cadence

The bot logged a row every third pass of its main loop, so the interval is a side effect of how long MtGox took to answer. Four seconds on 74% of steps, five on 24%, with a tail beyond. Resample rather than assuming a grid.

The 2014-2015 series

Six venues, sampled every two seconds nominal, from 17 December 2014 to 7 November 2015, about 37.2 million rows. A predecessor of this project ran the collector, and the data survived in an archive of that machine. Three of the six venues have since been shut down or seized, so this is the only form in which those books still exist.

TableVenueQuoteRowsFirstLastZero ratio
bayesdata_bitfinexBitfinexUSD10,123,3562014-12-172015-11-060.45%
bayesdata_btcchinaBTCChinaCNY10,838,9692014-12-172015-11-070.03%
bayesdata_okcoinOKCoinUSD8,468,4992014-12-172015-11-070.03%
bayesdata_bitstampBitstampUSD3,390,1362014-12-172015-11-061.79%
bayesdata_btceBTC-eUSD2,244,7862014-12-172015-11-070.02%
bayesdata_okcoin_cnyOKCoinCNY2,124,6492014-12-232015-11-0514.69%
Row counts and spans measured by streaming the source dump. The last column is an upper bound on contamination, explained below.

Columns

Five per table, identical across all six: dateline, last_trade, current_bid, current_ask and book_ratio. There is no volume column anywhere in this era and no size at the top of book.

Prices were stored in cents, and are published in major units

The three price columns were int unsigned counts of cents in the source database, so 31910 meant $319.10. At that era's prices this is full precision rather than rounding, which is the opposite of the modern series' problem. The import converts them to major units once, so the published files carry 319.10 and nothing has to divide by a hundred downstream.

Two of the six tables are quoted in yuan, not dollars: bayesdata_btcchina and bayesdata_okcoin_cny. Their columns have the same names as everywhere else because the quote currency belongs to the venue rather than to the column. No conversion is applied to them, and none should be, since applying one would assert an exchange rate the venue never quoted.

The ratio is a top-sixty-levels imbalance, not a price band

The 2014 collector summed resting volume across the top sixty levels per side of whatever the venue returned, and stored (bid volume - ask volume) / total in book_ratio, running from -1 for an all-ask book to +1 for an all-bid one. Sixty levels covers a different fraction of the book on every venue and at every moment, so the window this number looks through is not fixed and is not comparable to either of the others. Details under the three definitions below.

Zeros can be fabricated, and are kept anyway

The 2014 loop inserted a row even when the order book fetch failed, and every column carried a DEFAULT '0.00000'. A failed depth fetch therefore stored a ratio of exactly zero, indistinguishable row by row from a genuinely balanced book. The zero-ratio column in the table above counts those rows, which makes it an upper bound on the contamination rather than a measurement of it. OKCoin's yuan book at 14.69% is badly affected, the four large venues sit under half a percent.

Nothing was rewritten. Nulling those rows would have manufactured data, since some of them are real. The bound is published beside the data instead, and the filter you want in almost every case is:

WHERE book_ratio <> 0

Prices carry no such contamination. The insert was gated on the last trade parsing as a positive number, so a failed ticker fetch wrote no row at all.

Cadence

Two seconds nominal, and drifting. The loop guarded on the previous update being at least a second old and slept 60 milliseconds between passes, so the actual interval follows how long each venue took to answer. Expect deltas around two seconds with a long tail, and resample rather than assuming a grid.

The OKCoin fragment from November 2014

A second archive dump, from a machine that ran an earlier build of the same collector, holds 717,000 OKCoin rows from 2 November to 19 November 2014, six weeks before the main series starts. They are merged into the OKCoin table on import, with overlapping timestamps resolved in favour of the main series, so the OKCoin coverage begins earlier than every other venue's. If that asymmetry matters to what you are doing, cut all six tables to a common start date.

What the Chinese venues' volumes were worth, and why it barely matters here

Through 2014 and 2015 the large Chinese exchanges charged no trading fee, and their reported volumes were widely disputed at the time as inflated by wash trading. No credible correction factor was ever established. What saves this dataset from the question is that it has no volume column: bayesdata_btcchina and bayesdata_okcoin_cny record a price, a best bid, a best ask and a book imbalance. Read them as a record of what those books looked like, and do not read them as evidence of how much really changed hands.

The modern series

Collected, not published. This era is the research the project runs on, and no part of it is a release. There is nothing to download here and nothing scheduled. It is described because the older files were collected by the same hand for the same reasons, and because the depth column below is the third of the three definitions the eras do not share.

Running since 1 March 2024 at ten-second cadence. Sixteen series in total, four pairs on each of Bitstamp, Kraken, Bitfinex and MEXC.

The order book ratio here is a price band, not a level count. It sums resting base-currency volume within 2% of the best price on each side and stores (bid volume - ask volume) / total. Both venues' books cover that band with room, so the two are directly comparable to each other. Bitstamp additionally carries a 5% version. Kraken does not, and must not be given one, because its book does not reach that far.

Three seams

The collectors were rebuilt in August 2026 and the tables changed under the running series three times. Nothing was rewritten, so the history is exactly as it was recorded, and code that crosses a seam has to know it is there. All times are CEST, the host's local zone at the time.

WhenWhat changed
2026-08-21 21:57Prices went from integer dollars to two decimal places, and the tables from MyISAM to InnoDB. Every row before this point has its cents truncated.
2026-08-21 22:28:35bid_size and ask_size went live. NULL before, populated after, no backfill, because the sizes were never fetched before this.
2026-08-22 10:43:43The trade timing and depth columns went live, six on Bitstamp and nine on Kraken. Same pattern, NULL before and populated after.
A fourth change, at 2026-08-21 21:43, pinned the sample grid to wall clock. It added no column, so the only trace of it is in the interval statistics.

Where this series is defective

On the record for the same reason the other two eras' faults are, even though these files are not published. Anyone who is handed a slice of this data privately gets the list with it.

  1. Cents are truncated on every row before 2026-08-21 21:57, across 903 days, and cannot be repaired. current_bid == current_ask on those rows is rounding, not a locked market, and the spread is not recoverable before that seam.
  2. book_ratio = 0.00000 is ambiguous on a small number of rows, 134 on Bitstamp and 233 on Kraken, which are failed fetches recorded as a balanced book. Same filter as the older era, WHERE book_ratio <> 0.
  3. Three Bitstamp rows carry current_bid = 0, same cause.
  4. Two sampling regimes. Before 2026-08-21 21:43 the loop slept a flat ten seconds after its work, so the grid walked: mean interval 10.250 s on Bitstamp and 10.308 s on Kraken. After it, 10.019 s and 10.000 s, jittering either side of a second boundary. A gap of nine seconds is the signature of the later regime, since the earlier one could never produce one.
  5. One over-dense window, 2026-08-21 21:34:47 to 21:44:44, where two supervisors briefly ran the collectors at once. About 147 extra rows across the two tables. They are genuine independent readings, and anything sensitive to sample rate should still drop the window.
  6. The two venues are not aligned with each other. They run as independent processes. Over one measured day, 8,462 Bitstamp rows and 8,432 Kraken rows shared only 917 timestamps. A JOIN ... USING (dateline) silently discards about 89% of the data, so cross-venue work needs an as-of join or a common bucket.
  7. Sizes and prices came from two payloads until the third seam. The top of book sizes are read from the order book, current_bid and current_ask from a ticker call a fraction of a second earlier. After 2026-08-22 10:43:43 the row carries book_bid and book_ask, the prices of the very snapshot the sizes came from, and those are the ones to pair with a size.
  8. Outages account for about 0.2% of the span, 586 gaps over a minute on Bitstamp and 312 on Kraken, worst single gaps 4.2 and 6.3 hours. Nine of the fourteen gaps over half an hour hit both collectors within two seconds of each other, which puts the cause on the collecting host rather than at the exchanges. Drift costs far more rows than downtime does, roughly 2.2% against 0.2%.

Three eras, three definitions of depth, never one series

Every era carries a column that means "the book leans this way". Every one of them measures it through a different window, and two of the three are not even on the same scale.

EraColumnWindowScaleSign
2011bidscore, askscore, diffWithin $0.50 of the best price, each level weighted by 1/(1+distance)²Unbounded log ratio of the two scoresNegative is bid-heavy
2014-2015book_ratioTop sixty levels a side, whatever price range that spans-1 to +1Positive is bid-heavy
2024 onwardbook_ratioWithin 2% of the best price, however many levels that takes-1 to +1Positive is bid-heavy

The windows do not line up and cannot be made to. Fifty cents was eight to twenty-five percent of price in 2011 and would be a hundredth of a percent today. Sixty levels reaches a long way out on a thin book and stops inside a few basis points on a deep one. Only the 2% band means the same thing at every price, and it is the one era that is not published.

So a chart of any two of these on one axis is a chart of two different measurements sharing a colour. The explorer on bitcoincalc.com will not draw it: it takes one era at a time, and it turns the imbalance view off entirely for 2011, because a log ratio has no business on a -1 to +1 axis. Any cross-era work has to say which definition it used and stop there, and any published result has to carry the same caveat. This is the single most important line on the page.

The fee index, which is derived rather than collected

There is a fourth thing on this site and it is not an era. The fee index is computed here every Monday from public on-chain aggregates, daily since August 2010: total fees over estimated transfer volume, the same ratio with miner revenue in place of fees, and the median transaction's fee against its own size. None of it was collected by this project and none of it touches the three eras above.

It carries its own methodology, because the problem it has is a different one. The eras above are honest about how they measured a book. The fee index has an exact numerator and a denominator that no heuristic can verify, since a Bitcoin transaction's outputs mix the payment with the change returned to the sender and stripping change is guesswork with no ground truth to check it against. That argument, the seven ways the number can mislead a reader, and the sources are on the page itself rather than repeated here.

Two site-wide rules bend for it, deliberately. The freshest row on this page's eras is a release old, while the fee index chart is current to within a week, because it has no exchange on the other end of it and a weekly cadence is the whole point of the series. And its release is quarterly rather than one-and-done, because the series does not end.

Where these numbers come from

Everything above was measured rather than remembered: the 2011 and 2014 row counts, spans and zero fractions by streaming the source dumps, the modern intervals, gaps and value ranges by querying the live tables. Each release's manifest.json carries the same provenance in machine-readable form, and each historical file also carries it internally in a _meta table, so a copy of the data explains itself years from now without this website.

How to cite this.