scope S/R proximity alerts to watchlist only
Qualified tickers already get their own "qualified setup" alert, so an S/R proximity ping on them is redundant noise. Drop the watchlist ∪ qualified scope (remove now-unused _alert_scope_tickers) and alert only on watchlist tickers. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -224,25 +224,6 @@ async def _watchlist_tickers(db: AsyncSession) -> list[tuple[int, str]]:
|
|||||||
return [(tid, sym) for tid, sym in result.all()]
|
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]:
|
async def _qualified_setups(db: AsyncSession) -> list[dict]:
|
||||||
setups = await get_trade_setups(db)
|
setups = await get_trade_setups(db)
|
||||||
config = await get_activation_config(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]]:
|
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
|
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
|
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]] = []
|
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)
|
price = await _latest_close(db, tid)
|
||||||
if not price:
|
if not price:
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user