Warrior_EA/research/wyckoff_judge_sample.py

23 lines
1.5 KiB
Python

"""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)