Bitcoin vs the S&P 500: $10,000, Five Years Ago

$10,000 in Bitcoin vs $10,000 in the S&P 500 five years ago: what each is worth now, the winner, and how deep each one fell on the way. Official data, pulled fresh.

4 steps · shared by Klajdi · September 25, 2026
Make it your own →
No data is shared in this template. It contains only the recipe — column names and SQL logic. When you run it, your data is processed in your own browser and never leaves your machine.

How it works — every step, readable

  1. 01Bitcoin and the S&P 500, monthly
    SELECT * FROM read_csv_auto('FRED_CBBTCUSD_SP500.csv', header=true)
  2. 02Assumptions — edit these
    SELECT * FROM (VALUES ('Amount invested', 10000, 'USD')) AS t(assumption, value, unit)
  3. 03What $10,000 grew into
    WITH a AS (SELECT MAX(CASE WHEN assumption = 'Amount invested' THEN CAST(value AS DOUBLE) END) AS amt FROM input_2),
    d AS (SELECT * FROM input_1 WHERE cbbtcusd IS NOT NULL AND sp500_idx IS NOT NULL),
    f AS (SELECT * FROM d ORDER BY date LIMIT 1)
    SELECT d.date, ROUND(a.amt * d.cbbtcusd / f.cbbtcusd, 2) AS bitcoin_value, ROUND(a.amt * d.sp500_idx / f.sp500_idx, 2) AS sp500_value
    FROM d, f, a ORDER BY d.date
  4. 04The punch lines
    WITH g AS (SELECT *, max(bitcoin_value) OVER (ORDER BY date) AS bpk, max(sp500_value) OVER (ORDER BY date) AS spk FROM input_1),
    f AS (SELECT * FROM g ORDER BY date LIMIT 1), l AS (SELECT * FROM g ORDER BY date DESC LIMIT 1),
    dd AS (SELECT min(bitcoin_value / bpk - 1) AS bdd, arg_min(date, bitcoin_value / bpk) AS bdd_d, min(sp500_value / spk - 1) AS sdd FROM g),
    s AS (SELECT f.bitcoin_value AS amt, l.bitcoin_value AS bv, l.sp500_value AS sv, f.date AS d0 FROM f, l)
    SELECT area, finding, next_step FROM (
      SELECT 1 AS o, 'VERDICT' AS area, '▲ ' || CASE WHEN bv >= sv THEN 'BITCOIN' ELSE 'THE S&P 500' END || ' WINS — ' || ('$' || format('{:,}', CAST(ROUND(bv) AS BIGINT))) || ' vs ' || ('$' || format('{:,}', CAST(ROUND(sv) AS BIGINT))) || ' from ' || ('$' || format('{:,}', CAST(ROUND(amt) AS BIGINT))) || ' in ' || strftime(d0, '%B %Y') AS finding, '' AS next_step FROM s
      UNION ALL SELECT 2, ('$' || format('{:,}', CAST(ROUND(amt) AS BIGINT))) || ' in Bitcoin', ('$' || format('{:,}', CAST(ROUND(bv) AS BIGINT))) || ' today', printf('%+.0f%%', 100.0 * (bv / amt - 1)) || ' since ' || strftime(d0, '%b %Y') FROM s
      UNION ALL SELECT 3, ('$' || format('{:,}', CAST(ROUND(amt) AS BIGINT))) || ' in the S&P 500', ('$' || format('{:,}', CAST(ROUND(sv) AS BIGINT))) || ' today', printf('%+.0f%%', 100.0 * (sv / amt - 1)) || ' since ' || strftime(d0, '%b %Y') FROM s
      UNION ALL SELECT 4, 'Bitcoin''s worst drop', printf('%+.0f%%', 100.0 * (bdd)) || ' from its high', 'Bottomed in ' || strftime(bdd_d, '%B %Y') || ' — could you have held?' FROM dd
      UNION ALL SELECT 5, 'The S&P''s worst drop', printf('%+.0f%%', 100.0 * (sdd)) || ' from its high', 'Month-end prices' FROM dd
    ) ORDER BY o

Run this on your books

Free to try — no sign-up, no card. The workflow runs in your browser; your data never leaves your machine.

Make it your own →