Ansh Dani

Cross-venue price discovery in BTC-USD

When bitcoin's price moves, does one exchange tend to move first? I built collectors for the public Coinbase and Kraken BTC/USD feeds, recorded synchronized sessions, and tested whether each venue's quote changes help forecast the other's a fraction of a second later. Lead-lag between venues matters to anyone quoting on both, but clock errors and look-ahead can manufacture it, so the limits below matter as much as the headline.

Data

I recorded 10 accepted collection windows of about 31 minutes each between 2026-07-31 and 2026-08-08 (UTC), about 5.2 hours of paired overlap. The tests use top-of-book quotes only: returns are changes in each venue's mid-price. Trades were recorded but are not used in these tests. Quotes are aligned on a 100 ms grid where each point takes the latest quote at or before it, so no future quote can enter; a point is rejected if either quote is more than 2 seconds old. Each session is modeled on its longest unbroken run, and nine sessions had enough data: 343 to 7,831 returns each, about 20 minutes in total.

Method

For each session I fit a vector autoregression, with the lag chosen by BIC up to 1 second (it picked 100, 200 or 600 ms), and ran Granger tests in both directions: do past Coinbase returns improve the forecast of Kraken returns, and the reverse? I corrected with Benjamini–Hochberg at a 5% false discovery rate over all 18 session-by-direction tests. The settings were frozen in a configuration file, but it was committed with the analysis code after most sessions were collected, not as a separate pre-registration. The final run was repeated after 15 implementation errors were fixed, with the same settings but not blind to the first result.

Results

Coinbase predicted Kraken in 6 of 9 sessions after correction, against 1 of 9 in reverse (7 and 2 before correction; still 6 and 1 under Holm or Bonferroni). One-step predictive regressions are weaker: the Coinbase coefficient is positive in 8 of 9 sessions but individually significant in only 2. The session with the longest sample (7,831 returns) dominates the pooled p-values.

Long-run price discovery shows no fixed leader. Only 4 of the 9 sessions met the cointegration requirement for those measures, and they point different ways: Coinbase-dominant information-share bounds in two, Kraken-dominant in one, inconclusive in one.

Limits

Nine short sessions from one summer week is a small sample. Timestamps are each exchange's own, with no clock-offset correction; an offset of a few tens of milliseconds is comparable to the 100 ms grid and could shift or create an apparent lead. The two quote feeds update on different events (Coinbase's on trades, Kraken's on best bid or offer changes). The Granger tests were run only on the 100 ms grid. Granger tests show prediction, not causation, and nothing here is a trading result after fees and latency.

Reproduce it

These README commands install the package and run the checks and unit tests. The raw exchange messages are not in the repository, so the empirical results cannot be regenerated from it; the final tables, figures and their SHA-256 manifest are committed under results/final/generated/.

python3.12 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
python -m ruff check .
python -m pytest -q tests/unit
make check

GitHubFinal results