Discovery: merge %-gainer movers (the wildcards volume-ranking can't see)
Forensic from the source trader's 2026-07-02 recap: his ENTIRE day (+$8.9k) was CX — a thin reverse-split name that squeezed $3->$6 on a headline (his "wildcard effect": on dead pre-holiday days the one mover gets everyone's attention). Our system NEVER SAW IT: zero bars, zero discovery events. Root cause: discovery ranks by ABSOLUTE SHARE VOLUME (most-actives), and a thin %-squeezer never cracks a volume-ranked top-N. Every other name he called out we saw and judged the same way he did (DSY passed/backed-out, CWD too cheap, AHMA rejected) — the gap was pure discovery scope. - alpaca_paper/client.py: get_movers(top) — /v1beta1/screener/stocks/movers top %-gainers (verified working with our keys: CLRO +114%, CWD +73% live). - discover_active_symbols: wildcard gainers are fetched FIRST (warrants/units filtered: '.'-suffixed + 5-char W-endings), deduped with most-actives, same price-band filter. Additive + fail-open: a movers failure never breaks the existing actives path. Discovery/ingestion scope ONLY — every trading gate (confirmation window, quality, VWAP, cap) still applies unchanged. The immediate value is that shadow tracks + the labeler finally get BARS for wildcard movers, so the next CX is measurable instead of invisible. Verified live: universe now leads with gainer-sourced names (CLRO, CWD, USDE, YRD, DSY). 16 tests pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
6c36d04f7a
commit
4fc02a8c71
3 files changed
+185
-1
No files matched your search
@@ -361,6 +361,19 @@ class AlpacaPaperClient:
|
||||
)
|
||||
return payload.get("most_actives") or []
|
||||
|
||||
def get_movers(self, top: int = 15) -> list[dict]:
|
||||
"""Top %-change gainers (the 'wildcard' movers). Ranked by PERCENT change, not
|
||||
share volume — a thin reverse-split name squeezing on a headline (CX on
|
||||
2026-07-02: $3->$6, the source trader's whole day, invisible to
|
||||
most-actives-by-volume) shows up here and nowhere else.
|
||||
Items: {symbol, percent_change, change, price}."""
|
||||
payload = self._data(
|
||||
"GET",
|
||||
"/v1beta1/screener/stocks/movers",
|
||||
params={"top": top},
|
||||
)
|
||||
return payload.get("gainers") or []
|
||||
|
||||
def get_news(
|
||||
self,
|
||||
symbols: list[str] | None = None,
|
||||
|
||||
Reference in new issue
Block a user