# Premium-support ("black box") variants V1-V4 on the ATM option premium chart; exits X_OLD and X_T50 (PREREG PREMIUM-SUPPORT section). import sys,time; sys.path.insert(0,'/workspace/research/popular-strategies/scripts'); from plib import * t0=time.time(); S,PC=load_spot(); OPT=opt(); RS=f'{L}/results' DAYS=[d for d in sorted(S) if pd.Timestamp('2024-10-21')<=d<=LAST and nexp(d) is not None] ALLD=sorted(S); PREV={d:ALLD[i-1] for i,d in enumerate(ALLD) if i>0} T_END=hm2i('15:15'); W0=hm2i('09:44'); W1=hm2i('14:29'); W1B=hm2i('13:29'); SL=0.5 def prem5(oa): o,h,l,c=oa; P=np.full((4,72),np.nan) for k in range(72): s=slice(5*k,5*k+5); cc=c[s] if np.all(np.isnan(cc)): continue idx=np.where(~np.isnan(cc))[0]; P[0,k]=o[s][idx[0]]; P[1,k]=np.nanmax(h[s]); P[2,k]=np.nanmin(l[s]); P[3,k]=cc[idx[-1]] return P _p5={} def chart(d,e,typ,K): key=(d,e,typ,K) if key not in _p5: oa=oarr(d,e,typ,K); _p5[key]=(oa,prem5(oa)) if oa is not None else (None,None) return _p5[key] def spot5c(a): c=a[3]; return np.array([c[5*k+4] if not np.isnan(c[5*k+4]) else (c[5*k:5*k+5][~np.isnan(c[5*k:5*k+5])][-1] if (~np.isnan(c[5*k:5*k+5])).any() else np.nan) for k in range(72)]) def tol(x): return max(2.0,0.03*x) def pdl(d,e,typ,K): p=PREV.get(d); if p is None: return np.nan O=OPT.get((p,e)) if O is None or ('low',typ,K) not in O.columns: return np.nan v=O[('low',typ,K)].values; return np.nanmin(v) if np.isfinite(v).any() else np.nan def touch_ok(P,k,lvl): if not np.isfinite(lvl) or k<1: return False t=tol(lvl); return (lvl-t<=P[2,k]<=lvl+t) and (P[3,k-1]>lvl+t) def scan(d,var): e=nexp(d); a=S[d]; sc=spot5c(a); hits=[] for j in range(1,72): m=5*j+4 if m(W1B if var=='V4' else W1): continue for typ in ('CE','PE'): if var=='V4': if np.isnan(sc[j]): continue K=float(round(sc[j]/50)*50); oa,P=chart(d,e,typ,K) if P is None or np.isnan(P[3,j]): continue ph=np.nanmax(P[1,:j]) if np.isfinite(P[1,:j]).any() else np.nan if np.isfinite(ph) and P[3,j]>ph: hits.append((m,typ,K,P[2,j]-1,ph)) continue k=j-1 if np.isnan(sc[k]): continue K=float(round(sc[k]/50)*50); oa,P=chart(d,e,typ,K) if P is None or np.isnan(P[3,j]) or np.isnan(P[2,k]): continue if var=='V1': lvl=pdl(d,e,typ,K) elif var=='V2': lvl=np.nan for p in range(k-3,2,-1): if p+2>=k or p-2<0: continue w=P[2,p-2:p+3] if np.isfinite(w).all() and P[2,p]==w.min() and (wP[1,k] and P[3,j]>lvl: hits.append((m,typ,K,P[2,k]-1,lvl)) if hits: break if not hits: return None if len({h[1] for h in hits})>1: return 'both' return dict(zip(['m','typ','K','stop','level'],hits[0]))+dict(e=e) if False else dict(m=hits[0][0],typ=hits[0][1],K=hits[0][2],stop=hits[0][3],level=hits[0][4],e=e) def run_exit(d,oa,m,ex,Rp=None): raw=oa[0,m+1] if m+1m+1 else stop-SL)); rem=0; why='stop' if not t1 else 'lock'; xx=x; break if not t1 and hi>=fill+20: sells.append((0.4,fill+20-SL)); rem-=0.4; t1=True; stop=max(stop,fill+10) if not t2 and hi>=fill+40: sells.append((0.3,fill+40-SL)); rem-=0.3; t2=True; stop=max(stop,fill+25) if hi>=fill+60: sells.append((rem,fill+60-SL)); rem=0; why='target'; xx=x; break peak=max(peak,hi) if t2: stop=max(stop,peak-15) else: Rp=min(max(Rp,5.0),30.0); stop=raw-Rp; peak=0.0; rem=1.0 for x in range(m+1,T_END): op,hi,lo,cl=oa[:,x] if np.isnan(cl): continue if lo<=stop: sells.append((1.0,(min(op,stop) if x>m+1 else stop)-SL)); rem=0; why='stop'; xx=x; break pr=cl-raw; peak=max(peak,pr) if peak>=2*Rp and pr<=0.5*peak: px,y=next_px(oa,x+1) if y is not None: sells.append((1.0,px-SL)); rem=0; why='trail'; xx=y; break if rem>1e-9: px,y=next_px(oa,T_END) if y is None: v=np.where(~np.isnan(oa[3,:T_END+10]))[0]; v=v[v>m] if not len(v): return None px=oa[3,v[-1]]; y=v[-1] sells.append((rem,px-SL)); xx=y g=sum(f*p for f,p in sells)-fill; c_=charges(d,fill,sells,True) return dict(raw=raw,fill=fill,gross=g,cost=c_,pnl=g-c_,why=why,exit_min=i2hm(xx),n_orders=1+len(sells)) LAB=pd.read_csv(f'{RS}/regime_labels.csv',parse_dates=['date']).set_index('date') rows=[]; skipped=dict(both=0,nobar=0) for var in ('V1','V2','V3','V4'): for d in DAYS: s=scan(d,var) if s is None: continue if s=='both': skipped['both']+=1; continue oa,_=chart(d,s['e'],s['typ'],s['K']); raw=oa[0,s['m']+1] if s['m']+1