"""Option 2 sample (pre-registered 2026-10-05): 90 trigger candidates + 90 controls, shuffled, anonymised, key kept apart. Triggers: spring&prior-1 / utad&prior+1 / sos / sow, badvol=0, thinned >=48h per symbol, 2010-2024. Controls: box bars with no trigger, thinned. Equal draw per class. Judge sees chart only; outcome columns never shown.""" import os, sys, numpy as np, pandas as pd sys.path.insert(0, os.path.dirname(__file__)) import discover as D, wyckoff_gold as G, wyckoff_scan as S L = pd.read_csv("wyckoff_ledger.csv", parse_dates=["t"]); L = L[(L.badvol == 0) & (L.t.dt.year >= 2010)] trig = ((L.spring == 1) & (L.prior == -1)) | ((L.utad == 1) & (L.prior == 1)) | (L.sos == 1) | (L.sow == 1) T = pd.concat([S.thin(g) for _, g in L[trig].groupby("sym")]) C = pd.concat([S.thin(g) for _, g in L[~trig].groupby("sym")]) print("trigger pool", len(T), "control pool", len(C)) rng = np.random.default_rng(2026) T = T.iloc[rng.choice(len(T), 90, replace=False)].assign(kind="trig") C = C.iloc[rng.choice(len(C), 90, replace=False)].assign(kind="ctl") A = pd.concat([T, C]).sample(frac=1, random_state=5).reset_index(drop=True) d = os.path.join(G.OUT, "judge"); os.makedirs(d, exist_ok=True) cache = {} for i, r in A.iterrows(): h = cache.setdefault(r.sym, D.load_h1(r.sym)) k = h.index.get_loc(r.t) G.render(h.iloc[k - G.W + 1:k + 1], os.path.join(d, f"{i:03d}.png")) A.insert(0, "id", [f"{i:03d}" for i in range(len(A))]); A.to_csv(os.path.join(d, "_key.csv"), index=False) print(len(A), "charts", d)