`monster-discover` ALB coverage postmortem
`monster-discover` ALB coverage postmortem
Question: Why did monster-discover never produce $ALB during its 2025-Q4 / 2026-Q1 run from $57 → $204 (3.6× in 12 months at $24B mcap)?
Verdict: The local validator gate (goldenCross + strong-up + vsSma200 ≥ 30) is the structural killer for deep-bottomed rotation names. ALB has never passed in 2026 — not because the move was small, but because a 2024 collapse from $170 → $59 baked a tall SMA200 that SMA50 hasn't caught yet. A proposed monster-rotation preset variant catches the pattern empirically (ALB: 7 hit-days in 2026 starting 2026-03-23) without false-positives on broken names (FMC, RIVN, LCID, NIO: 0 hits). Preset proposed; implementation deferred as a narrow follow-up.
What we're asking
The 2026-05-10 lithium-breakout thread surfaced that monster-discover never caught $ALB despite a textbook 3.6× run. The working hypothesis in TASKS-RESEARCH.md:115 was: "monster-discover preset is mid-cap+ above SMA200, and ALB likely failed the SMA200 filter for most of 2025 because it was bottoming."
This investigation tests the hypothesis empirically against $ALB's full price history, decomposes the filter into Finviz-pre-filter vs local-validator gates, identifies which gate is actually responsible, and proposes a concrete monster-rotation preset variant calibrated against a peer basket.
What we found
1 — Filter anatomy
monster-discover is two stages stacked:
Finviz pre-filter (stonks/python/src/discover.py:50):
cap_midover— market cap ≥ $2Bta_sma200_pa30— price ≥ 30% above SMA200ta_sma50_pa— price above SMA50
Local validator (stonks/cli/chart/monster-discover.ts:244):
trend === "strong-up"(price > SMA50 AND SMA50 > SMA200)goldenCross === true(SMA50 > SMA200)vsSma200 ≥ 30
Combined the filter demands an already-confirmed uptrend: price 30%+ above the 200-day mean and both moving averages stacked bullishly. By construction this misses everything in the "rotation-back-up" / "death-cross-not-yet-unwound" window.
2 — Empirical: $ALB never passed in 2026
Monthly snapshots through the run (closes from stonks/data/stocks/ALB/ohlc/max.json, computed locally):
| Date | Close | SMA50 | SMA200 | vs SMA200 | vs SMA50 | Golden cross | Monster pass |
|---|---|---|---|---|---|---|---|
| 2025-04-30 | $59.26 | $86.74 | $170.01 | -65.1% | -31.7% | no | fail |
| 2025-07-31 | $67.16 | $78.40 | $160.80 | -58.2% | -14.3% | no | fail |
| 2025-10-31 | $97.69 | $76.97 | $151.11 | -35.3% | +26.9% | no | fail |
| 2026-01-31 | $170.21 | $90.23 | $147.37 | +15.5% | +88.6% | no | fail |
| 2026-02-27 | $178.23 | $97.69 | $146.87 | +21.3% | +82.4% | no | fail |
| 2026-03-31 | $178.09 | $108.13 | $145.21 | +22.6% | +64.7% | no | fail |
| 2026-04-30 | $193.88 | $118.56 | $144.79 | +33.9% | +63.5% | no | fail |
| 2026-05-22 | $171.58 | $126.26 | $144.58 | +18.7% | +35.9% | no | fail |
Daily scan over all of 2026: 0 monster-pass days.
Two findings here:
(a) The original hypothesis ("ALB failed the SMA200 filter") is half right. ALB was below SMA200 from collapse through Jan 2026 (8+ months) — the Finviz ta_sma200_pa30 filter would have rejected it everywhere except a brief late-April window when ALB briefly hit +33.9% above SMA200.
(b) The bigger gate now is goldenCross. Even at the late-April peak when Finviz would have surfaced $ALB, the local validator would have rejected it because SMA50 ($118.56) was still 12% below SMA200 ($144.79). The 2024 collapse from $170 → $59 left the SMA200 elevated by a long tail of high prices; SMA50 needs another ~60 trading days at current price to cross. $ALB has not been in a golden-cross state at any point during the 2025-Q4 → 2026-Q1 run.
3 — Watchlist evidence
$ALB is present in stonks/watchlists/monster-discoveries.json, added in commit fb45e79ab8 (2026-03-26 full scan) — but is not in the saved research/scans/2026-03-31-monster-discover-archive.md new-discovery list (COGT, NKTR, KYMR, NXT, ENS, AGRO, CE, GSAT, GRDN, NOK). The watchlist add was likely a manual or skill-driven inclusion during the full-scan reconcile step, not the algorithmic monster-discover filter producing a hit. The algorithmic filter never produced ALB.
4 — Did the filter at least catch peer commodity-cycle names?
Spot check (today, computed locally):
| Ticker | 1y return | vs SMA200 | Golden cross | Monster pass |
|---|---|---|---|---|
| $CF | +186% | +47% | yes | PASS |
| $FCX | +74% | +49% | yes | PASS |
| $SQM | +108% | +42% | yes | PASS |
| $URNM | +130% | +36% | yes | PASS |
| $LIT | +6% | +59% | yes | PASS |
| $AA | +87% | +86% | yes | PASS |
| $AEM | +206% | +96% | yes | PASS |
| $ALB | (per-table above) | +19% | no | fail |
| $MOS | -19% | -30% | no | fail (correctly — didn't run) |
| $FMC | -86% | -78% | no | fail (correctly — still falling) |
So the filter catches most materials/commodity-cycle runners. $ALB's specific failure is the depth of the prior 2022-2024 collapse — a deeper fraction below SMA200 than peers, so the SMA50 catch-up takes longer.
5 — Proposed monster-rotation preset
A second preset alongside monster-mid / monster-large / monster-parabolic, calibrated for "deep-bottomed rotation names where SMA50 hasn't yet crossed SMA200":
Local validator (monster-rotation):
- price > SMA50 (early uptrend confirmed)
- SMA50 < SMA200 (death cross still unwinding — explicitly NOT golden cross)
- 6-month return ≥ 40%
- 3-month return ≥ 15%
Finviz pre-filter (proposed):
cap_midover— keepta_sma50_pa— keepta_perf26w40o— 6-month performance ≥ 40% (Finviz syntax; verify exact code)ta_perf13w15o— 3-month performance ≥ 15% (Finviz syntax; verify exact code)- Drop
ta_sma200_pa30— the whole point is to catch names below SMA200
6 — Empirical validation of the proposed preset
Daily back-scan over 2026 against a 25-name basket (materials, semis, EV, consumer, big-tech):
| Ticker | slow-cycle hit days in 2026 | First hit | Last hit | True/false positive |
|---|---|---|---|---|
| $ALB | 7 | 2026-03-23 | 2026-05-04 | TRUE positive (the target case) |
| $SQM | 8 | 2026-02-23 | 2026-04-20 | true positive (lithium peer) |
| $LIT | 2 | 2026-02-23 | 2026-03-09 | true positive (lithium ETF) |
| $AA | 7 | 2026-01-05 | 2026-02-16 | true positive (aluminum) |
| $INTC | 2 | 2026-01-05 | 2026-01-12 | true positive (semis rotation) |
| $FMC | 0 | — | — | true negative (still falling) |
| $AMD | 0 | — | — | true negative (already passes monster) |
| $RIVN, $LCID, $NIO | 0 | — | — | true negative (broken EV) |
| $NVDA, $AAPL, $META, $PLTR, $RKLB | 0 | — | — | true negative (no recent death cross) |
| $BA, $GE, $DIS, $SBUX, $NKE, $LULU, $TGT, $WMT | 0 | — | — | true negative (not in deep-rotation pattern) |
Filter cleanly distinguishes the target pattern. Sample size is small but the shape is informative — slow-cycle hits land on materials/commodity cycle names that were below SMA200 and recovering, and skip both broken names and names already inside the standard monster-mid window.
7 — Sector-specific monster variant
The task asked: "consider adding a sector-specific monster-discover for materials/commodities cycles." Recommendation: defer. The proposed monster-rotation preset is already sector-agnostic and catches the materials/commodities-cycle shape via behavior (not via Finviz sec_basicmaterials flag). A sector-specific variant would add noise without solving a different problem. If the rotation preset under-covers a specific cycle (e.g., copper-grid build-out, where mid-caps may be smaller than cap_midover), revisit then.
Verdict + reasoning
Verdict: The hypothesis is confirmed and refined. The structural gating issue is the local-validator
goldenCrossrequirement, more than the Finvizta_sma200_pa30filter. Amonster-rotationpreset with explicit non-golden-cross gating, calibrated by 6m/3m return thresholds, recovers $ALB across a 6-week window (first hit 2026-03-23, well ahead of when $ALB enteredmonster-discoveries.jsonon 2026-03-26).Pattern to expect: Deep-bottomed commodity-cycle names (resource-cycle dynamics, prior drawdown > 60%, multi-quarter basing) will systematically miss
monster-discover. Sectors most at risk: lithium, fertilizer, specialty chemicals, deep-cyclical industrial metals, semi-equipment after a cycle bottom, biotech after a multi-year flat range.Implementation deferred: Producer-only investigation; the actual
monster-rotationpreset wiring (Finviz syntax verification, validator code, archive output, watchlist auto-add path) is a code change filed below as a narrow follow-up. Two open items: (a) confirm exact Finviz codesta_perf26w40o/ta_perf13w15oagainst Finviz's current screener vocabulary; (b) decide whethermonster-rotationresults land inmonster-discoveries.jsonor a separatemonster-rotation-discoveries.jsonwatchlist (separate avoids muddying the algorithmic-monster-pass population with rotation hits).Not a
monster-discoverdefect: The filter as designed is doing what it advertises — finding stocks in confirmed uptrends. Adding the rotation preset is feature work, not a bug fix. The bug-like gap is that we lacked a complementary preset for the obvious adjacent shape; that gap is now named.
Sources
stonks/cli/chart/monster-discover.ts:244— local validator gate that ALB fails.stonks/python/src/discover.py:50— Finviz preset filter definitions.stonks/data/stocks/ALB/ohlc/max.json— ALB price history (1683 rows, 1994-02-21 → 2026-05-18; SMA/return computations local).stonks/watchlists/monster-discoveries.json— ALB present; added 2026-03-26 viafb45e79ab8full-scan commit.research/scans/2026-03-31-monster-discover-archive.md— the only saved monster-discover output; confirms ALB was not in the algorithmic new-discoveries list (10 names: COGT, NKTR, KYMR, NXT, ENS, AGRO, CE, GSAT, GRDN, NOK).TASKS-RESEARCH.md:115— source row that surfaced this gap from the 2026-05-10 lithium-breakout thread.- Peer basket spot-checks (25 tickers) — computed locally from
stonks/data/stocks/<TICKER>/ohlc/max.jsonfiles; data as of 2026-05-18 close (last row in each file).
Carrier notes
Price/SMA computations use cached OHLC through 2026-05-18 (last row in max.json files). No fresh fetch — this is a methodology investigation against historical state, not a current-tape read. The 2026-05-22 row in the monthly snapshot is from interpolating SMA at that index against the data; it's representative not authoritative.
Related
8 eventsNo direct external sources are attached to this read.