Buy-the-Dip Scanner

Last run: 2026-05-27 21:30 UTC · 9 tickers · 0 WATCH · 0 CONSIDER

A daily research scan of a small watchlist. Flags mean-reversion setups — names that have pulled back into a dip pattern — and confirms or rejects them with FinBERT sentiment on the last 5 days of headlines. Reruns every weekday at 17:30 ET after US close.

How to read the table

WATCH — dip rule fires: close < SMA50×0.95 and RSI < 35 and 20d drawdown > 5%.
CONSIDER — WATCH plus sentiment confirms: mean sentiment < −0.3 across ≥3 confident headlines.
— quiet, no dip today. Most days look like this. That's the expected state.

What to do when something fires
TickerCloseRSI(14)20d DD SMA50 gapHeadlinesSentimentSignal
AAPL $310.85 79.1 0.0% 14.0% 177 / 205 -0.03
MSFT $412.67 50.1 -2.6% 3.1% 200 / 244 -0.01
NVDA $212.60 51.0 -9.8% 7.3% 218 / 248 0.04
GOOGL $388.83 61.0 -3.4% 12.9% 208 / 249 0.02
AMZN $271.85 62.7 -1.1% 11.3% 213 / 245 0.05
META $635.26 56.9 -5.1% 2.8% 189 / 224 -0.05
TSLA $440.36 63.0 -1.1% 12.9% 179 / 208 0.07
SPY $750.46 71.2 -0.0% 7.2% 194 / 224 0.03
QQQ $729.45 74.6 -0.1% 12.7% 81 / 91 0.03

Reference — what makes a number good or bad

Mindset: why "bad-looking" is good (and the trap that lives inside that)

This is a contrarian filter. Numbers that look ugly on a normal stock screen are exactly what we want to find — oversold RSI, deep drawdown, broken trend, negative news flow. The thesis: when those four red flags align on a fundamentally sound stock, the market is being too emotional and reversion is likely.

The trap: bad-looking is good only when the dip is temporary. When fundamentals genuinely broke, the same bad-looking numbers mean "catch a falling knife." The dashboard cannot distinguish these — that's why a CONSIDER is a prompt for due diligence, not a buy trigger.

The deeper the numbers go past my thresholds, the more carefully you need to verify why before acting. The rule is calibrated for noise-driven dips in mostly-healthy megacaps; pathological situations land in the same bucket but mean the opposite thing.
RSI(14) — momentum oscillator (0–100)

The 14-day Relative Strength Index measures the speed and magnitude of recent price changes. Computed using Wilder's smoothing of up-day gains vs down-day losses over the trailing 14 trading days.

RangeWhat it meansDip-buy view
70+Overbought, ran too far too fast❌ No dip here
50–70Normal uptrend, mild pullback🟡 Nothing yet
35–50Weakening🟡 Watch but not signal
< 35Oversold — my threshold✅ Contributes to dip signal
< 20Extreme oversold / capitulation🟢 Strongest or big trouble

Limitation: RSI can stay below 30 for weeks in a real bear move. "Oversold" doesn't mean "guaranteed to bounce." Combine with the other columns.

20d DD — drawdown from 20-day high (the dip itself)

Measures how far the current close is below the highest closing price of the last 20 trading days (about one trading month). Always ≤ 0% by construction.

DD = (Close / max(Close over last 20 trading days) − 1) × 100

Why it matters: direct measure of "how much has this stock fallen from its recent peak" — the literal definition of the dip you'd be buying. Trend-agnostic: works in uptrends and downtrends alike.

RangeEyeball as
0 to −2%At recent highs — no pullback
−2 to −5%Normal chop — every stock wobbles this much
−5 to −10%Real pullback — my threshold (DD > 5%) fires here
−10 to −15%Sharp correction — pain showing
Worse than −15%Crash territory — something is happening

Limitations: the 20-day window resets when a new high prints — a stock that fell 30% then bounced 20% might show only −10% DD even though it's near year-lows. DD also says nothing about why the stock fell.

SMA50 gap — close vs 50-day moving average (the trend break)

Distance between the current close and the average of the last 50 closing prices (~2.5 months of trading). Positive = above trend. Negative = below trend.

gap = (Close / SMA50 − 1) × 100

Why it matters: the 50-day moving average is the most-watched intermediate-term trend line in equity markets. Every chart, every algo references it. When a stock breaks below SMA50, trend-followers exit and "trend is broken" gets written into research notes. It's self-fulfilling — enough capital treats SMA50 as the line that it becomes the line.

For dip-buying: a stock that's just dipped (DD shows recent pain) AND broken below SMA50 (trend-followers have bailed) is in maximum forced-selling mode — exactly the irrational-pessimism state contrarians want.

GapEyeball as
> +10%Stretched — momentum chase
+5% to +10%Strong uptrend, healthy
0 to +5%At trend — normal
0 to −5%Trend wobbling but intact
< −5%Trend broken — my threshold (Close < SMA50 × 0.95) fires
Worse than −10%Major breakdown — likely something fundamentally wrong

Limitations: choppy stocks can cross SMA50 daily on noise. Threshold magnitude (−5%) suits megacap tech; would be too loose for crypto, too tight for utilities.

Sentiment — mean FinBERT score across confident headlines (−1 to +1)

FinBERT (a BERT variant fine-tuned on financial text) scores each Finnhub headline as positive / negative / neutral. We keep only headlines where FinBERT was confident (its max-class probability > 0.6) and average positive − negative across them. Range: −1 (all bearish) to +1 (all bullish).

RangeNews flow looks likeDip-buy view
+0.3 to +1.0Bullish (earnings beats, upgrades, hype)❌ Already optimistic
+0.1 to +0.3Mildly positive❌ Boring
−0.1 to +0.1Mixed / neutral — normal day🟡 Most days are here
−0.1 to −0.3Mildly negative🟡 Early concern
−0.3 to −0.6Clearly negative — "fear" cycle✅ My CONSIDER threshold
Worse than −0.6Extreme negative🟢 Capitulation or something legitimately broken

Headlines column matters: n_confident / n_total. If confident count is < 3, the sentiment number is essentially undefined and CONSIDER won't fire regardless. Healthy reading is ~85–95% confident.

Limitation: FinBERT is trained on long-form financial text (~2019). It handles headlines but misses some modern tone. A v2 Claude-Haiku swap is parked in our roadmap.

How they combine — the 2×2 dip pattern

The metrics measure different things. The rule requires both a recent drawdown AND a broken longer-term trend — and the news layer further filters from there:

                       SMA50 gap
                  Above trend       Below trend (< −5%)
                  ─────────────     ──────────────────
DD shallow      │ ❌ Strong         │ ⚠️ Slow grinder
(0 to −5%)      │   uptrend         │   No recent peak —
                │   No dip          │   stock has been
                │                   │   bleeding quietly
                │                   │   (no signal fires)
                ─────────────────────────────────────────
DD deep         │ ⚠️ Spike-and-     │ ✅ CLASSIC DIP
(< −5%)         │   revert          │   Recent sharp drop
                │   Recent sharp    │   PLUS trend broken —
                │   drop, trend     │   short-term sellers
                │   still intact    │   AND trend-followers
                │                   │   both bailing
                │   (no signal)     │
                │                   │   → WATCH or CONSIDER

Top-right (slow grinder): real decline but no "dip" to buy — nothing to revert from. Catch-a-knife territory.

Bottom-left (spike-and-revert): flash sell-off in a strong uptrend. Often mean-reverts on its own but the bigger thesis ("everyone's bailing") doesn't apply because nobody actually bailed yet.

Bottom-right: where the rule fires. Forced selling + trend-follower exits = maximum pessimism = the actual mean-reversion edge.

Layer in the sentiment column on top: if news flow is negative at the same time, the bet upgrades from WATCH to CONSIDER — meaning the pessimism has a story attached to it, which is contrarian-bullish provided the story is not real damage.

Action: what to do when a row fires

If everything is

Do nothing. Most days look like this and that's the expected state. The tool is silent until conditions align.

If a row shows WATCH

If a row shows CONSIDER

Universal rules

What this tool doesn't know about (yet)