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
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
- 01Bitcoin and the S&P 500, monthly
SELECT * FROM read_csv_auto('FRED_CBBTCUSD_SP500.csv', header=true) - 02Assumptions — edit these
SELECT * FROM (VALUES ('Amount invested', 10000, 'USD')) AS t(assumption, value, unit) - 03What $10,000 grew intobuckets values by condition · filters to the relevant rows · sorts the output
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 - 04The punch linesbuckets values by condition · computes running / windowed totals · appends result sets (e.g. a TOTAL row)
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 →