1"""Live contract tests against FinData OS (WP41_LIVE=1). They verify, on real rows, the conventions the pipeline2relies on: bar-open stamps, regular-session counts, split equivalence, export == paged bars, provenance headers."""3import os4from pathlib import Path56import numpy as np7import pandas as pd8import pytest9import polars as pl10import pyarrow.parquet as pq1112from chronos_x.data.client import FinDataClient, validate_bars_schema13from chronos_x.data.calendar import sessions14from chronos_x.data.adjustments import apply_splits15from chronos_x.data.features import build_grid1617pytestmark = pytest.mark.live181920@pytest.fixture(scope="module")21def client(tmp_path_factory):22 return FinDataClient(log_path=tmp_path_factory.mktemp("prov") / "prov.jsonl")232425def test_schema_and_headers(client):26 sch = client.bars_schema()27 assert sch["timestamp_convention"] == "bar_open" and sch["timezone_storage"] == "UTC"28 r = client.request("GET", "/market/bars", params={"symbol": "AAPL", "interval": "1m", "start": "2024-03-11",29 "end": "2024-03-11", "limit": 5, "format": "arrow"})30 assert r.headers.get("x-request-id") and r.headers.get("x-dataset-version")313233def test_regular_session_counts_on_real_rows(client):34 for sym, day, n in (("AAPL", "2024-03-08", 391), ("AAPL", "2024-03-11", 391), ("AAPL", "2024-11-29", 211)):35 t = client.bars(sym, day, day).to_pandas()36 s = sessions(day, day)[0]37 reg = t[(t["timestamp_utc"] >= s.open_utc) & (t["timestamp_utc"] <= s.close_utc)]38 assert len(reg) == n39 assert reg["timestamp_utc"].min() == s.open_utc404142def test_explicit_split_equals_server_split(client):43 raw = pl.from_arrow(client.bars("AAPL", "2020-08-24", "2020-09-04"))44 srv = pl.from_arrow(client.bars("AAPL", "2020-08-24", "2020-09-04", adjustment="split")).sort("timestamp_utc")45 acts = client.instrument("AAPL")["corporate_actions"]46 ours = apply_splits(raw, acts).sort("timestamp_utc")47 np.testing.assert_allclose(ours["close"].to_numpy(), srv["close"].to_numpy(), rtol=1e-9)48 np.testing.assert_allclose(ours["volume"].to_numpy(), srv["volume"].to_numpy(), rtol=1e-9)495051def test_export_matches_paged_bars(client, tmp_path):52 dest = tmp_path / "x.parquet"53 res = client.export(["MSFT"], "2024-02-01", "2024-02-07", dest)54 exp = pq.read_table(dest)55 validate_bars_schema(exp.schema)56 paged = client.bars("MSFT", "2024-02-01", "2024-02-07")57 a = exp.to_pandas().sort_values("timestamp_utc").reset_index(drop=True)58 b = paged.to_pandas().sort_values("timestamp_utc").reset_index(drop=True)59 assert len(a) == len(b) == res.row_count60 np.testing.assert_allclose(a["close"].values, b["close"].values)61 assert res.sha256 and res.dataset_version626364def test_grid_from_real_rows(client):65 raw = pl.from_arrow(client.bars("SPY", "2024-06-24", "2024-07-05"))66 arrays, meta = build_grid(raw, [], "2024-06-24", "2024-07-05", "SPY", "etf")67 i = meta.session_dates.index("2024-07-03")68 assert meta.n_slots[i] == 211 and meta.early_close[i]69 assert "2024-07-04" not in meta.session_dates70 assert arrays["mask"][i, :211].mean() > 0.99 and arrays["mask"][i, 211:].sum() == 071 j = meta.session_dates.index("2024-06-25")72 assert arrays["mask"][j].mean() > 0.9973