"""SH01 path live: last_block_only == tail del walk-forward completo (parity by construction) + merge storia parquet/feed del runner.""" import numpy as np import pandas as pd import pytest from src.portfolio.runner import _with_history def _df(n=6500, seed=0, t0=1_600_000_000_000): rng = np.random.default_rng(seed) c = 100 * np.exp(np.cumsum(rng.normal(0, 0.01, n))) h = c * (1 + np.abs(rng.normal(0, 0.004, n))) l = c * (1 - np.abs(rng.normal(0, 0.004, n))) o = np.roll(c, 1); o[0] = c[0] ts = t0 + 3_600_000 * np.arange(n) return pd.DataFrame({"timestamp": ts, "open": o, "high": h, "low": l, "close": c, "volume": 1.0}) def test_last_block_only_matches_full_wf_tail(): from scripts.analysis.shape_ml_research import ml_wf_entries df = _df() cfg = dict(W=24, H=12, model="logit", thresh=0.55, train_min=4000, retrain=500) full = ml_wf_entries(df, **cfg) last = ml_wf_entries(df, last_block_only=True, **cfg) n = len(df) # confine dell'ultimo blocco: start + k*retrain (deterministico) start = max(cfg["train_min"], cfg["W"] - 1) B = start while B + cfg["retrain"] < n - 1: B += cfg["retrain"] full_tail = [e for e in full if e["i"] >= B] assert last == full_tail # identita' esatta, non solo simile assert all(e["i"] >= B for e in last) def test_with_history_merges_contiguous(): hist = _df(n=100) live = _df(n=50, t0=int(hist["timestamp"].iloc[60])) # overlap: live parte dentro hist out = _with_history(hist, live) assert len(out) == 60 + 50 # hist pre-overlap + live completo ts = out["timestamp"].values assert (np.diff(ts) > 0).all() # serie strettamente crescente def test_with_history_gap_falls_back_to_live(): hist = _df(n=100) gap_start = int(hist["timestamp"].iloc[-1]) + 10 * 3_600_000 # buco di 10 barre live = _df(n=50, t0=gap_start) warned = set() out = _with_history(hist, live, warned, "BTC") assert len(out) == 50 and "BTC" in warned # solo feed + warn deduplicato out2 = _with_history(hist, live, warned, "BTC") assert len(out2) == 50 # secondo giro: nessun nuovo warn def test_with_history_none_hist_passthrough(): live = _df(n=50) assert _with_history(None, live) is live