# Pre-specified 'heavy buying at the low' signals + controls; outcomes on spot (no filling, cap 15:14) import pandas as pd,numpy as np,itertools P=pd.read_parquet('data/minute_panel_v.parquet') P=P[P.hm<='15:14'].copy() P['tm']=P.timestamp.dt.hour*60+P.timestamp.dt.minute ROWS=[] XS=[150,200,250]; VS=[3,5] for d,g in P.groupby('date'): g=g.reset_index(drop=True) if g.close.isna().mean()>0.05: continue # sessions with >5% missing minutes skipped (data gap) o,h,l,c=g.open.values,g.high.values,g.low.values,g.close.values fvr=g.fvr.values; foi=g.foi.values; tm=g.tm.values; n=len(g) rh=np.fmax.accumulate(np.nan_to_num(h,nan=-1e9)); rl=np.fmin.accumulate(np.nan_to_num(l,nan=1e9)) rh_i=np.array([int(np.argmax(np.nan_to_num(h[:i+1],nan=-1e9))) for i in range(n)]) rl_i=np.array([int(np.argmin(np.nan_to_num(l[:i+1],nan=1e9))) for i in range(n)]) fv3=pd.Series(fvr).rolling(3,min_periods=3).mean().values doi3=foi-np.r_[[np.nan]*3,foi[:-3]] done={} for t in range(1,n): if not (9*60+20<=tm[t]<=14*60+14): continue if not np.isfinite(c[t]) or not np.isfinite(c[t-1]): continue dd=rh[t]-rl[t] if dd<150 or rl_i[t]3: continue rng=h[t]-l[t]; shape=(rng>0) and (c[t]>=l[t]+0.6*rng) and (c[t]>c[t-1]) and (c[t]-rl[t]<=25) at_low=(c[t]-rl[t]<=25) fut=dict(fvr1=fvr[t],fvr3=fv3[t],doi3=doi3[t]) # outcomes H={k:min(t+k,n-1) for k in (15,30,60)} out={} for k,j in H.items(): seg=h[t+1:j+1]; out[f'mfe{k}']=np.nanmax(seg)-c[t] if len(seg) and np.isfinite(seg).any() else np.nan segl=l[t+1:j+1]; out[f'mae{k}']=np.nanmin(segl)-c[t] if len(segl) and np.isfinite(segl).any() else np.nan segl=l[t+1:min(t+61,n)]; out['hold60']=bool(np.nanmin(segl)>=rl[t]) if np.isfinite(segl).any() else np.nan segl=l[t+1:]; out['hold_day']=bool(np.nanmin(segl)>=rl[t]) if np.isfinite(segl).any() else np.nan out['to_1514']=c[n-1]-c[t] if np.isfinite(c[n-1]) else np.nan for X in XS: if dd