During one of my analyses, I pulled on-chain insights from Bitcoin's BigQuery dataset, wrote an anomaly detector for time-series metrics, and poked around an Ethereum address. I never got to build on any of it afterward. This project revisits that same territory on my own terms, with the one big constraint changed: instead of a paid BigQuery dataset, everything here runs on free public APIs, and instead of a one-off exercise, it has to actually answer a real question. Does big-wallet ("whale") transaction activity actually move the Bitcoin price, or is that just a story crypto Twitter tells itself?
This is the write-up. The live demo is linked at the bottom, and the repository is public.
Three free APIs standing in for a BigQuery dataset
The original challenge pointed at Google's BigQuery Bitcoin dataset, which is genuinely excellent but needs a GCP account, billing set up, and a query-cost budget to manage. None of that is a good fit for a self-contained public demo, so this project swaps in three sources that need no account and no API key at all:
rawblock returns an entire block, every transaction with every output value, in one HTTP call. That makes it practical to check every single transaction in a real recent window rather than statistically sampling. It does not make it practical to do that for a full year: roughly 52,000 blocks, well over 300GB of JSON, is not a demo-project ask. So the whale dataset here is real and exhaustive, just deliberately bounded to the most recent window rather than dressed up as more history than it is.
flowchart TD
A["CoinGecko\nmarket_chart API"] -->|"daily price, market cap, volume"| D["daily_metrics.csv"]
B["blockchain.info Charts API"] -->|"active addresses, tx count, hash rate"| D
C["blockchain.info rawblock API"] -->|"real recent block window"| E["whale_transactions.csv"]
E --> F["whale_daily.csv\ntx count + BTC volume"]
D --> G["ESD anomaly test\nprice, active addresses"]
D --> H["lead-lag correlation\nwhale volume vs price returns"]
F --> H
G --> I["dashboard_data.json"]
H --> I
F --> I
D --> I
I --> J["static/index.html\nsynced to forwardforecasting-landing"]
Why a 1983 statistics paper instead of a model
The event-detection task in the original challenge asked for exactly this: flag anomalous points in a time series, ideally without hand-tuning a threshold per series. My answer then was a generalized ESD (Extreme Studentized Deviate) test, from Rosner's 1983 paper, run on the residuals of a series against its own moving average. It is old, it is auditable line by line, and it still works, so I reimplemented it here as a small functional module instead of the original stateful class, and applied it independently to the BTC price series and the active-addresses series.
The result I didn't fake
The interesting question this project set out to answer is whether whale activity leads price moves, lags them, or does neither. The pipeline computes exactly that: Pearson and Spearman correlation between daily whale BTC volume and price returns, at lags from -3 to +3 days. On the run currently live on the dashboard, the honest answer is that the test could not run at all.
The reason is straightforward once you see it: the whale scan window is real chain activity, but it only spans about two days (150 blocks at roughly 10 minutes each), while the price and on-chain series are daily. Two data points is not a correlation, it's a coin flip. Rather than compute a Pearson r on two rows and print a number that looks precise but means nothing, the pipeline checks the overlap first and says plainly when there isn't enough of it. That is a duller sentence than "whales don't move the market" or "whales do move the market," and it's the honest one.
| Metric | Value |
|---|---|
| BTC/USD (latest) | $77,127 |
| 30-day price change | +22.4% |
| Whale transactions (≥50 BTC), 150 blocks scanned | 2,177 |
| Total whale volume, ~2-day window | 696,791 BTC |
| ESD-flagged price anomalies | 2 |
| ESD-flagged active-address anomalies | 1 |
| Annualized volatility | 44.1% |
The anomaly detector, which doesn't need the same daily overlap the correlation test does, worked exactly as intended: two price days and one active-address day got flagged by the ESD test on this run, each one an actual statistical outlier against its own trailing average, not a fixed percentage-move threshold picked by hand.
Why statistics, not machine learning
A tempting version of this project trains a classifier on whale features to predict next-day price direction. I didn't build that one, for reasons that matter more than "it would take longer":
What actually broke
The most concrete bug worth admitting: the first deployed version of the dashboard shipped with its charts pinned to Chart.js 4.4.4 loaded from cdnjs. That version simply isn't published at that path, cdnjs returns a 404 for it, so the script tag silently failed to load and every chart canvas rendered as an empty black box, dark background, no data, no error visible to a casual look. The fix was pinning to 4.4.1, an actual published build, and it's exactly the kind of failure that only shows up when you check the live page rather than trusting that "the code ran" means "the page works."
The stack, briefly
What it costs to run
Nothing. Every data source is a free, keyless public API, there's no server and no database, and the deployed page is a static file synced onto infrastructure that already runs everything else on this domain. The only real cost anywhere in this write-up was the AWS Bedrock call that generated the cover image above.
What's next
The single highest-value addition is a proper address-label database: a small schema for address, label, source, and confidence, seeded from public sources like mining-pool lists, so whale transactions can be split into "exchange inflow/outflow" versus "unknown wallet" instead of one undifferentiated bucket. That, plus a longer whale backfill from a local Bitcoin Core node instead of one HTTP call per block, is what would turn the correlation test from "not enough overlap to check" into an actual answer.
Try it
The live demo at forwardforecasting.eu/blockchain-analytics has the real price and on-chain charts, the whale-activity breakdown, the anomaly markers, and the correlation panel exactly as described here, including the honest "not enough data" line when that's what's true. The code, whale-detection logic, ESD implementation, and the Chart.js version bug included, is public.
See it live
Real price and on-chain data, a real scan of real blocks, and an answer that stays honest when the data doesn't support a headline.
Open the demo → View on GitHub →About the cover image: the golden whale gliding along its own candlestick trail is a literal read on the project's actual question, whether a whale's movement traces the price chart's path or just happens to share the same space. ImageModelstability.stable-image-core-v1:1 · AWS Bedrock (us-west-2)Prompt“Editorial illustration, a golden whale silhouette breaching through a glowing candlestick price chart made of light, deep navy background, minimalist flat vector illustration style, clean geometric linework, no text, no logos”