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.
| Range | What it means | Dip-buy view |
| 70+ | Overbought, ran too far too fast | ❌ No dip here |
| 50–70 | Normal uptrend, mild pullback | 🟡 Nothing yet |
| 35–50 | Weakening | 🟡 Watch but not signal |
| < 35 | Oversold — my threshold | ✅ Contributes to dip signal |
| < 20 | Extreme 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.
| Range | Eyeball 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.
| Gap | Eyeball 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).
| Range | News flow looks like | Dip-buy view |
| +0.3 to +1.0 | Bullish (earnings beats, upgrades, hype) | ❌ Already optimistic |
| +0.1 to +0.3 | Mildly positive | ❌ Boring |
| −0.1 to +0.1 | Mixed / neutral — normal day | 🟡 Most days are here |
| −0.1 to −0.3 | Mildly negative | 🟡 Early concern |
| −0.3 to −0.6 | Clearly negative — "fear" cycle | ✅ My CONSIDER threshold |
| Worse than −0.6 | Extreme 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
- Open the chart (TradingView, Yahoo, whatever). Confirm the dip visually — does it look like a normal pullback in a healthy stock, or the start of a broader breakdown?
- Check the earnings calendar. A dip 2 days before earnings is mostly volatility theater, not a buying opportunity.
- Ask yourself: "would I buy this dip if I had no rule and just saw it on the chart?" If the honest answer is no, the rule is just pattern-matching noise.
- A WATCH is a prompt for due diligence, not a buy trigger.
If a row shows CONSIDER
- All the WATCH checks plus: read the actual headlines the sentiment is reacting to. Click through to Finnhub or Google News.
- Categorize the news: irrational fear (downgrade noise, sector-wide rumor, macro panic) vs real damage (missed guidance, fraud disclosure, key person leaves).
- Contrarian opportunity exists in the first category. The second category is the falling knife.
- You'll also get a Slack alert in #test-channel when a ticker first flips to CONSIDER. No re-alerts while it sits there.
Universal rules
- Don't trust one day. Let the signal persist into the next session before sizing anything. Real setups don't disappear overnight.
- Position sizing, stops, holding period are entirely your call. The tool surfaces candidates; it doesn't decide trades.
- Backtest tells us productive holding windows are ~5 days (bounce capture) or ~60 days (full mean reversion). The 20-day in-between zone has no edge — useful for stop placement decisions.
What this tool doesn't know about (yet)
- Market regime. Buy-the-dip works in bull/recovery markets and dies in trending bears. In May 2022 these same numbers would have meant something very different. Planned: SPY 200-day trend gate.
- Earnings proximity. A dip the day before earnings is mostly volatility, not opportunity. Planned: suppress signals in the ±3 day earnings window.
- Volume. A dip on falling volume = quiet selling, weak signal. A dip on 1.5× average volume = capitulation, stronger signal. Currently ignored. Planned: volume confirmation flag.
- Your portfolio. The tool doesn't know if you're already long the name, already capped on sector exposure, or in a position-sizing-aware framework. Treat its output as an idea list, not a trade list.