SPB Git

spb/wp41_uqo

Public
3.5 KB · 63 lines python
1"""P0 audit: live FinData catalog, bars schema, OpenAPI, timestamp conventions on real rows (secrets never printed)."""2from __future__ import annotations34import json5import sys6import time7from datetime import datetime, timezone8from pathlib import Path910sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))11from chronos_x.data.client import FinDataClient  # noqa: E40212from chronos_x.data.calendar import sessions  # noqa: E4021314ROOT = Path(__file__).resolve().parents[1]15OUT = ROOT / "results" / "metrics" / "p0_api_audit.json"161718def main() -> None:19    c = FinDataClient(log_path=ROOT / "results" / "logs" / "provenance_audit.jsonl")20    t0 = time.time()21    health = c.health()22    datasets = c.datasets()23    schema = c.bars_schema()24    openapi = c.openapi()25    report = {"audited_at": datetime.now(timezone.utc).isoformat(), "base": c.base,26              "health": {k: health.get(k) for k in ("status", "checked_at", "alerts")},27              "lake": health.get("components", {}).get("lake"),28              "openapi": {"version": openapi.get("openapi"), "n_paths": len(openapi.get("paths", {})),29                          "export_schema": openapi.get("components", {}).get("schemas", {}).get("ExportIn")},30              "bars_schema": schema,31              "datasets": {d["id"]: {k: d.get(k) for k in ("status", "row_count", "first_session", "last_session",32                                                          "license_class")}33                           for d in datasets if d["id"].startswith(("market_bars.stock", "market_bars.etf", "corporate"))}}34    # timestamp conventions on real rows35    checks = {}36    for sym, day in (("AAPL", "2024-03-08"), ("AAPL", "2024-03-11"), ("AAPL", "2024-11-29"), ("SPY", "2024-07-03")):37        t = c.bars(sym, day, day).to_pandas()38        s = sessions(day, day)[0]39        reg = t[(t["timestamp_utc"] >= s.open_utc) & (t["timestamp_utc"] <= s.close_utc)]40        checks[f"{sym}_{day}"] = {"rows_total": int(len(t)), "rows_regular": int(len(reg)), "expected_regular": s.n_slots,41                                 "first_ts": str(t["timestamp_utc"].min()), "last_ts": str(t["timestamp_utc"].max()),42                                 "open_utc": str(s.open_utc), "close_utc": str(s.close_utc),43                                 "closing_print_volume": float(reg[reg["timestamp_utc"] == s.close_utc]["volume"].sum()),44                                 "median_regular_volume": float(reg["volume"].median()),45                                 "quality_flags_nonempty": int((reg["quality_flags"].map(len) > 0).sum()),46                                 "revision_ids": sorted(int(x) for x in t["revision_id"].unique())}47    # split consistency: raw vs server-side split on AAPL around 2020-08-31 (4:1)48    raw = c.bars("AAPL", "2020-08-28", "2020-08-28").to_pandas()49    spl = c.bars("AAPL", "2020-08-28", "2020-08-28", adjustment="split").to_pandas()50    ratio = float((raw["close"] / spl["close"]).median())51    checks["AAPL_split_2020-08-31"] = {"raw_over_split_median": ratio, "expected": 4.0,52                                       "volume_ratio": float((spl["volume"] / raw["volume"]).median())}53    report["timestamp_checks"] = checks54    report["elapsed_s"] = round(time.time() - t0, 1)55    OUT.parent.mkdir(parents=True, exist_ok=True)56    OUT.write_text(json.dumps(report, indent=1, default=str))57    print(json.dumps({k: v for k, v in report.items() if k in ("health", "lake", "timestamp_checks", "elapsed_s")},58                     indent=1, default=str))596061if __name__ == "__main__":62    main()63
Files · main
Menu

Theme