SPB Git

spb/findata

Public
2.3 KB · 32 lines python
1from __future__ import annotations23from fastapi import APIRouter, Depends, Query4from findata_core.db import connection56from findata_api import auth as A78router = APIRouter(prefix="/quality", tags=["quality"])91011@router.get("")12def quality(dataset_id: str = "market_bars.stock.1m.raw", p: A.Principal = Depends(A.require("read:market"))):13    with connection() as conn:14        report = conn.execute("SELECT * FROM quality_reports WHERE dataset_id=%s ORDER BY created_at DESC LIMIT 1", (dataset_id,)).fetchone()15        by_code = conn.execute("SELECT code, severity, count(*) n, sum((detail->>'rows')::int) rows FROM quality_anomalies WHERE dataset_id=%s AND created_at > now() - interval '30 days' GROUP BY 1,2 ORDER BY n DESC", (dataset_id,)).fetchall()16        reports = conn.execute("SELECT id, created_at, rows_checked, anomalies, summary FROM quality_reports WHERE dataset_id=%s ORDER BY created_at DESC LIMIT 30", (dataset_id,)).fetchall()17    return {"latest": report, "anomalies_by_code_30d": by_code, "reports": reports,18            "codes": {"ohlc_inconsistent": "high < max(open,close) or low > min(open,close)", "nonpositive_price": "price <= 0",19                      "negative_volume": "volume < 0", "zero_volume": "volume == 0 (vendor normally omits these)", "fractional_volume": "non-integral volume",20                      "off_interval": "timestamp not on the interval grid", "duplicate": "duplicate (symbol, timestamp)",21                      "outside_session": "outside 04:00–20:00 ET", "non_trading_day": "bars on a non-session date", "price_jump": ">25 % move between consecutive bars"}}222324@router.get("/anomalies")25def anomalies(dataset_id: str = "market_bars.stock.1m.raw", code: str | None = None, severity: str | None = None, symbol: str | None = None,26              limit: int = Query(200, le=5000), p: A.Principal = Depends(A.require("read:market"))):27    with connection() as conn:28        rows = conn.execute("SELECT id, symbol, session_date, code, severity, detail, created_at FROM quality_anomalies WHERE dataset_id=%s "29                            "AND (%s::text IS NULL OR code=%s) AND (%s::text IS NULL OR severity=%s) AND (%s::text IS NULL OR symbol=%s) ORDER BY created_at DESC, id DESC LIMIT %s",30                            (dataset_id, code, code, severity, severity, symbol, symbol, limit)).fetchall()31    return {"data": rows}32
Files · main
Menu

Theme