perf: scope SEC ticker quality checks
This commit is contained in:
@@ -69,25 +69,42 @@ async def _latest_validation(db: AsyncSession) -> dict:
|
||||
return summary if isinstance(summary, dict) else {}
|
||||
|
||||
|
||||
async def blocked_reasons_by_cik(db: AsyncSession) -> dict[str, str]:
|
||||
async def blocked_reasons_by_cik(
|
||||
db: AsyncSession,
|
||||
ciks: set[str] | None = None,
|
||||
) -> dict[str, str]:
|
||||
"""Current SEC blocker code by CIK; no historical audit scan."""
|
||||
if not await fundamental_data_refresh_service.is_enabled(db):
|
||||
return {}
|
||||
if ciks is not None and not ciks:
|
||||
return {}
|
||||
|
||||
reasons = {gap.cik: "sec_filing_gap" for gap in await active_gaps(db)}
|
||||
reasons = {
|
||||
gap.cik: "sec_filing_gap" for gap in await active_gaps(db, ciks)
|
||||
}
|
||||
summary = await _latest_validation(db)
|
||||
|
||||
def wanted(cik: str) -> bool:
|
||||
return ciks is None or cik in ciks
|
||||
|
||||
# New summaries carry the complete compact CIK set while the detailed lists
|
||||
# stay capped for audit readability. Detailed entries supply the reason.
|
||||
for cik in summary.get("setup_blocked_ciks") or []:
|
||||
if cik:
|
||||
reasons.setdefault(str(cik), "sec_filing_gap")
|
||||
normalized = str(cik) if cik else ""
|
||||
if normalized and wanted(normalized):
|
||||
reasons.setdefault(normalized, "sec_filing_gap")
|
||||
for item in summary.get("missing_xbrl") or []:
|
||||
if item.get("cik"):
|
||||
reasons.setdefault(str(item["cik"]), "sec_filing_gap")
|
||||
normalized = str(item.get("cik") or "")
|
||||
if normalized and wanted(normalized):
|
||||
reasons.setdefault(normalized, "sec_filing_gap")
|
||||
for cik in summary.get("no_xbrl_ciks") or []:
|
||||
normalized = str(cik) if cik else ""
|
||||
if normalized and wanted(normalized):
|
||||
reasons[normalized] = "no_xbrl_filings"
|
||||
for item in summary.get("no_xbrl_filings") or []:
|
||||
if item.get("cik"):
|
||||
reasons[str(item["cik"])] = "no_xbrl_filings"
|
||||
normalized = str(item.get("cik") or "")
|
||||
if normalized and wanted(normalized):
|
||||
reasons[normalized] = "no_xbrl_filings"
|
||||
return reasons
|
||||
|
||||
|
||||
@@ -111,7 +128,7 @@ async def ticker_quality(db: AsyncSession, symbol: str) -> SetupQuality:
|
||||
).scalar_one_or_none()
|
||||
if ticker is None or not ticker.cik:
|
||||
return SetupQuality(eligible=True)
|
||||
reason = (await blocked_reasons_by_cik(db)).get(ticker.cik)
|
||||
reason = (await blocked_reasons_by_cik(db, {ticker.cik})).get(ticker.cik)
|
||||
if reason == "no_xbrl_filings":
|
||||
return SetupQuality(
|
||||
eligible=False,
|
||||
@@ -135,4 +152,9 @@ async def ticker_quality(db: AsyncSession, symbol: str) -> SetupQuality:
|
||||
|
||||
|
||||
async def ticker_is_eligible(db: AsyncSession, ticker_id: int) -> bool:
|
||||
return ticker_id not in await blocked_ticker_ids(db)
|
||||
cik = (
|
||||
await db.execute(select(Ticker.cik).where(Ticker.id == ticker_id))
|
||||
).scalar_one_or_none()
|
||||
if not cik:
|
||||
return True
|
||||
return cik not in await blocked_reasons_by_cik(db, {cik})
|
||||
|
||||
Reference in New Issue
Block a user