import pandas as pd,numpy as np,matplotlib; matplotlib.use('Agg'); import matplotlib.pyplot as plt,sys sys.path.insert(0,'scripts'); from load import SESS R='results'; CH='charts'; plt.rcParams.update({'font.size':9,'figure.dpi':110}) D=pd.read_csv(f'{R}/daily_summary.csv'); c=pd.read_csv(f'{R}/contrib_daily_pts.csv',index_col=0) lab=[d[5:] for d in SESS] # 1 heatmap o=c.loc[c.abs().sum(1).sort_values(ascending=False).index] fig,ax=plt.subplots(figsize=(9,14)); v=np.nanmax(np.abs(o.values)); im=ax.imshow(o.values,cmap='RdYlGn',vmin=-v*0.7,vmax=v*0.7,aspect='auto') ax.set_xticks(range(len(SESS))); ax.set_xticklabels([f"{l}\n{D.n_chg[i]:+.0f}" for i,l in enumerate(lab)]); ax.set_yticks(range(len(o))); ax.set_yticklabels(o.index) for i in range(o.shape[0]): for j in range(o.shape[1]): if abs(o.values[i,j])>=3: ax.text(j,i,f"{o.values[i,j]:.0f}",ha='center',va='center',fontsize=7) ax.set_title('Nifty point contribution per stock per day (prev official close -> official close)\ncolumn header = Nifty change; implied weights (regression)'); plt.colorbar(im,ax=ax,shrink=0.4); plt.tight_layout(); plt.savefig(f'{CH}/heatmap_contrib.png'); plt.close() # 2 windows stacked w=pd.read_csv(f'{R}/window_recon.csv').pivot(index='date',columns='window',values='nifty_actual')[['gap','09:15-10:15','10:15-13:00','13:00-15:14','auction 15:15-close']] fig,ax=plt.subplots(figsize=(10,4.5)); bot_p=np.zeros(len(w)); bot_n=np.zeros(len(w)); cols=['#999','#d62728','#ff7f0e','#1f77b4','#9467bd'] for k,col in zip(w.columns,cols): vals=w[k].values; b=np.where(vals>=0,bot_p,bot_n); ax.bar(range(len(w)),vals,bottom=b,color=col,label=k); bot_p+=np.where(vals>=0,vals,0); bot_n+=np.where(vals<0,vals,0) ax.plot(range(len(w)),w.sum(1).values,'k*',ms=10,label='net day change'); ax.axhline(0,color='k',lw=.5) ax.set_xticks(range(len(w))); ax.set_xticklabels(lab); ax.set_ylabel('Nifty points'); ax.legend(fontsize=8,ncol=3); ax.set_title('Where in the day the points came from (gap / 3 windows / closing auction)') plt.tight_layout(); plt.savefig(f'{CH}/windows.png'); plt.close() # 3 intraday panels with bursts & volume tl=pd.read_csv(f'{R}/minute_timeline.csv'); br=pd.read_csv(f'{R}/bursts.csv'); sp=pd.read_csv(f'{R}/stock_volume_spikes.csv') fig,axs=plt.subplots(len(SESS),1,figsize=(11,3*len(SESS))) for ax,d in zip(axs,SESS): x=tl[tl.date==d].reset_index(drop=True); t=np.arange(len(x)) ax.plot(t,x.nifty,'k',lw=1); ax.set_ylabel('Nifty'); ax2=ax.twinx(); ax2.bar(t,x.fut_vol_ratio.clip(upper=10),color='tab:blue',alpha=.3,width=1); ax2.plot(t,x.cash_wvol_ratio.rolling(3).mean(),color='tab:orange',lw=.8); ax2.set_ylim(0,10); ax2.set_ylabel('vol / 20d same-minute') hm=list(x.hm) for _,b in br[br.date==d].iterrows(): a=hm.index(b.start); e=hm.index(b.end); ax.axvspan(a,e,color='green' if b.side=='BUY burst' else 'red',alpha=.25) ax.text(a,ax.get_ylim()[1],f"{b.fut_pts:+.0f}",fontsize=7,va='top',color='green' if b.side=='BUY burst' else 'red') s=sp[(sp.date==d)&(sp.pts.abs()>=1)] for _,r in s.iterrows(): if r.hm in hm: ax.plot(hm.index(r.hm),x.nifty[hm.index(r.hm)],'v' if r.pts<0 else '^',color='red' if r.pts<0 else 'green',ms=4) ax.set_xticks(range(0,len(x),45)); ax.set_xticklabels(hm[::45]); ax.set_title(f'{d} Nifty chg {D.set_index("date").n_chg[d]:+.1f}',fontsize=9,loc='left') plt.tight_layout(); plt.savefig(f'{CH}/intraday_timeline.png'); plt.close() # 4 players po=pd.read_csv(f'{R}/participant_oi.csv'); po=po[po.date.isin(SESS)] fig,axs=plt.subplots(3,1,figsize=(10,10)) ax=axs[0]; xx=np.arange(len(SESS)); ax.bar(xx-0.2,D.fii_cash_cr,0.4,label='FII cash net (cr)',color='tab:red'); ax.bar(xx+0.2,D.dii_cash_cr,0.4,label='DII cash net (cr)',color='tab:green'); ax.axhline(0,color='k',lw=.5) ax.set_xticks(xx); ax.set_xticklabels(lab); ax.legend(); ax.set_title('FII / DII provisional cash (NSE)') ax=axs[1] for i,cat in enumerate(['FII','Pro','Client','DII']): q=po[po.cat==cat].set_index('date').reindex(SESS); ax.bar(xx+(i-1.5)*0.2,q.fut_idx_net_chg,0.2,label=cat) ax.axhline(0,color='k',lw=.5); ax.set_xticks(xx); ax.set_xticklabels(lab); ax.legend(ncol=4); ax.set_title('Daily change in NET index-futures contracts (long-short), participant-wise OI') ax=axs[2]; q=po[po.cat=='FII'].set_index('date').reindex(SESS); ax.plot(xx,q.fut_idx_long_pct,'o-',label='FII index-fut long %'); ax.set_ylabel('FII long %'); ax3=ax.twinx(); ax3.plot(xx,D.n_close_official,'k--',label='Nifty close'); ax.set_xticks(xx); ax.set_xticklabels(lab); ax.legend(loc='upper left'); ax3.legend(loc='upper right'); ax.set_title('FII index-futures long share vs Nifty') plt.tight_layout(); plt.savefig(f'{CH}/players.png'); plt.close() # 5 breadth mb=pd.read_csv(f'{R}/market_breadth.csv').set_index('date').reindex(SESS) fig,ax=plt.subplots(figsize=(10,3.8)); ax.bar(xx-0.2,D.n_chg_pct,0.4,label='Nifty 50 %'); ax.bar(xx+0.2,mb.median_chg_pct,0.4,label='Median NSE EQ stock %'); ax.axhline(0,color='k',lw=.5) for i in xx: ax.text(i+0.2,min(mb.median_chg_pct.iloc[i],0)-0.25,f"{mb.n_down_gt3pct.iloc[i]}↓>3%",ha='center',fontsize=7) ax.set_xticks(xx); ax.set_xticklabels(lab); ax.legend(); ax.set_title('Index vs broad market (NSE security-wise bhavcopy, EQ series)'); plt.tight_layout(); plt.savefig(f'{CH}/breadth.png'); plt.close() # 6 spike timeline scatter fig,ax=plt.subplots(figsize=(11,4.5)); s=sp[sp.pts.abs()>=1] tm=pd.to_datetime(s.hm,format='%H:%M'); mins=(tm.dt.hour*60+tm.dt.minute)-555 ax.scatter(mins,s.date.map({d:i for i,d in enumerate(SESS)}),s=np.clip(s.pts.abs()*15,5,300),c=np.where(s.pts<0,'red','green'),alpha=.5) for k,(_,r) in enumerate(s[s.pts.abs()>=5].iterrows()): ax.text((int(r.hm[:2])*60+int(r.hm[3:]))-555,SESS.index(r.date)+0.15+0.18*(k%2),r.sym,fontsize=6) ax.set_yticks(range(len(SESS))); ax.set_yticklabels(SESS); ax.set_xticks(range(0,361,45)); ax.set_xticklabels([f"{(555+m)//60:02d}:{(555+m)%60:02d}" for m in range(0,361,45)]) ax.set_title('Stock 1-minute volume spikes (>=5x own 20-day same-minute avg) — size = Nifty points moved in that minute, red = down'); plt.tight_layout(); plt.savefig(f'{CH}/spike_timeline.png'); plt.close() # 7 options walls st=pd.read_csv(f'{R}/nifty_options_strikes.csv') fig,axs=plt.subplots(3,3,figsize=(12,9),sharey=False) for ax,d in zip(axs.flat,SESS): q=st[st.date==d]; ax.barh(q.strike-15,q.ce_oi_lots/1e3,height=30,color='tab:red',label='CE OI'); ax.barh(q.strike+15,q.pe_oi_lots/1e3,height=30,color='tab:green',label='PE OI') ax.axhline(D.set_index('date').n_close_official[d],color='k',lw=.8); ax.set_title(f"{d} exp {q.expiry.iloc[0][5:]}",fontsize=8); ax.tick_params(labelsize=7) axs[0,0].legend(fontsize=7); fig.suptitle('Nifty near-expiry OI by strike (thousand lots); black line = close'); plt.tight_layout(); plt.savefig(f'{CH}/oi_walls.png'); plt.close() print('charts ok')