""" Loud-window conditioning of the Wyckoff ledger (2026-10-05). PRE-REGISTERED: per symbol, the 8 highest mean-range hours and the 3 highest mean-range weekdays are chosen from 2010-2017 ONLY; the four setups are then evaluated inside those windows on 2018-2024 (OOS). Control = same direction on every box bar inside the same windows. """ import os, sys, numpy as np, pandas as pd sys.path.insert(0, os.path.dirname(__file__)) import discover as D from wyckoff_scan import thin, tstat L = pd.read_csv(os.path.join(os.path.dirname(__file__), "wyckoff_ledger.csv"), parse_dates=["t"]) loud_h, loud_d = {}, {} for s in L.sym.unique(): b = D.load_h1(s); b = b[(b.index < "2018-01-01") & (b.index.year >= D.START[s])] rg = (b.h - b.l) / b.c loud_h[s] = set(rg.groupby(b.index.hour).mean().nlargest(8).index) loud_d[s] = set(rg.groupby(b.index.dayofweek).mean().nlargest(3).index) print(s, "hours", sorted(loud_h[s]), "days", sorted(loud_d[s])) L["loud"] = [(t.hour in loud_h[s]) and (t.dayofweek in loud_d[s]) for s, t in zip(L.sym, L.t)] oos = L[L.t >= "2018-01-01"] setups = [("SPRING_L", (oos.spring == 1) & (oos.prior == -1), "rL"), ("SOS_L", oos.sos == 1, "rL"), ("UTAD_S", (oos.utad == 1) & (oos.prior == 1), "rS"), ("SOW_S", oos.sow == 1, "rS")] print(f"\nOOS 2018-2024. {'setup':9s}{'window':8s}{'n':>5s}{'meanR':>8s}{'t':>6s}{'ctl':>8s}{'ctl n':>7s}{'lift':>7s}") for name, m, col in setups: for w, sel in (("loud", oos.loud), ("quiet", ~oos.loud)): tr = pd.concat([thin(g) for _, g in oos[m & sel].groupby("sym")]) if (m & sel).sum() else oos[m & sel] ctl = pd.concat([thin(g) for _, g in oos[sel].groupby("sym")]) if len(tr) < 3: print(f"{'':20s}{name:9s}{w:8s}{len(tr):5d} too few"); continue x, y = tr[col].to_numpy(), ctl[col].to_numpy() print(f"{'':20s}{name:9s}{w:8s}{len(x):5d}{x.mean():8.3f}{tstat(x):6.1f}{y.mean():8.3f}{len(y):7d}{x.mean()-y.mean():7.3f}")