From 9113d8ea4cd54bae96533d5da25dad9d6ea3ddf6 Mon Sep 17 00:00:00 2001 From: momentum dev Date: Tue, 16 Jun 2026 12:58:07 -0400 Subject: [PATCH] Fix screener returning empty all session (top>100) + add momentum launcher - discover_active_symbols requested get_most_actives(top*3); once screen_universe used top*2 headroom for the ETF filter (top=20 -> 40 -> get_most_actives(120)), this exceeded Alpaca's hard cap of 100 -> HTTP 400, swallowed by the bare except -> discovery returned EMPTY every cycle. The live loop therefore traded the static fallback list (non-gappers) instead of real movers all morning. Fix: cap at min(top*3, 100). Verified: screen_universe now returns 20 real sub-$20 names, ETF-filtered. - Add ./momentum launcher (project venv) so 'momentum watch' works without the full venv path ('python' on the box is the Windows pyenv shim, no deps). 67/67 tests green. Co-Authored-By: Claude Opus 4.8 --- momentum | 14 ++++++++++++++ research/ingestion/market_data.py | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 momentum diff --git a/momentum b/momentum new file mode 100644 index 0000000..2923f92 --- /dev/null +++ b/momentum @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# momentum — run the inspection/monitoring CLI with the project's venv. +# Usage: ./momentum watch | doctor | inspect signals | inspect criteria SYM | ... +ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +VENV_PY="/home/philip/.venvs/momentum/bin/python" +if [ ! -x "$VENV_PY" ]; then + echo "venv python not found at $VENV_PY" >&2 + echo "create it:" >&2 + echo " uv venv \"\$HOME/.venvs/momentum\" --python 3.13" >&2 + echo " uv pip install --python \"\$HOME/.venvs/momentum\" psycopg2-binary pandas pydantic pydantic-settings pyyaml typer rich numpy python-dotenv" >&2 + exit 1 +fi +cd "$ROOT" +exec "$VENV_PY" momentum_cli.py "$@" diff --git a/research/ingestion/market_data.py b/research/ingestion/market_data.py index 9884dd2..72ca1fb 100644 --- a/research/ingestion/market_data.py +++ b/research/ingestion/market_data.py @@ -234,7 +234,8 @@ def discover_active_symbols( static symbol list. """ try: - actives = client.get_most_actives(top=top * 3, by="volume") + # Alpaca caps the most-actives `top` at 100; never request more. + actives = client.get_most_actives(top=min(top * 3, 100), by="volume") symbols = [a["symbol"] for a in actives if a.get("symbol")] if not symbols: return []