fix: harden Structural S/R after OHLCV writes and surface cleanup failures
Honor custom S/R tolerance as a transient detect, refresh levels after OHLCV mutations without failing committed price writes, report per-ticker S/R rebuild failures from admin cleanup, and warn in the admin UI when refresh is partial.
This commit is contained in:
@@ -318,14 +318,18 @@ async def update_ticker_universe_default(db: AsyncSession, universe: str) -> dic
|
||||
# Data cleanup
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
async def cleanup_data(db: AsyncSession, older_than_days: int) -> dict[str, int]:
|
||||
async def cleanup_data(db: AsyncSession, older_than_days: int) -> dict:
|
||||
"""Delete OHLCV, sentiment, and fundamental records older than N days.
|
||||
|
||||
Preserves tickers, users, and latest scores.
|
||||
Returns a dict with counts of deleted records per table.
|
||||
Preserves tickers, users, and latest scores. After OHLCV pruning, rebuilds
|
||||
Structural S/R for every ticker so chart levels match the remaining history.
|
||||
|
||||
Returns deleted-row counts plus S/R refresh outcomes. A per-ticker S/R
|
||||
failure rolls the session back (so later tickers still run) and is listed
|
||||
in ``sr_refresh_failures`` rather than aborting the whole cleanup.
|
||||
"""
|
||||
cutoff = datetime.now(timezone.utc) - timedelta(days=older_than_days)
|
||||
counts: dict[str, int] = {}
|
||||
counts: dict = {}
|
||||
|
||||
# OHLCV — date column is a date, compare with cutoff date
|
||||
result = await db.execute(
|
||||
@@ -346,6 +350,36 @@ async def cleanup_data(db: AsyncSession, older_than_days: int) -> dict[str, int]
|
||||
counts["fundamentals"] = result.rowcount # type: ignore[assignment]
|
||||
|
||||
await db.commit()
|
||||
|
||||
counts["sr_refresh_ok"] = 0
|
||||
counts["sr_refresh_failed"] = 0
|
||||
counts["sr_refresh_failures"] = []
|
||||
|
||||
# Structural S/R is derived from OHLCV; recompute after history shrinks.
|
||||
if counts["ohlcv"]:
|
||||
from app.services.sr_service import recalculate_sr_levels
|
||||
|
||||
symbols = list(
|
||||
(await db.execute(select(Ticker.symbol).order_by(Ticker.symbol))).scalars().all()
|
||||
)
|
||||
for symbol in symbols:
|
||||
try:
|
||||
await recalculate_sr_levels(db, symbol)
|
||||
counts["sr_refresh_ok"] += 1
|
||||
except Exception as exc:
|
||||
logger.exception("S/R refresh after cleanup failed for %s", symbol)
|
||||
try:
|
||||
await db.rollback()
|
||||
except Exception:
|
||||
logger.exception(
|
||||
"Session rollback after S/R cleanup failure also failed for %s",
|
||||
symbol,
|
||||
)
|
||||
counts["sr_refresh_failed"] += 1
|
||||
counts["sr_refresh_failures"].append(
|
||||
{"symbol": symbol, "error": f"{type(exc).__name__}: {exc}"}
|
||||
)
|
||||
|
||||
return counts
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user