{"slug":"llm-generated-alpha-factors","qid":"best_of_n","label":"The best score climbs with the size of the search: best and average Sharpe by trials run","post_title":"Can an LLM Find Alpha Factors?","post_url":"/blog/llm-generated-alpha-factors#q-best_of_n","columns":["factors_tried","best_sharpe","average_sharpe"],"rows":[{"factors_tried":1,"best_sharpe":0.44,"average_sharpe":0.44},{"factors_tried":2,"best_sharpe":0.44,"average_sharpe":0.36},{"factors_tried":5,"best_sharpe":0.44,"average_sharpe":-0.18},{"factors_tried":10,"best_sharpe":0.52,"average_sharpe":-0.12},{"factors_tried":25,"best_sharpe":0.73,"average_sharpe":-0.03},{"factors_tried":50,"best_sharpe":0.73,"average_sharpe":-0.04},{"factors_tried":100,"best_sharpe":1.1,"average_sharpe":-0.04},{"factors_tried":160,"best_sharpe":1.59,"average_sharpe":-0.04},{"factors_tried":240,"best_sharpe":1.59,"average_sharpe":0.01}],"shape":"ranking","sql":"WITH month_end AS (\n    SELECT ticker,\n           toStartOfMonth(toDate(toTimeZone(window_start, 'America/New_York'))) AS month_start,\n           argMax(toFloat64(close), window_start) AS close_px\n    FROM global_markets.delayed_stocks_minute_aggs\n    WHERE ticker IN ('AAPL','ADBE','AMZN','BA','CAT','COST','CRM','CSCO','CVX','DE',\n                     'DUK','GE','GOOGL','HD','HON','IBM','INTC','JNJ','JPM','KO',\n                     'LMT','MCD','MMM','MRK','MSFT','NKE','NVDA','ORCL','PEP','PFE',\n                     'PG','QCOM','SO','T','TGT','TXN','UNP','VZ','WMT','XOM')\n      AND toDate(toTimeZone(window_start, 'America/New_York')) >= toDate('2015-12-01')\n      AND toDate(toTimeZone(window_start, 'America/New_York')) <= toDate('2021-06-30')\n      AND toDayOfMonth(toTimeZone(window_start, 'America/New_York')) >= 22\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 ticker, month_start\n),\nlagged AS (\n    SELECT ticker,\n           month_start,\n           close_px,\n           lagInFrame(close_px) OVER (PARTITION BY ticker ORDER BY month_start\n                                      ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prev_px\n    FROM month_end\n),\nmonthly_return AS (\n    SELECT ticker, month_start, close_px / prev_px - 1 AS ret\n    FROM lagged\n    WHERE prev_px > 0\n      AND month_start >= toDate('2016-01-01')\n),\ntrial AS (\n    SELECT arrayJoin(range(1, 241)) AS n\n),\nfactor_month AS (\n    SELECT t.n AS trial_id,\n           m.month_start AS month_start,\n           avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1)\n         - avgIf(m.ret, bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) AS long_short_ret\n    FROM monthly_return AS m\n    CROSS JOIN trial AS t\n    GROUP BY trial_id, month_start\n    HAVING countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 1) > 0\n       AND countIf(bitAnd(cityHash64(m.ticker, toString(m.month_start), t.n), 1) = 0) > 0\n),\nscored AS (\n    SELECT trial_id,\n           avg(long_short_ret) / stddevSamp(long_short_ret) * sqrt(12) AS sharpe\n    FROM factor_month\n    GROUP BY trial_id\n    HAVING stddevSamp(long_short_ret) > 0\n),\nladder AS (\n    SELECT arrayJoin([1, 2, 5, 10, 25, 50, 100, 160, 240]) AS n\n)\nSELECT l.n AS factors_tried,\n       round(max(s.sharpe), 2) AS best_sharpe,\n       round(avg(s.sharpe), 2) AS average_sharpe\nFROM ladder AS l\nCROSS JOIN scored AS s\nWHERE s.trial_id <= l.n\nGROUP BY factors_tried\nORDER BY factors_tried","computed_at":"2026-08-02T08:34:52.969681+00:00","elapsed":28.424849104}