Skip to content
investiDocs

Candidate sources

Where new candidates come from (near low, big drop, Strict 1, uploaded screener exports), the exact Strict 1 filters, and what "new" means.

On this page

Investi keeps finding names worth a first look, and above all tells you which ones are new. A candidate can come from four places. Each source records the day it first saw a name, per account, so a name you saw last month and already evaluated does not show up as new again because a different screen found it. Everything here is research: no source places, changes or suggests an order.

The candidates appear at the top of Discover, on Home as a count, at GET /api/v1/candidates (REST API) and in the get_new_candidates tool (Claude (MCP)).

The four sources#

Source A name enters when Refreshed
Near low It is within your near-low distance of its 52-week low (10% by default, the same as a Schwab "Near Price Lows" screen set to 10%). When a Discover scan finishes, and after each close.
Big drop It fell at least your big-drop threshold in one session (10% by default), its market cap is at or above your floor ($2B by default), and it clears the quality gate below. Every 15 minutes in the session and once after the close.
Strict It passes all eleven filters of the Strict 1 screen below. After each close, for names within 10% of their 52-week low with a market cap of $2B or more.
Uploaded It is a row in a screener export you uploaded: Schwab Stock Screener or Finviz. When you upload.

The near-low distance, the big-drop threshold and floor, and the "new" window are in Settings.

Near low#

Near low reuses the Discover scan: the same universe (US common stocks and ADRs above your screener market-cap floor, priced $5 or more) and the same 52-week math (regular-session daily bars, the trailing 365 days). Discover's table can still show names out to 25% from the low; only names within your near-low distance become candidates.

Big drop#

The drop is measured over N sessions (Settings, Candidates: big drop over (sessions), 1 by default). For one session the change comes from the same-session snapshot the Markets movers use, which covers every US common stock of $2B or more. For more than one session it is computed from the daily closes Investi stores: the close N sessions back against the latest close (or against the same-session price, when it is newer than the last stored bar).

When the change feed fails (Nasdaq answered "Error while calling vendor", or too few rows came back), the failure is recorded with its time and reason, the one-day change is computed from the last two stored daily closes instead, and Discover's Big drop button says fallback with the reason. Names without stored bars cannot be judged on that pass, and the note says how many names were covered. The quality gate reads SEC XBRL filings and has exactly these checks, all of which must pass:

Check Passes when
Change Down your threshold or more over your N sessions (10% over 1 session by default).
Market cap At or above your floor ($2B by default).
TTM net income Positive over the trailing twelve months.
TTM operating margin Operating income over revenue is positive over the trailing twelve months.

A fact that is missing from the filings is unknown, and an unknown check does not pass. Banks, insurers and some industrials (Nike, for one) do not tag operating income, so they do not qualify as big drops. The checks and their values are stored with the sighting and shown in Discover. Drops the gate held back are listed above the New entrants table with the first check they missed, for example "NKE -11.0% (operating margin unknown)".

Strict 1#

Strict 1 is a Finviz screen reproduced inside Investi. Investi does not read finviz.com; it computes each filter from SEC XBRL company facts and Nasdaq daily bars. The Finviz URL it mirrors is cap_midover, fa_debteq_u0.5, fa_epsyoy_pos, fa_grossmargin_o50, fa_netmargin_pos, fa_opermargin_o15, fa_roe_o15, fa_sales5years_o5, sh_avgvol_o500, ta_highlow52w_a0to10h, ta_sma200_pb.

# Filter Investi computes
1 Market cap $2B or more Nasdaq listing market cap.
2 Debt/equity under 0.5 Total debt (long-term debt including the current portion, plus short-term borrowings) over stockholders' equity, latest balance sheet. Negative equity fails.
3 EPS growth this year positive Latest reported fiscal-year diluted EPS against the fiscal year before: (this year minus last year) over the absolute value of last year. Reported, not estimates; a shrinking loss counts as growth (the checklist row says so on hover).
4 Gross margin over 50% Trailing-twelve-month gross profit over revenue.
5 Net margin positive Trailing-twelve-month net income over revenue.
6 Operating margin over 15% Trailing-twelve-month operating income over revenue.
7 ROE over 15% Trailing-twelve-month net income over the latest stockholders' equity. Negative equity fails.
8 Sales growth past 5 years over 5% Annualized revenue growth from the fiscal year about five years before the latest one.
9 Average volume over 500K Mean shares traded per session over the last 63 sessions (about three months).
10 0 to 10% above the 52-week low Last close against the lowest low of the trailing 365 days.
11 Price below the 200-day SMA Last close against the mean of the last 200 closes.

Every filter is reported separately as Pass, Fail or Unknown, with the measured value and where it came from. Unknown means the fact is not in the filing data (for example a bank has no gross profit concept, or a filer stopped tagging long-term debt); it never counts as a pass. A name is a Strict candidate only when all eleven pass.

Where Investi's numbers can differ from Finviz's:

  • EPS growth this year. Finviz can blend analyst estimates for the current fiscal year. Investi uses reported diluted EPS only, so it compares the last two reported fiscal years.
  • ROE. Investi divides by the latest equity, not an average over the year.
  • Debt. A filer whose latest balance sheet has no long-term debt concept, although it tagged debt in the past, reads Unknown rather than a falsely low ratio.
  • Foreign filers that report under IFRS use different concept names; most of their fundamental filters read Unknown.

Strict 1 runs on the near-low pool because filter 10 already requires a price within 10% of the low; no name outside that pool could pass.

Uploaded screener exports#

Upload a CSV with POST /api/v1/screens/import (a multipart file field or the CSV as the request body). Investi detects the export from its header row:

Export Recognized by Stored as
Finviz No., Ticker and Company columns upload:finviz
Schwab Stock Screener a Symbol column upload:schwab_screener
Anything else with a Ticker column Ticker upload:other

Title lines above the header and disclaimer lines below the last row are skipped, BRK/B becomes BRK.B, and a duplicate ticker in one file is kept once. Each row keeps its original cells. A name from an upload is new only if no source has seen it within your window and it has not been evaluated under your current rules, so uploading today's Schwab export shows exactly the names that are new to you.

What "new" means#

A name is new when either is true:

  • it was first seen, by any source, within your window (7 days by default), or
  • it has never been evaluated under your current policy record (the same test as the NEW and policy-CHANGED candidate states).

Three exceptions:

  • A name you own is listed, tagged Owned, but never counted as new.
  • A name you dismiss stays hidden. Investi remembers the lower of its last price and its 52-week low at that moment; if the name later trades below that price (a new low), it comes back, tagged Back, and counts as new again.
  • A name seen in two sources is one row with both sources. Its first-seen date is the earliest of them.

Home counts the new names first seen since your last visit to Discover. A visit within 30 minutes of the previous one continues it.

Analysis#

New entrants get a verdict automatically. After each scan and after each close, the Discover analysis queue evaluates new entrants from every source that have no evaluation under your current rules, before its usual near-gate names. It uses the deterministic rules only, so it costs nothing. A name the queue cannot analyze (an upload with a symbol Investi does not recognize) is skipped for a day instead of blocking the queue. The Analyze button on a row evaluates one name right away.

Schedule#

A scheduled job (/api/cron/candidates, every 15 minutes on weekdays from 13:00 to 23:45 UTC) does the work:

  • In the session it records big drops when the set of falling names has changed since its last pass. An unchanged set ends the run without touching the database.
  • Every pass writes a status note: when big drops last ran, where the change came from (the feed, or stored closes and why), how many names were down enough and how many passed the gate, the field values the gate saw for the first ten names (change, window, market cap, TTM net income, operating margin), and how many near-low names Strict 1 checked and how many pass. Discover reads this note for its source buttons, so a source that has not run yet says not run instead of 0. A fresh deployment shows not run until the first weekday pass (9:00 AM ET).
  • From 16:30 New York it records the closing big drops, starts the day's Discover scan for each account that uses Discover (the screener job finishes it), recomputes Strict 1, records near-low and strict sightings, and runs the analysis queue. Once the day's work is done, later runs end without touching the database until the next session. On a market holiday nothing is rescanned.