from __future__ import annotations import datetime as dt from libs.export.continuation_snapshot import _build_continuation_rows_from_bars def test_build_continuation_rows_reanchors_event_and_labels() -> None: base_rows = [ { "event_id": "EVT::AAPL::1", "ticker": "AAPL", "event_type": "earnings_release", "event_date": "2026-01-05", "reaction_date": "2026-01-05", "entry_date": "2026-01-06", "event_close": 100.0, "parse_confidence_overall": 0.8, "oneoff_penalty": 0.1, } ] bars_by_symbol = { "AAPL": { dt.date(2026, 1, 6): {"open": 101.0, "high": 103.0, "low": 100.0, "close": 102.0, "volume": 1000}, dt.date(2026, 1, 7): {"open": 102.0, "high": 104.0, "low": 101.0, "close": 103.0, "volume": 1100}, dt.date(2026, 1, 8): {"open": 103.0, "high": 105.0, "low": 102.0, "close": 104.0, "volume": 1200}, dt.date(2026, 1, 9): {"open": 104.0, "high": 108.0, "low": 103.0, "close": 107.0, "volume": 1400}, dt.date(2026, 1, 12): {"open": 108.0, "high": 110.0, "low": 107.0, "close": 109.0, "volume": 1500}, dt.date(2026, 1, 13): {"open": 109.0, "high": 111.0, "low": 108.0, "close": 110.0, "volume": 1600}, dt.date(2026, 1, 14): {"open": 110.0, "high": 112.0, "low": 109.0, "close": 111.0, "volume": 1700}, dt.date(2026, 1, 15): {"open": 111.0, "high": 113.0, "low": 110.0, "close": 112.0, "volume": 1800}, dt.date(2026, 1, 16): {"open": 112.0, "high": 114.0, "low": 111.0, "close": 113.0, "volume": 1900}, } } rows = _build_continuation_rows_from_bars(base_rows, bars_by_symbol, lookback_days=3) assert len(rows) == 1 row = rows[0] assert row["event_id"] == "EVT::AAPL::1::cont_d3" assert row["original_event_id"] == "EVT::AAPL::1" assert row["event_date"] == "2026-01-09" assert row["reaction_date"] == "2026-01-09" assert row["entry_date"] == "2026-01-12" assert abs(row["continuation_anchor_drift_pct"] - 0.07) < 1e-9 assert row["entry_convention"] == "next_open_after_continuation_signal" assert row["fwd_return_3d"] is not None def test_build_continuation_rows_skips_when_not_enough_bars() -> None: base_rows = [ { "event_id": "EVT::AAPL::2", "ticker": "AAPL", "event_type": "earnings_release", "event_date": "2026-01-05", "reaction_date": "2026-01-05", "entry_date": "2026-01-06", "event_close": 100.0, } ] bars_by_symbol = { "AAPL": { dt.date(2026, 1, 6): {"open": 101.0, "high": 103.0, "low": 100.0, "close": 102.0, "volume": 1000}, dt.date(2026, 1, 7): {"open": 102.0, "high": 104.0, "low": 101.0, "close": 103.0, "volume": 1100}, dt.date(2026, 1, 8): {"open": 103.0, "high": 105.0, "low": 102.0, "close": 104.0, "volume": 1200}, } } assert _build_continuation_rows_from_bars(base_rows, bars_by_symbol, lookback_days=3) == []