The Screener System — S1 → S2 → S3 Vision
Last verified
This is the why. For the mechanics — funnel stages, gate config, refresh cadences, the demotion cost-split, the data tables — see Screener Pipeline & Lifecycle (operations). For what each pattern looks for, see the archetype pages.
What the screener is for
The screener exists to do one thing well: take a large, noisy universe of liquid names and surface a small, high-conviction shortlist of dislocated single-name setups — then collect deep data on those names so the operator can act with confidence and so the platform accumulates a permanent, labeled history of “what a real setup looked like, and what happened next.”
It is not a list of everything that twitched. A wall of 200 candidates is noise wearing the costume of thoroughness. The job is to be the filter, not the firehose.
The three stages
The system has a single spine — an automatic data tier that deepens as a name proves it deserves attention — plus one manual control the operator owns.
S1 — the universe (hidden muck)
The full screen universe: the S&P 900 (S&P 500 + S&P 400 MidCap, ~903 names),
config-driven via screener_config.json → universe.tier. This is the raw
material — index-curated, liquid, and otherwise undifferentiated. It is hidden
by design. The operator never browses S1; the screener’s whole value is that it
reads S1 so you don’t have to. Every S1 name is run through every archetype on
each screener pass. S1 carries only the cheap data needed to score it (daily
OHLCV); nothing deep.
S2 — the screener shortlist (auto-selected, ~20, floating)
The names that survive the archetype gates. There is no hard cap. The count
floats — a calm tape yields a handful, a genuine dislocation yields more — and
that is a feature, not a bug: the board should surface more when there is
genuinely more to surface. The target is intense gates that naturally leave
~20, not a [:30] slice applied after the fact. The “dial” that controls
quality is the gate configuration, not a truncation.
S2 names get the deep datafeed refresh (options chain, estimates, sentiment, gamma) and appear on the screener board — the discovery surface. Promotion into and demotion out of S2 is automatic, driven entirely by whether a name clears the gates on a given pass.
S3 — the watchlist (manual, permanent)
S3 splits along a second axis (see below). The visible half is the operator’s permanent watchlist — the dropdown of names you actually care about. A name enters it only when the operator clicks Promote, and it stays until the operator clicks Demote. The screener never adds or removes names from your dropdown. This keeps the interface stable and uncluttered: you are never digging through a constantly-rotating list of names you didn’t choose.
The key insight: two orthogonal axes
The design that makes this work cleanly is separating data collection (automatic) from interface visibility (manual). They never fight.
| Data tier — automatic | Visibility — manual | |
|---|---|---|
| Driven by | the screener gates | the operator’s Promote / Demote |
| Controls | what data we collect + how often we refresh | what appears in the watchlist dropdown |
| Range | S1 → S2 → hidden-S3 | pinned / not pinned |
A name can be in any combination:
- S2-active + pinned — on the board, in your dropdown, full data. (You promoted a winner.)
- S2-active + unpinned — full data collected silently (hidden S3-auto), but NOT in your dropdown. The data is there if you ever want it; the interface stays clean.
- Demoted-from-S2 + unpinned — fell out of the shortlist; deep refresh stops, but history is kept (see below).
- Pinned + not in S2 — you care about it regardless of the screener; it keeps the full treatment until you demote it.
So: data collection is fully automatic (S1 → S2 → hidden-S3); the dropdown is 100% operator-curated and stable. The screener feeds the data; you curate the view.
Why a floating funnel beats a hard cap
A hard “top 30” cap is a crude patch — it discards the 31st name even when it is a genuine setup, and it pads the list to 30 even when only 5 names qualify. Both are lies about the state of the market. Tuning the gates instead means the board always tells the truth: it is short when opportunity is thin and longer when a real dislocation event hits multiple names at once. The operator reads the count itself as signal.
A drift alarm guards the dial: if a pass yields 0 or more than ~50 survivors, that is the gates slipping, not the market moving — it logs loudly so the thresholds get re-tuned rather than silently degrading.
Demotion keeps everything — and keeps it smart
When a name is automatically demoted from S2, nothing is ever deleted (retention is sacred — see the operations page). But we stop spending on it:
- Stop the expensive deep refresh (options chain, estimates, sentiment) and any intraday refresh.
- Keep a cheap daily price bar running — because the forward price path after demotion is the outcome label the predictive layer needs (“what happened next”).
Freezing a demoted name entirely would blind us to the very thing we’re trying to measure. The cheap-daily-bar split is the cost-vs-signal sweet spot.
Macro overlay — don’t fight the tape (context only)
Every candidate carries two macro context tags: the prevailing regime and a
sector-rotation read. The rotation tag asks one question — is the
sector-rotation tape with this name or against it? A name whose GICS sector is
being rotated into gets a tailwind; a sector being rotated out of gets a
headwind; in between reads neutral. The read is derived from the same
cyclical-vs-defensive sector-breadth rotation the macro dashboard shows, so the
screener and the dashboard agree.
This is context only — never a hard filter and never a conviction input. The
overlay does not drop a candidate or change its conviction; it surfaces the macro
weather so the operator can decide whether a setup is worth taking against the
rotation. When a sector is missing from the rotation breadth (or the macro read
is unavailable), the tag honestly abstains (—) rather than guessing a neutral.
The predictive payoff
Every screener pass writes an append-only archetype-fire event log — per
(ticker, trade_date, archetype, state, score, triggers), kept forever. Joined to
the S2 promotion / demotion timestamps and the retained forward price paths, this
becomes a labeled dataset: “names that fired this archetype combination, at this
confluence, then did X over the next N days.” That history is the raw material
for backtesting the archetypes and for the
Historical Analogs layer. We collect everything
now precisely because we cannot know today which slice will matter later.
Where pitfalls arise
- Gate drift — gates tuned too tight blank the board; too loose flood it. The drift alarm + the stale-board fallback exist for this. Re-tune by config, never by post-hoc truncation.
- Dual feature paths — the universe sweep and the per-name deep path must compute the SAME features, or a name scores differently depending on how it was evaluated. This drift has shipped 0-candidate bugs before; both paths are parity-tested.
- Sparse options legs — the options-based archetype legs (A3 / A4 / A6) only have data for scaffolded names, so for most of S1 they abstain. That is intentional; a name isn’t penalized for lacking an options row.
- Confusing visibility with data — demoting from the dropdown is NOT deleting data; auto-demotion from S2 is NOT removing the name from history. The two axes are independent.
Related
- Screener Pipeline & Lifecycle (operations) — the mechanics behind this vision.
- Archetypes — the long (A*) and short (N*) dislocation patterns the gates run.
- Historical Analogs / hybrid matcher — where the kept event history pays off.
- The live board: /screener.