Every stock screener ranks by the same things: RSI under 30, price above the 50-day, a volume spike, a MACD cross. They rank by what the chart looks like right now. None of them rank by the thing you actually care about — what setups that looked like this did next.
So we built one that does. And building it forced us to confront an uncomfortable, useful truth about chart patterns.
The idea: rank by the cohort's outcome
Chart Library retrieves, for any (symbol, date), a cohort of ~40–50 historically similar setups across 10 years and 19K+ symbols, then looks at what those analogs actually did over the next 1/3/5/10 days — the full forward-return distribution, every number a real historical fact, not a generation.
The Outcome Screener runs that across the whole market and ranks names by their cohort's expected move. Instead of "show me oversold stocks," you ask "show me names whose look-alikes historically made the biggest moves next." That's a fundamentally different — and more honest — sort key.
The uncomfortable truth: shape predicts size, not direction
Here's what fell out when we validated it on 300K+ historical cohort observations:
- Direction is ~unpredictable. The correlation between a cohort's historical mean return and the anchor's realized direction is ≈ −0.015 — a coin flip. A "bullish-looking" cohort wins 52% of the time vs a 54% baseline. There's no there there.
- Magnitude is predictable. The correlation between cohort dispersion and the realized absolute move is ≈ +0.20, and it's monotonic across quintiles — wider cohort, bigger realized move, reliably.
So we made a deliberate product decision: the screener ranks by expected magnitude, and refuses to rank by predicted direction. Most "AI alpha" tools quietly do the opposite — they sell you a direction they can't actually call. We'd rather ship the signal that survives validation.
And expected magnitude is useful even without a direction call — it's exactly what you need for option premium, position sizing, and stop placement. Knowing a name is primed for a 12% move (vs a 4% one) changes how you trade it regardless of which way it breaks.
A detail that mattered: robust estimators
The first version ranked a mega-cap to the top with a "320% expected move." It wasn't signal — it was an outlier-corrupted standard deviation. Naive std/mean over a cohort's forward returns gets wrecked by a single 10x penny-stock day.
The fix was to estimate dispersion robustly:
- For raw returns: MAD × 1.4826 (median absolute deviation — the consistent estimator of σ for a normal), falling back to std only when MAD degenerates.
- For stored percentiles: IQR / 1.349 (the normal-consistent σ from the interquartile range), with a sanity guard.
import numpy as np
def robust_sigma(returns: np.ndarray) -> float:
"""Dispersion that ignores the one insane bar instead of being dragged by it."""
med = np.median(returns)
mad = np.median(np.abs(returns - med))
sigma = 1.4826 * mad
return sigma if sigma > 0 else float(np.std(returns))
After the swap, the rankings became sane — and real. AMBA, for instance, surfaces with a ~12% expected move at ~1.9× its own baseline volatility, instead of a phantom mega-cap at 320%.
Use it three ways
- UI: chartlibrary.io/screener, plus Strategy Lab to backtest cohort-conditioned rules against base rates.
-
API:
GET /api/v1/screenerreturns ranked names with expected move + volatility ratio. -
Agent / MCP:
pip install chartlibrary-mcpgives Claude, Cursor, or a LangChain agent the same cohort tools. It's in the official MCP Registry.
The takeaway
A screener that ranks by outcome instead of appearance is more useful — but only if it's honest about what's actually predictable. Shape tells you how big, not which way. Build on the part that survives the backtest, and say so out loud.













