Commit Graph
13 Commits
Author SHA1 Message Date
momentum devandClaude Opus 4.8 9113d8ea4c 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 <noreply@anthropic.com>
2026-06-16 12:58:07 -04:00
momentum devandClaude Opus 4.8 020eec7f96 WS5 Grafana dashboards + RSS news-catalyst discovery
- grafana/: docker-compose + provisioned Postgres datasource + 'Momentum — Live'
  dashboard (evaluation board with status colours, ready signals, risk events,
  bars + equity timeseries) reading the event store via JSONB extraction.
  Run: cd grafana && docker compose up -d -> http://localhost:3000.
- RSS news-catalyst discovery wired: extract_tickers also matches $CASHTAGS;
  run_discovery pulls tickers from recent news into the universe when NEWS_FEEDS
  is set (no-op / safe otherwise).
- docs: .env.example NEWS_FEEDS; GO_LIVE monitoring adds 'momentum watch' + Grafana.

67/67 tests green. Live board (momentum watch) verified rendering the evaluation
board with real determinations.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 09:00:22 -04:00
momentum devandClaude Opus 4.8 11f1dd8b15 Live monitoring board: momentum watch
Full-screen auto-refreshing board (rich.Live) of what the system is evaluating
in real time: per-symbol status (ready/late/blocked), score, gap%, RVOL and the
blocking reason, ranked by score — plus ready signals, open positions, and risk
events. 'momentum watch' (refresh) or '--once' (single frame). Reads the
Postgres event store.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 08:54:09 -04:00
momentum devandClaude Opus 4.8 6c339121f0 Circuit breaker: auto-flatten on breach
When the daily-loss breaker trips it now also flattens the book: cancels
unfilled (armed) entries and market-closes every open position via
client.close_position (which cancels resting bracket legs). Configurable via
TRADING_FLATTEN_ON_BREACH (default on). Best-effort per symbol; emits a
'halted_and_flattened' risk_rule_triggered event with the flatten summary.

Verified: trip at -4% closes 2 seeded positions + cancels 1 armed entry. 67/67 green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 08:20:57 -04:00
momentum devandClaude Opus 4.8 37c6131b8e GO_LIVE.md: trading enabled (auto-approve + circuit breaker + ETF filter)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 08:03:56 -04:00
momentum devandClaude Opus 4.8 a0276958ca Trading enablement: circuit breaker, ETF filter, robust discovery
- trading_execution: implement the daily-loss circuit breaker (account equity vs
  prior close; latches once tripped; fail-open on a data hiccup) — was
  advertised in the docstring/settings but never implemented.
- discovery: filter leveraged ETFs (SOXS/TZA/TSLL/NVD/BITO/...) out of the
  universe; retry the screener on a transient empty (rate-limit) result.
- run_live_paper: fallback watchlist is now liquid sub-$20 names, not mega-caps
  (mega-caps just get filtered by the watcher band -> nothing to trade).

Verified live: forced ready signal -> auto-approve -> real Alpaca bracket order
(pending_new, then cancelled); breaker trips at -3% (simulated). 67/67 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 08:02:46 -04:00
momentum devandClaude Opus 4.8 d5d50a5e4f GO_LIVE.md runbook + verified continuous loop for market open
Market-open runbook: start command (observe mode), the 9:30-10:35 ET trading
window (10:30 entry cutoff), monitoring commands (doctor / inspect signals /
criteria / bars), how to enable paper execution, env tuning, honest known limits.

Verified this session: continuous loop stable with graceful Ctrl-C; full
pipeline (discover -> ingest -> evaluate) produces ready signals on real
2026-06-15 morning data; 67/67 tests green throughout.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 07:28:17 -04:00
momentum devandClaude Opus 4.8 a16a8cd29d WS3: surface evaluation internals (gap/rvol/per-criterion reasons)
- SetupEvaluationResult.criteria_detail: per-criterion {name,passed,reason}.
- watcher CriteriaEvaluatedEvent now carries gap_pct, relative_volume, status,
  reason, and the per-criterion detail (was only passed/failed names).
- CLI: 'inspect criteria SYMBOL' shows status + gap/rvol + each criterion reason;
  new 'inspect signals' = ready board + per-symbol gap/rvol/status.

Verified on real 2026-06-15 bars: RGNT shows 9/9 with reasons (rvol 26.2x),
'late' explained by the 10:30 ET cutoff. 67/67 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 07:22:55 -04:00
momentum devandClaude Opus 4.8 9e79c50751 WS2: momentum inspect/doctor CLI (per-section verification)
momentum_cli.py (typer + rich):
- doctor: PASS/WARN/FAIL across db / schema / research / ingestion / discovery /
  event_store, with honest known-gap WARNs (circuit breaker not implemented,
  quality_score hardcoded, ETF universe).
- inspect events / bars / discovery / criteria: read the Postgres event store +
  bar tables. 'inspect bars' shows per-symbol counts + freshness and flags
  0-bar (market-closed/thin) vs broken.

Verified against live Postgres: 6 pass / 4 warn / 0 fail.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 00:38:17 -04:00
momentum devandClaude Opus 4.8 1443e7691a Discovery-by-default + WS1 bars/discovery telemetry
- research/ingestion/discovery.py: screen sub-$20 most-actives, backfill daily,
  rank gappers, persist scanner snapshot, and EMIT a discovery event.
- run_live_paper: watchlist defaults to the screener universe (was a hardcoded
  mega-cap list); add a periodic 'discover' task; emit bars-collected
  (per-symbol counts) and discovery events every pass.
- IngestionResult.per_symbol: per-symbol row counts (incl 0) so 'are bars
  collected?' is answerable per symbol, distinguishing market-closed from broken.

Verified live vs Postgres: watches SOXS/RGNT/GRAB/SOFI/ACHR/... (sub-$20),
820 daily bars backfilled, discovery+ingestion events land in the event store.
67/67 tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 00:35:52 -04:00
momentum devandClaude Opus 4.8 b1ef0930ca WS0 cleanup: DuckDB-free + wire DATABASE_URL
- Drop duckdb dependency (pyproject, requirements) -> psycopg2-binary.
- run_live_paper: boot log shows the real Postgres target (masked); add
  _db_target_desc() helper.
- .env.example: document DATABASE_URL / PG* vars; mark WATCHER_EVENT_DB_PATH legacy.
- evaluation/storage.py: INSERT OR REPLACE -> INSERT (setup_id is a fresh uuid).

Verified: 67/67 tests green on Postgres with duckdb UNINSTALLED; app boots
against the live endpoint (127.0.0.1:5432 proxy) and wrote 205 daily bars.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-16 00:15:19 -04:00
momentum devandClaude Opus 4.8 c4669fe0ce WS0: migrate datastore DuckDB -> PostgreSQL (psycopg2)
- storage/db_pg.py: thin psycopg2 connection shim (?->%s translation,
  autocommit, .df(), and per-test isolated schema for ':memory:').
- storage/db.py: delegate get_connection/get_memory_connection to db_pg.
- storage/pg_schema.sql: Postgres schema, applied on connect.
- research/query.py runs UNMODIFIED on Postgres via the shim.
- ingestion upserts: INSERT OR REPLACE -> INSERT ... ON CONFLICT DO UPDATE.
- event_store: drop invalid btree-on-JSON-text index.

Full logic suite: 67/67 green against Postgres (was DuckDB).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:48:35 -04:00
momentum devandClaude Opus 4.8 007cd95c79 Baseline before Postgres migration (WS0)
Snapshot before the DuckDB->PostgreSQL migration. data/, archive/, the 232MB
rebuild zip, the Windows .venv, and .env are excluded via .gitignore.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-15 23:39:29 -04:00