`monster-discover` ALB coverage postmortem

Investigation

`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 ≥ $2B
  • ta_sma200_pa30 — price ≥ 30% above SMA200
  • ta_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 — keep
  • ta_sma50_pa — keep
  • ta_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 goldenCross requirement, more than the Finviz ta_sma200_pa30 filter. A monster-rotation preset 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 entered monster-discoveries.json on 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-rotation preset 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 codes ta_perf26w40o / ta_perf13w15o against Finviz's current screener vocabulary; (b) decide whether monster-rotation results land in monster-discoveries.json or a separate monster-rotation-discoveries.json watchlist (separate avoids muddying the algorithmic-monster-pass population with rotation hits).

  • Not a monster-discover defect: 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.jsonALB price history (1683 rows, 1994-02-21 → 2026-05-18; SMA/return computations local).
  • stonks/watchlists/monster-discoveries.jsonALB present; added 2026-03-26 via fb45e79ab8 full-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.json files; 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.

8 events

No direct external sources are attached to this read.