diff --git a/app/services/alert_service.py b/app/services/alert_service.py index 16a6470..54c411e 100644 --- a/app/services/alert_service.py +++ b/app/services/alert_service.py @@ -224,25 +224,6 @@ async def _watchlist_tickers(db: AsyncSession) -> list[tuple[int, str]]: return [(tid, sym) for tid, sym in result.all()] -async def _alert_scope_tickers(db: AsyncSession) -> list[tuple[int, str]]: - """Tickers eligible for S/R-proximity alerts: watchlist ∪ qualified setups. - - A ticker only matters for a proximity heads-up if you're watching it or it - has an actionable setup — not the whole universe. - """ - scope: dict[int, str] = {tid: sym for tid, sym in await _watchlist_tickers(db)} - - qualified_symbols = {s["symbol"] for s in await _qualified_setups(db)} - missing = qualified_symbols - set(scope.values()) - if missing: - result = await db.execute( - select(Ticker.id, Ticker.symbol).where(Ticker.symbol.in_(missing)) - ) - for tid, sym in result.all(): - scope[tid] = sym - return list(scope.items()) - - async def _qualified_setups(db: AsyncSession) -> list[dict]: setups = await get_trade_setups(db) config = await get_activation_config(db) @@ -280,14 +261,15 @@ async def _latest_close(db: AsyncSession, ticker_id: int) -> float | None: async def _collect_sr_proximity(db: AsyncSession) -> list[tuple[str, str]]: - """One alert per ticker for the NEAREST strong S/R zone within range. + """One alert per watchlist ticker for the NEAREST strong S/R zone within range. Levels are merged into zones with the same clusterer the chart uses, so a cluster of near-duplicate levels (e.g. 183 + 185) is a single zone and a - single alert. Scoped to watchlist ∪ qualified tickers. + single alert. Scoped to the watchlist only — qualified tickers already get + their own 'qualified setup' alert, so S/R on them would be redundant. """ out: list[tuple[str, str]] = [] - for tid, symbol in await _alert_scope_tickers(db): + for tid, symbol in await _watchlist_tickers(db): price = await _latest_close(db, tid) if not price: continue