{"slug":"kelly-criterion-position-sizing","qid":"bet_size_grid","label":"One decade of S&P 500 daily returns compounded at eight fixed bet sizes: ending wealth and worst drawdown","post_title":"Kelly Criterion Position Sizing, Measured","post_url":"/blog/kelly-criterion-position-sizing#q-bet_size_grid","columns":["bet_size","ending_multiple","max_drawdown_pct"],"rows":[{"bet_size":"0.5x","ending_multiple":1.92,"max_drawdown_pct":18.2},{"bet_size":"1x","ending_multiple":3.39,"max_drawdown_pct":34.2},{"bet_size":"1.5x","ending_multiple":5.52,"max_drawdown_pct":48},{"bet_size":"2x","ending_multiple":8.27,"max_drawdown_pct":59.6},{"bet_size":"2.5x","ending_multiple":11.37,"max_drawdown_pct":69.2},{"bet_size":"3x","ending_multiple":14.34,"max_drawdown_pct":77},{"bet_size":"4x","ending_multiple":17.4,"max_drawdown_pct":88.1},{"bet_size":"5x","ending_multiple":14.35,"max_drawdown_pct":94.5}],"shape":"ranking","sql":"WITH daily AS (\n    SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS dt,\n           argMax(toFloat64(close), window_start) AS c\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE ticker = 'SPY'\n      AND window_start >= '2016-01-01 00:00:00'\n      AND window_start <  '2026-01-01 00:00:00'\n      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60\n           + toMinute(toTimeZone(window_start, 'America/New_York'))) BETWEEN 570 AND 959\n    GROUP BY dt\n),\nsteps AS (\n    SELECT dt, c,\n           lagInFrame(c) OVER (ORDER BY dt ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev\n    FROM daily\n),\nrets AS (\n    SELECT dt, c / prev - 1 AS ret\n    FROM steps\n    WHERE prev > 0\n),\nsizes AS (\n    SELECT arrayJoin([0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0]) AS bet\n),\npaths AS (\n    SELECT bet, dt,\n           exp(sum(log(greatest(1 + bet * ret, 0.0001)))\n               OVER (PARTITION BY bet ORDER BY dt\n                     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)) AS equity\n    FROM rets CROSS JOIN sizes\n),\npeaks AS (\n    SELECT bet, dt, equity,\n           max(equity) OVER (PARTITION BY bet ORDER BY dt\n                             ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS peak\n    FROM paths\n)\nSELECT concat(toString(bet), 'x') AS bet_size,\n       round(argMax(equity, dt), 2) AS ending_multiple,\n       round(100 * max(1 - equity / peak), 1) AS max_drawdown_pct\nFROM peaks\nGROUP BY bet\nORDER BY bet","computed_at":"2026-07-31T03:07:14.442502+00:00","elapsed":18.971988723}