Screener methodology
How Drogo screeners filter the live universe, what data each filter uses, and how often it updates.
Last reviewed:
Universe & cadence
The default screener universe is "all US-listed common equities and ETFs with a primary listing on NYSE, NASDAQ, NYSE-American, or Cboe BZX, plus the top 200 crypto pairs by 30-day rolling spot volume on Binance and Coinbase". Users can narrow this to S&P 500, Nasdaq 100, Russell 2000, sector ETFs, or a custom watchlist.
Filters that use price/volume data refresh on every screener run and read from the last completed bar at the user's selected resolution (default: 1D). Filters that use fundamentals (P/E, market cap, sector, industry) refresh nightly from Polygon's fundamentals snapshot. Filters that use derived signals (RSI, breakouts, gaps) are recomputed on each run from the underlying OHLCV — they are not cached at the value level.
Filter taxonomy
Price filters — last price between $X and $Y, intraday gap ≥ X%, return over last N days ≥ X%. Computed from /history. No survivorship adjustment is applied to live filters because the live universe is by definition non-delisted.
Volume filters — average daily dollar volume over last N days ≥ $X, today's volume ≥ X× the N-day average. Dollar-volume thresholds are recommended over share-volume thresholds because they handle high-priced stocks (BRK.A) and low-priced stocks (penny stocks) correctly.
Indicator filters — RSI(14) ≤ X (oversold) or ≥ Y (overbought), MACD signal cross, 50-day vs 200-day SMA, ATR(14) ≥ X% of price (volatility regime). All indicators use Wilder's formulas where applicable; see the signals methodology page for exact definitions.
Fundamental filters — market cap, P/E, P/B, dividend yield, EPS growth YoY, sector, industry. Source: Polygon fundamentals as of last completed quarter.
Backend pipeline
A screener run is a stateless POST to /screener/run carrying the JSON-encoded filter payload. The data API resolves each filter against Redis-cached OHLCV slices (TTL 60s on the most recent bar, 5 minutes on older bars), computes derived signals on the fly, intersects the symbol sets, and returns a deduplicated list of tickers ordered by liquidity (descending dollar volume).
The terminal's in-app screener UI and the public /screeners/{slug} SSR pages call the same endpoint with the same canonical filter set, so what you see on the public page is bit-for-bit what you would see if you opened the screener in the terminal at the same moment (modulo the ~60s cache window).
Limitations & known biases
Public screener pages show only the top 50 results, ranked by liquidity. The full result set is available in the terminal.
Screeners that use intraday resolutions during regular trading hours can produce inconsistent results across reruns within the same minute, because the in-progress bar is excluded but its volume is monotonically increasing. This is intentional — quoting on the in-progress bar would cause look-ahead in any user-defined alert built on top of the screener.
Crypto screeners exclude pairs that have less than 14 days of trading history, even if they technically pass the user's filters. This avoids "new listing" pump artifacts.
How we choose the canonical screener slugs
The canonical screener catalog (src/lib/seo/screener-catalog.ts) lists the screeners that have a stable public URL. We add a slug only if (a) the underlying filters are unambiguous and language-independent, (b) the result set has had at least one match every trading day for the past 90 days, and (c) the strategy concept is documented in a Learn article.
Screeners that depend on a specific user's context (their watchlist, custom indicators, private notes) do not get public slugs.
Changelog
- — Initial publication.
- — Documented public-page top-50 result cap and explained why crypto pairs require ≥ 14 days of history.
References
Drogo Research — Quant editorial
נבדק לדיוק עובדתי; המתודולוגיה מקושרת למטה.