# TWENTY-NO-TV (PREREG 20:31 IST 27-Oct-2026): ~20 premium that is almost all intrinsic (ITM by ~20). Real bars; spot>=15:15 missing, not filled. import sys; sys.path.insert(0,'/workspace/research/popular-strategies/scripts') from ec_lib import * from multiprocessing import Pool WN=[('W1',20,105),('W2',105,225),('W3',225,315),('W4',315,345)] def wof(t): return next(w for w,a,b in WN if a<=t<=b) SHL={} for ix in ('NIFTY','SENSEX'): d=pd.read_parquet(f'{CD}/{ix.lower()}_1m_clean.parquet'); d['mi']=d.timestamp.dt.hour*60+d.timestamp.dt.minute-555 for dt,g in d.groupby('date'): h=np.full(375,np.nan); l=np.full(375,np.nan); ok=(g.mi>=0)&(g.mi<360)&(~g.missing); h[g.mi[ok].values]=g.high[ok].values; l[g.mi[ok].values]=g.low[ok].values; SHL[(ix,dt)]=(h,l) e=pd.read_parquet('/workspace/market-live-stack/bots/upstox/eod/2026-10-27/nifty_1m_2026-10-27.parquet'); ts=pd.to_datetime(e.timestamp); m=(ts.dt.hour*60+ts.dt.minute-555).values; k=m<360 h=np.full(375,np.nan); l=np.full(375,np.nan); h[m[k]]=e.high.values[k]; l[m[k]]=e.low.values[k]; SHL[('NIFTY',pd.Timestamp('2026-10-27'))]=(h,l) def trendo(s,OPEN): tr=np.zeros(375,int) for t in range(20,346): if np.isnan(s[t]) or np.isnan(s[t-20]): continue tr[t]=1 if (s[t]>OPEN and s[t]-s[t-20]>0) else -1 if (s[t]=2*R else g) if peak>=2*R and g<=0.5*peak: ex=r[3,y]-slip; why='trail'; break if ex is None: ex=r[3,last]-slip ex=max(ex,0.05); return ex-fill-chg(ix,dt,fill,[(1,ex)]),why def fchg(ix,dt,e,x): Q=lot(ix,dt); stt=(0.0005 if dt>=pd.Timestamp('2026-04-01') else 0.0002)*x; tx=(0.0000173 if ix=='NIFTY' else 0.000005)*(e+x); st=0.00002*e; sebi=1e-6*(e+x); gst=0.18*(40/Q+tx+sebi) return 40/Q+stt+tx+st+sebi+gst def spotctl(ix,dt,s,t,d,f,slip): h,l=SHL[(ix,dt)]; e=s[t]+d*slip; ys=[y for y in range(t+1,360) if not np.isnan(s[y])] if not ys: return dict(sa=np.nan,sb=np.nan,sc=np.nan) last=ys[-1]; Sx=DH[ix].close.get(dt,np.nan); out={} def G(p): return d*(p-e) # a' s1=s2=None; stop=False for y in ys: adv=G(l[y] if d>0 else h[y]) if not np.isnan(h[y]) else G(s[y]); fav=G(h[y] if d>0 else l[y]) if not np.isnan(h[y]) else G(s[y]) if adv<=-20*f: g1=-20*f if s1 is None else s1; s1=g1; s2=-20*f; stop=True; break if s1 is None and fav>=20*f: s1=20*f if fav>=40*f: s2=40*f; break if s1 is None: s1=G(s[last])-slip if s2 is None: s2=G(s[last])-slip if stop and s1==-20*f: s1=-20*f-slip; s2=-20*f-slip out['sa']=0.5*(s1+s2)-fchg(ix,dt,e,e) # b' peak=0; ex=None for y in ys: adv=G(l[y] if d>0 else h[y]) if not np.isnan(h[y]) else G(s[y]); fav=G(h[y] if d>0 else l[y]) if not np.isnan(h[y]) else G(s[y]); g=G(s[y]) if adv<=-10*f: ex=-10*f-slip; break peak=max(peak,fav if fav>=20*f else g) if peak>=20*f and g<=0.5*peak: ex=g-slip; break if ex is None: ex=G(s[last])-slip out['sb']=ex-fchg(ix,dt,e,e) # c' ex=None for y in ys: adv=G(l[y] if d>0 else h[y]) if not np.isnan(h[y]) else G(s[y]) if adv<=-20*f: ex=-20*f-slip; break if ex is None: ex=G(Sx) if not np.isnan(Sx) else np.nan out['sc']=ex-fchg(ix,dt,e,e); return out TVS={'tv2':lambda tv,c,f:-2*f<=tv<=2*f,'tv1':lambda tv,c,f:abs(tv)<=1*f,'tv10pct':lambda tv,c,f:abs(tv)<=0.1*c} def day(fp): ix,ds=os.path.basename(fp)[:-8].split('_'); dt=pd.Timestamp(ds); s=SP.get((ix,dt)) if s is None or (ix,dt) not in SHL: return [],[],[] OPEN=DH[ix].open.get(dt,np.nan); OPEN=s[0] if np.isnan(OPEN) else OPEN; tr=trendo(s,OPEN) A,src=load(ix,dt); slip=0.5 if ix=='NIFTY' else 1.5 sc=DH['SENSEX'].open.get(dt,np.nan)/DH['NIFTY'].open.get(dt,np.nan) if ix=='SENSEX' else 1.0 sets=[('raw',1.0)]+([('scaled',sc)] if ix=='SENSEX' and not np.isnan(sc) else []) EV=[];RN=[];NEG=[] for sn,f in sets: Lv=20*f; ST={} for (typ,K),r in A.items(): c=r[3]; v=r[4]; first={k:None for k in TVS}; negseen=False for t in range(20,346): if np.isnan(c[t]) or np.isnan(s[t]): continue I=(s[t]-K) if typ=='CE' else (K-s[t]) if not (0.9*Lv<=I<=1.1*Lv and 0.8*Lv<=c[t]<=1.2*Lv) or (not np.isnan(v[t]) and v[t]<=0): continue tv=c[t]-I if tv<-2*f and not negseen: negseen=True; NEG.append(dict(ix=ix,date=dt,set=sn,typ=typ,K=K,t=t,tv=tv)) for k,fn in TVS.items(): if first[k] is None and fn(tv,c[t],f): first[k]=(t,tv,I) if TVS['tv2'](tv,c[t],f): ST.setdefault(typ,[]).append((t,K)) for k,x in first.items(): if x is None: continue t,tv,I=x; o=outcome(ix,dt,A,typ,K,t,slip,0.05*Lv) if o.get('status')!='ok': o.update(ix=ix,date=dt,set=sn,tvdef=k,typ=typ,K=K,t=t); EV.append(o); continue o['pnl_b'],o['why_b']=outb(ix,dt,r,t,slip,10*f); d=1 if typ=='CE' else -1 lab=tr[t]*(1 if typ=='PE' else -1); mode='counter' if lab==1 else 'with' if lab==-1 else 'neutral' o.update(spotctl(ix,dt,s,t,d,f,slip)); o.update({'o'+k:v for k,v in spotctl(ix,dt,s,t,-d,f,slip).items()}) o.update(ix=ix,date=dt,set=sn,tvdef=k,typ=typ,K=K,t=t,tv=tv,intr=I,spot=s[t],mode=mode,win=wof(t),src=src,f=f); EV.append(o) # R1 random: for primary trades (earliest per side), done in stats via these state lists -> simulate here prim={} for o in EV: if o['set']==sn and o['tvdef']=='tv2' and o.get('status')=='ok' and (o['typ'] not in prim or o['t']