Kelly Criterion Position Sizing, Measured
Kelly inputs from daily closes, 2016 through 2025: win rate, average gain, average loss, and the fraction the formula returnstable ·
2026-07-31 · 6×5
The same Kelly calculation on the S&P 500 tracker, year by year, 2016 through 2025table ·
2026-07-31 · 10×5
One decade of S&P 500 daily returns compounded at eight fixed bet sizes: ending wealth and worst drawdownranking ·
2026-07-31 · 8×3
Kelly inputs from daily closes, 2016 through 2025: win rate, average gain, average loss, and the fraction the formula returns
Kelly inputs from daily closes, 2016 through 2025: win rate, average gain, average loss, and the fraction the formula returns
| ticker | win_rate_pct | avg_gain_pct | avg_loss_pct | full_kelly_x |
|---|---|---|---|---|
| SPY | 55.3 | 0.71 | 0.76 | 10.1 |
| MSFT | 54.1 | 1.17 | 1.16 | 7.4 |
| JNJ | 51.8 | 0.79 | 0.77 | 5.8 |
| KO | 53 | 0.76 | 0.8 | 4.4 |
| NVDA | 54.6 | 2.28 | 2.3 | 3.8 |
| TSLA | 52 | 2.71 | 2.64 | 2 |
the exact SQL behind every number
WITH daily AS (
SELECT ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS dt,
argMax(toFloat64(close), window_start) AS c
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'KO', 'JNJ', 'MSFT', 'NVDA', 'TSLA')
AND window_start >= '2016-01-01 00:00:00'
AND window_start < '2026-01-01 00:00:00'
AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
+ toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959
GROUP BY ticker, dt
),
steps AS (
SELECT ticker, dt, c,
lagInFrame(c) OVER (PARTITION BY ticker ORDER BY dt
ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev
FROM daily
),
rets AS (
SELECT ticker, c / prev - 1 AS ret
FROM steps
WHERE prev > 0 AND c != prev
)
SELECT ticker,
round(100 * countIf(ret > 0) / count(), 1) AS win_rate_pct,
round(100 * avgIf(ret, ret > 0), 2) AS avg_gain_pct,
round(100 * abs(avgIf(ret, ret < 0)), 2) AS avg_loss_pct,
round(countIf(ret > 0) / count() / abs(avgIf(ret, ret < 0))
- countIf(ret < 0) / count() / avgIf(ret, ret > 0), 1) AS full_kelly_x
FROM rets
GROUP BY ticker
HAVING countIf(ret > 0) > 0 AND countIf(ret < 0) > 0
ORDER BY full_kelly_x DESC
More from this analysisKelly Criterion Position Sizing, Measured
The same Kelly calculation on the S&P 500 tracker, year by year, 2016 through 2025
table 10×5
→
One decade of S&P 500 daily returns compounded at eight fixed bet sizes: ending wealth and worst drawdown
ranking 8×3
→
S&P 500 tracker (SPY): down sessions by calendar year, 2016 to mid-2026
table 11×5
→
One-day move profile, seven household names, July 2025 to June 2026
table 7×6
→
See all 2,173 queries →