import pandas as pd,numpy as np,html,json,datetime as dt,sys sys.path.insert(0,'scripts'); from load import SESS R='results'; E=html.escape D=pd.read_csv(f'{R}/daily_summary.csv').set_index('date'); C=pd.read_csv(f'{R}/contrib_daily_pts.csv',index_col=0) F=pd.read_csv(f'{R}/stock_day_flow.csv'); BR=pd.read_csv(f'{R}/bursts.csv'); SW=pd.read_csv(f'{R}/swing_legs.csv'); WN=pd.read_csv(f'{R}/window_recon.csv') PO=pd.read_csv(f'{R}/participant_oi.csv'); MB=pd.read_csv(f'{R}/market_breadth.csv').set_index('date'); W=pd.read_csv('data/implied_weights.csv',index_col=0) def tbl(df,fmt=None,idx=True): return df.to_html(index=idx,border=0,float_format=(fmt or (lambda x:f'{x:,.1f}')),na_rep='—',escape=True) def top(d,n=5,asc=True): x=F[F.date==d].set_index('sym'); s=C[d].sort_values(ascending=asc).head(n) return ', '.join(f"{k} {v:+.1f} ({x.chg_pct[k]:+.1f}%, dlv {x.DELIV_PER[k]:.0f}% vs {x.DELIV_PER_20d[k]:.0f})" for k,v in s.items()) import zoneinfo; built=dt.datetime.now(zoneinfo.ZoneInfo('Asia/Kolkata')).strftime('%Y-%m-%d %H:%M') # ---------- per-day summaries (facts auto, interpretation hand-written) ---------- INTERP={ '2026-10-12':"Gap-up (+73) on Trump's Russia–Ukraine 'energy ceasefire' and RBI rupee steps was sold from the first minute (high 09:15, low 15:10, −347 peak-to-trough). Broad-based: 36 of 50 Nifty stocks fell; RELIANCE, HDFCBANK, LT, ICICIBANK, BHARTIARTL did ~150 of the 321-pt fall. Futures: long unwinding (OI down, price down) — longs exiting rather than aggressive fresh shorts; clients bought +13.4k net index-futures contracts into the fall, Pros sold −13.8k.", '2026-10-13':"'Heavy buying' day #1: +359, closed at the day high (15:12 high, then auction). Catalysts: IT rally on results in the morning (HCLTECH +8.4% on Q2, TCS +6.8%, INFY +4.1%; Nifty 22,321 → 22,566 by 10:00), then FM Sitharaman's LTCG/STT remarks at the Bloomberg New Economy Forum in the afternoon (first headlines 14:25 IST; Nifty 22,553 at 14:00 → 22,700 at 15:14). IT and HDFCBANK/ICICIBANK supplied ~126 pts. Futures OI fell while price rose = short covering; FIIs cut 3.2k index-futures shorts and added 3.1k longs (net +6.4k), clients sold −13.1k. FIIs still sold ₹1,305 cr cash. HDFCBANK/ICICIBANK cash volume was only 0.6x normal — the rally was futures/short-covering led, not heavy delivery buying.", '2026-10-14':"Next-day reversal: −99 with short buildup (futures OI +2.3k contracts, price −186). FIIs added 6.1k index-futures shorts (net −7.2k), clients bought +15.5k. ICICIBANK (−33 pts), BAJFINANCE, M&M, SHRIRAMFIN led; IT kept rising (INFY +20). Delivery was normal (59.7% vs 59.1%).", '2026-10-15':"'Heavy buying' day #2: +375 on the Jio IPO price band (RIL +3.4%) plus banks (ICICIBANK +79, RIL +57, HDFCBANK +53, BHARTIARTL +39 pts). Futures OI −19.7k contracts with price up = the biggest short-covering day of the period; FIIs covered 12.6k index-futures shorts (net +16.9k) while selling ₹5,285 cr in cash; clients sold −26.0k. Broad market did not join: median NSE stock −0.7%, 1,755 decliners. NESTLEIND −7.8% after results.", '2026-10-16':"+149, still short covering (OI −2.7k). Unusual cash flow: FII +₹1,166 cr, DII −₹3,661 cr. BHARTIARTL +2.8% on 4.2x volume and 81% delivery (delivery value ₹3,891 cr vs ₹862 cr normal — consistent with a block trade, not verified); TECHM +8.5% after results/bonus. Highest index-weighted delivery of the period (61.5%).", '2026-10-19':"'Next-day heavy selling' after the two short-covering days: −257, high at 09:18, low 13:47 (−330). Driven by bank Q2 results over the weekend: HDFCBANK −2.3% (record-low margins, deputy MD exit) −56 pts, AXISBANK −4.2% −33, ICICIBANK −25 (2.6x volume). 09:24–09:28 was the single biggest burst (−150 pts in 5 min). Long unwinding in futures; FIIs added 3.6k shorts and cut 3.3k longs (net −6.9k), clients bought +10.9k. Delivery was the lowest of the period (48% vs 59%) — mostly intraday/derivative selling, not delivery dumping.", '2026-10-21':"Jio IPO day 1. Gap-up +127 (RIL, IT, Asia) to 23,121 at 09:40, then a 471-pt slide to 22,650 at 14:47 in a series of 40–55 pt futures sell bursts every ~30 min (10:02, 11:06, 11:18, 11:38, 12:11, 13:44). Financials did 176 of the 453-pt fall (HDFCBANK −49, ICICIBANK −34), RIL gave back −41 from its high, BAJFINANCE −3.3% after results. Futures: long unwinding (OI −7.5k); FIIs cut both longs (−4.1k) and shorts (−6.4k); FII cash +₹1,022 cr, DII +₹1,614 cr. Broad market far worse than Nifty: median stock −2.2%, 968 stocks down >3%, breadth 337/2,338.", '2026-10-22':"Gap-down −124 to 22,555 low (09:35) on Saudi attacks / US diplomats leaving Saudi / oil. Intraday it was two-way (buy bursts +98 at 10:19, +87 at 12:50; sell −77 at 11:42 with 11 stocks at ≥3x volume). Short buildup: futures OI +13.9k contracts (largest add of the period); FIIs added 4.8k shorts; FII cash −₹3,459 cr, DII +₹2,891 cr. HDFCBANK −1.8% on 2.1x volume and delivery value ₹2,486 cr (1.9x normal) = real delivery selling; RIL −2.0% but on low delivery (33% vs 58%) = churn. Also BSE Sensex weekly expiry with closing-auction (CAS) swings reported.", '2026-10-23':"Friday: Brent ~$113–114 (Houthi attacks on Saudi, Aramco HQ evacuation reports). Open 22,742 → 22,372 at 12:51 (−415): first hour alone −238 pts; IT (−61), RIL (−31), BHARTIARTL (−31), ICICIBANK (−27) led the fall. 13:38–13:42 the biggest buy burst of the period: +137 futures pts on 8.7x futures volume with 16 Nifty stocks at ≥3x volume (no confirmed news catalyst — futures-led spike; nearest event: FM chaired the 30th FSDC meeting ~12:16–13:28 IST, no market-moving remark found; the 13:55 'Finance Minister's tax comments' headline was a repost of the 13-Oct story) — immediately followed by a −64 sell burst at 13:50. Close via auction +83 above 15:14. Day = short buildup (OI +4.0k); FII cash +₹888 cr, DII +₹3,235 cr; VIX 16.9 (period high). Broad market: median stock −2.4%, 1,056 stocks down >3%.", } BIG=['2026-10-12','2026-10-19','2026-10-21','2026-10-22','2026-10-23']; HB=['2026-10-13','2026-10-15','2026-10-16'] def card(d): r=D.loc[d]; mb=MB.loc[d] facts=(f"Nifty O/H/L/C {r.n_open:,.0f}/{r.n_high:,.0f}/{r.n_low:,.0f}/{r.n_close_official:,.2f} ({r.n_chg:+.1f}, {r.n_chg_pct:+.2f}%), range {r.n_range:.0f} (high {r.n_hi_time}, low {r.n_lo_time}); Bank Nifty {r.bn_chg:+.0f} ({r.bn_chg_pct:+.2f}%). " f"FII cash ₹{r.fii_cash_cr:+,.0f} cr, DII ₹{r.dii_cash_cr:+,.0f} cr. Nifty futures (all expiries) OI {r.nf_oi_chg_contracts:+,.0f} contracts, price {r.nf_px_chg:+.0f} → {r.nf_buildup}; FII index-fut long {r.fii_idxfut_long_chg:+,.0f} / short {r.fii_idxfut_short_chg:+,.0f} (long share {r.fii_idxfut_long_pct:.1f}%). " f"Index-weighted delivery {r.w_deliv_pct:.1f}% (20d avg {r.w_deliv_pct_20d:.1f}%). Breadth NSE {int(mb.adv)}/{int(mb.dec)}.") return f"

{d} ({pd.Timestamp(d).strftime('%a')}) — Nifty {r.n_chg:+.0f}

Top 5 draggers (pts): {top(d)}
Top supporters: {top(d,3,False)}

Facts: {facts}

Reading: {INTERP[d]}

" # ---------- tables ---------- dt1=D[['n_open','n_high','n_low','n_1514','n_close_official','auction_jump','n_chg','n_range','n_gap','n_hi_time','n_lo_time','bn_close','bn_chg','vix']].copy() dt1.columns=['Open','High','Low','15:14 (last real)','Official close','Auction jump','Chg','Range','Gap','High @','Low @','BankNifty','BN chg','VIX'] ft=D[['nf_oi_contracts','nf_oi_chg_contracts','nf_px_chg','nf_vol_contracts','nf_basis_near','nf_buildup','bnf_oi_chg_contracts','bnf_px_chg','bnf_buildup']].copy() ft.columns=['NF OI (contracts)','NF OI chg','NF px chg','NF vol (contracts)','NF basis (near−spot)','NF buildup','BNF OI chg','BNF px chg','BNF buildup'] pl=D[['fii_cash_cr','dii_cash_cr','fii_idxfut_net_cr','fii_idxopt_net_cr','fii_stkfut_net_cr','fii_idxfut_long_chg','fii_idxfut_short_chg','fii_idxfut_net_chg','fii_idxfut_long_pct','pro_idxfut_net_chg','client_idxfut_net_chg','dii_idxfut_net_chg']].copy() pl.columns=['FII cash','DII cash','FII idx-fut net buy (cr)','FII idx-opt net buy (cr)','FII stk-fut net buy (cr)','FII idx-fut long chg','FII idx-fut short chg','FII net chg','FII long %','Pro net chg','Client net chg','DII net chg'] po2=PO[PO.date.isin(SESS)].pivot(index='date',columns='cat',values=['opt_net_call_chg','opt_net_put_chg']) po2.columns=[f'{a.replace("opt_net_","").replace("_chg","")} {b}' for a,b in po2.columns] op=D[['expiry','atm','atm_iv_near','atm_iv_oct27','vix','pcr_near','pcr_all','max_ce_oi_strike','max_ce_oi_lots','max_pe_oi_strike','max_pe_oi_lots','top_ce_add','top_ce_add_lots','top_pe_add','top_pe_add_lots','ce_oi_chg_lots','pe_oi_chg_lots']].copy() op.columns=['Near expiry','ATM','ATM IV near %','ATM IV 27-Oct %','VIX','PCR near','PCR all','Max CE OI strike','lots','Max PE OI strike','lots ','Top CE add','lots ','Top PE add','lots ','CE OI chg (lots)','PE OI chg (lots)'] fl=D[['w_vol_ratio','w_upvol_share','w_close_vs_vwap','w_deliv_pct','w_deliv_pct_20d','deliv_val_cr','deliv_val_cr_20d','turnover_cr','turnover_cr_20d','n_adv','n_dec']].copy() fl.columns=['Vol vs 20d (wtd)','Up-minute vol share (wtd)','15:14 vs VWAP % (wtd)','Delivery % (wtd)','Delivery % 20d','Nifty50 delivery ₹cr','20d','Nifty50 turnover ₹cr','20d ','Nifty50 adv','dec'] mb=MB.loc[SESS,['turnover_cr','turnover_cr_20d','deliv_val_cr','deliv_val_cr_20d','adv','dec','median_chg_pct','n_down_gt3pct']].copy(); mb.insert(0,'Nifty %',D.n_chg_pct) wn=WN.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']] # per-window top draggers WL=pd.read_csv(f'{R}/contrib_windows_long.csv'); WL=WL[WL.sym!='NIFTY_ACTUAL'] wtop=[] for d in SESS: for w in ['09:15-10:15','10:15-13:00','13:00-15:14']: x=WL[(WL.date==d)&(WL.window==w)].set_index('sym').pts.sort_values() wtop.append(dict(date=d,window=w,nifty=wn.loc[d,w],draggers=', '.join(f'{k} {v:+.1f}' for k,v in x.head(4).items()),supporters=', '.join(f'{k} {v:+.1f}' for k,v in x.tail(3)[::-1].items()))) wtop=pd.DataFrame(wtop).set_index(['date','window']) sw=SW.set_index(['date','leg'])[['start','end','peak_to_trough','sum_components','banks_fin','reliance','it','top5']] br=BR.copy(); br['fut_oi_chg_contracts']=(br.fut_oi_chg_units/65).round(0); br=br.drop(columns=['fut_oi_chg_units']); br.loc[br.fut_oi_chg_contracts.isna(),'classify']='n/a (includes open)' br=br.set_index(['date','start']) # big day stock tables def bigtab(d): x=F[F.date==d].set_index('sym').loc[C[d].abs().sort_values(ascending=False).index[:12],['contrib_pts','chg_pct','vol_ratio_20d','upvol_share','close_vs_vwap_pct','DELIV_PER','DELIV_PER_20d','deliv_val_cr','deliv_val_cr_20d','max_ratio','max_ratio_hm']] x.columns=['Nifty pts','Chg %','Vol vs 20d','Up-vol share','15:14 vs VWAP %','Deliv %','Deliv % 20d','Deliv ₹cr','Deliv ₹cr 20d','Max 1m vol ratio','at'] return tbl(x,lambda v:f'{v:,.2f}') gaps=["Holidays: 2026-10-02 (Gandhi Jayanti) and 2026-10-20 — no session; NSE archive URLs for those dates serve the previous day's file (filtered out by DATE1).", "Spot Nifty / Bank Nifty and all 50 cash stocks: 15:15–15:29 bars are frozen by the NSE closing auction (since 2026-08-03) and are treated as MISSING; last real minute = 15:14. Official close taken from Upstox day candles; the 15:14→official-close move is shown separately as 'auction'.", "Upstox 1-minute futures volume undercounts the day candle on 22-Oct (Nifty fut 76%, Bank Nifty fut 87% of the day total) and 23-Oct (72% / 55%); all other days ≈100%. Futures 1m volume ratios on those two days are therefore understated (conservative). Cash-stock 1m volume ≈100% of day volume except a few names on 22/23-Oct (min 55%; see results/volume_coverage_check.csv). Not filled.", "Upstox intraday futures OI is lagged/partial (first bar ≈ previous day's official OI; the official EOD OI only appears next morning). Burst-level 'short covering / fresh longs' labels use Oct+Nov futures 1m OI and are INDICATIVE only; day-level buildup uses official NSE F&O bhavcopy OI (all expiries).", "Nifty weights: NSE's weightage file was not accessible (NSE API 404). Weights are regression-implied: NNLS of 1-minute Nifty changes on the 50 stocks' 1-minute price changes, 1–23 Oct (5,385 minutes), R² 0.9985, implied weights sum to 99.9%. Daily stock contributions reconcile to the actual Nifty change within ±1.5 pts every day.", "FII/DII cash = NSE provisional figures captured live by the local macro feed (fiidiiTradeReact). Participant-wise OI/volume, FII derivative stats, delivery and F&O bhavcopy = NSE public archives. No paid sources. 20-day baselines use the 20 sessions before each day (from 2026-09-08).", "Jio IPO amounts: the local news archive reports issue size ₹30,213 cr and total demand ₹3.73 lakh cr after day 2 (5.5x); the final-day (23-Oct) total and the '₹1.76 lakh cr liquidity' figure in the brief were not found in the archive and are not used.", "Options IV = Black-76 on the synthetic forward (put–call parity at ATM) from NSE bhavcopy closes; 12-Oct 'near' expiry is 13-Oct (1 day) so its near IV is noisy; 19-Oct's own expiry is skipped (next = 27-Oct)."] css="""body{font-family:system-ui,-apple-system,Segoe UI,sans-serif;margin:0 auto;max-width:1250px;padding:20px;color:#1b1f24;line-height:1.45} h1{font-size:1.55em}h2{margin-top:1.8em;border-bottom:1px solid #ddd;padding-bottom:4px}h3{margin:.2em 0}table{border-collapse:collapse;font-size:12px;margin:8px 0;display:block;overflow-x:auto} th,td{border:1px solid #d6d9de;padding:3px 6px;text-align:right;white-space:nowrap}th{background:#f2f4f7}td:first-child,th:first-child{text-align:left} .card{border:1px solid #d6d9de;border-left:6px solid #c62828;padding:8px 14px;margin:10px 0;border-radius:4px}.card.up{border-left-color:#2e7d32}.fact{color:#333;font-size:.93em;background:#fafbfc;padding:6px} .verdict{background:#fff8e1;border-left:6px solid #f9a825;padding:12px 16px;margin:12px 0}img{max-width:100%;border:1px solid #eee}.note{color:#555;font-size:.92em}code{background:#f4f4f4;padding:1px 4px} td.wrap{white-space:normal;text-align:left;min-width:300px}""" H=[f"Nifty flow forensics: who sold, who bought — 12–23 Oct 2026", "

Nifty flow forensics, 12–23 Oct 2026: what actually happened on the 300-point falls and the buy-then-sell days

", "
Correction (25-Oct-2026 08:30 IST): an earlier version attributed the 23-Oct 13:38 +137 buy burst (and the recovery from the 12:51 low) to 'Finance Minister's tax comments'. That was wrong: Sitharaman's LTCG/STT remarks were made on Tue 13-Oct-2026 at the Bloomberg New Economy Forum (Nifty +358.6 / Sensex +1,109 that day; ET, Indian Express). The 23-Oct 13:55 headline (INDIA New England News) is a repost of the 13-Oct story — the same item appears in our archive at 13-Oct 21:22, 21-Oct 10:49, 22-Oct 04:14 and 23-Oct 13:55. The 23-Oct burst now reads: no confirmed news catalyst, futures-led spike (8.7x futures volume); nearest event: FM chaired the 30th FSDC meeting ~12:16–13:28 IST, no market-moving remark found. The 13-Oct card now lists the FM remarks (afternoon) and the IT rally (HCL Tech +8% on results, TCS +6%) as catalysts. News matching now ignores headlines whose quoted index move does not match the actual Nifty move and keeps only the first copy of a reposted headline. No numbers changed. Added 25-Oct 08:45 IST: section 9: who bought and who sold in the 23-Oct burst and the 13-Oct rally.
", f"

Built {built} IST. Research only, not advice; read-only data work, no orders. 9 sessions (20-Oct holiday). Sources: Upstox historical candles (1-min + day; 50 Nifty stocks, Nifty, Bank Nifty, Nifty/Bank Nifty futures, VIX), NSE public archives (security-wise delivery, F&O UDiFF bhavcopy, participant-wise OI, FII derivative stats), NSE provisional FII/DII cash (local feed), local news archive. Sample = 9 sessions: everything below is descriptive, not a tested edge.

", "

Plain-language summary

Short version. The 'heavy buying' days (13-Oct +359, 15-Oct +375, 16-Oct +149) were short covering by FIIs in index futures (Nifty futures OI fell each day while price rose; FIIs cut 3.2k, 12.6k and 5.4k index-futures shorts), with retail clients selling into the rally and FIIs still selling cash on 13/15-Oct. The following sell days (14-Oct, 19-Oct, 22-Oct, 23-Oct) saw FIIs re-add shorts (short buildup on 14, 22, 23-Oct; long unwinding on 12, 19, 21-Oct) while clients bought the dips. FIIs stayed ~89–91% short in index futures the whole fortnight, and their long share rose and fell with Nifty — i.e. the swings were mostly a heavily-short FII book covering and re-shorting, not fresh long money arriving. Most intraday 'heavy' bursts were futures-led and concentrated in 4–5 heavyweights (HDFCBANK, ICICIBANK, RELIANCE, BHARTIARTL, INFY); cash volume in those stocks was often near normal. The Jio IPO window (21–23 Oct) coincided with a broad-market sell-off far worse than Nifty (median NSE stock −2.2% and −2.4% on 21 and 23-Oct, ~1,000 stocks down >3%), but Nifty-50 delivery value was below its 20-day average and Reliance's 22-Oct drop was on low delivery — so there is no evidence in this data of heavyweights being dumped to fund IPO bids; any IPO-funding effect shows up in mid/small caps (interpretation).
", "

New (25-Oct): Buying at the lows — what happened at each intraday bottom 12–23 Oct, and whether 'heavy buying at the low' is tradable for an option buyer (verdict: FAIL).

", "

Recurring patterns (descriptive, n=9)

", "

Day-by-day: big down days

"]+[card(d) for d in BIG]+["

Day-by-day: the 'heavy buying' days and the day after

"]+[card(d).replace('class=card','class="card up"') for d in HB]+[card('2026-10-14')]+[ "

1. Index, futures and Bank Nifty (official)

",tbl(dt1,lambda v:f'{v:,.2f}'),"

Auction jump = official close − 15:14 last real print. Buildup rule: price↑OI↑ long buildup; price↓OI↑ short buildup; price↑OI↓ short covering; price↓OI↓ long unwinding (OI summed over all expiries, so Oct→Nov rollover nets out).

",tbl(ft,lambda v:f'{v:,.1f}'), "

2. Stock contribution to the Nifty move

Points = implied pts-per-₹ × (official close − previous official close). Sum vs actual Nifty change: residual within ±1.5 pts every day. Implied weights: top 10 "+', '.join(f"{k} {v:.1f}%" for k,v in W.implied_weight_pct.head(10).items())+" (full list: implied_weights.csv).

", "

Where in the day (gap / windows / auction)

",tbl(wn),"

Top draggers / supporters per window

",wtop.to_html(border=0,float_format=lambda v:f'{v:+.1f}'), "

The main fall and the rebound after the low (peak-to-trough, real minutes only)

",tbl(sw,lambda v:f'{v:+.1f}'), "

3. Volume forensics

Per panel: black = Nifty spot (to 15:14); blue bars = Nifty futures 1m volume ÷ its own 20-day same-minute average (capped 10); orange = index-weighted cash volume ratio of the 50 stocks; shaded = 5-minute futures bursts (|move| ≥40 pts & avg vol ratio ≥2x; green buy, red sell; label = futures pts); triangles = single-stock 1m volume spikes ≥5x that moved Nifty ≥1 pt.

", "

Futures bursts (5-minute) — who moved the index

",tbl(br,lambda v:f'{v:,.1f}'),"

classify = sign of Oct+Nov futures OI change over the burst from Upstox 1m OI (lagged → indicative only). top5 = stock contributions (Nifty pts) in the burst; volratio = those stocks' cash volume vs 20-day same-minute avg.

", "", "

Buy/sell pressure and delivery (index-weighted, Nifty 50)

",tbl(fl,lambda v:f'{v:,.2f}'),"

Up-minute vol share = volume on minutes closing above the previous minute ÷ (up+down) volume, 09:15–15:14. Delivery % from NSE sec_bhavdata_full (EQ series).

", "

Biggest movers on each big day: contribution, volume, delivery

"]+[f"

{d}

"+bigtab(d) for d in BIG+HB]+[ "

4. Players: FII/DII cash, participant-wise OI, options

",tbl(pl,lambda v:f'{v:,.1f}'), "

Participant columns = change in contracts (NSE fao_participant_oi). FII derivative ₹cr = buy − sell from NSE fii_stats.

Index options: net long calls / puts change by participant (contracts)

",tbl(po2,lambda v:f'{v:+,.0f}'), "

Nifty options: IV, PCR, OI walls

",tbl(op,lambda v:f'{v:,.2f}'),"", "

5. Context: broad market, Jio IPO, news

",tbl(mb,lambda v:f'{v:,.1f}'), "

Jio IPO check (facts): RELIANCE on 21/22/23-Oct: "+'; '.join(f"{d[5:]} {F[(F.sym=='RELIANCE')&(F.date==d)].chg_pct.iloc[0]:+.2f}%, vol {F[(F.sym=='RELIANCE')&(F.date==d)].vol_ratio_20d.iloc[0]:.2f}x, delivery {F[(F.sym=='RELIANCE')&(F.date==d)].DELIV_PER.iloc[0]:.0f}% (20d {F[(F.sym=='RELIANCE')&(F.date==d)].DELIV_PER_20d.iloc[0]:.0f}%)" for d in ['2026-10-21','2026-10-22','2026-10-23'])+ ". Nifty-50 delivery value 21–23 Oct ₹"+', '.join(f"{D.deliv_val_cr[d]:,.0f}" for d in ['2026-10-21','2026-10-22','2026-10-23'])+" cr vs 20-day avg ₹"+', '.join(f"{D.deliv_val_cr_20d[d]:,.0f}" for d in ['2026-10-21','2026-10-22','2026-10-23'])+" cr (below normal). Whole-NSE EQ turnover on 23-Oct ₹1.22 lakh cr vs ₹1.12 lakh cr 20-day avg (+9%). Headline 23-Oct: 'Banking liquidity surplus shrinks to Rs 541 crore as cash crunch increases'. Jio allotment Mon 26-Oct, refunds Tue 27-Oct (per brief) — if IPO-bid funding caused the small/mid-cap selling, refunds could reverse some of it; that is a hypothesis, untested.

", "

Key catalysts per session (local news archive, IST)

"] CAT={'2026-10-12':"Trump 'energy ceasefire' Russia–Ukraine → oil eases; RBI rupee/forex-derivative curbs (weekend); Houthi attacks on Saudi; 'IT, telecom decline as selloff resumes amid FII outflows'; India Sept CPI near RBI ceiling (17:51).", '2026-10-13':"Asia AI/chip sell-off (Nikkei −2%) but India rebounds on IT (HCL Tech Q2 +8%, TCS +6%) + HDFC Bank; afternoon: FM Sitharaman at Bloomberg New Economy Forum says open to views on LTCG/STT (14:25+ headlines) — 'Sensex jumps 1,109 points' (close; Nifty +358.6). Sources: ET, Indian Express.", '2026-10-14':"Oil up again on US–Iran/Iraq strikes; 'Gulf oil production rebounds'; IT keeps rallying.", '2026-10-15':"Jio Platforms IPO price band (₹30,213 cr, 21–23 Oct) → RIL +3%; US Sept CPI hot; WPI 11.4%; 'Short-covering rally may take Nifty to 23,000–23,150' (07:48); Nestle Q2 (−8%), TechM Q2 after close.", '2026-10-16':"TechM bonus/results; Wipro, Jio Financial in focus; FII net buyers, DII net sellers.", '2026-10-19':"Weekend bank Q2: HDFC Bank margins record low + deputy MD exit, Axis misses, ICICI beats; 'Crude tops $100'; 'Sensex crashes 900 pts… private banks lead'.", '2026-10-21':"Jio IPO opens, fully subscribed in ~100 min, 3.16x day 1 (~₹70k cr bids); Bajaj Finance −3% post Q2 margin warning; 'Sensex crashes 1,350 pts from day's high'; VIX +8%.", '2026-10-22':"US orders diplomats to leave Saudi Arabia; 'Oil jumps $2'; 7 tankers hit in Hormuz; Jio IPO 5.57x, ₹3.73 lakh cr demand; FIIs sell ₹3,459 cr; Sensex weekly expiry closing-auction swings ('CAS chaos'); RBI hike headline (20:55).", '2026-10-23':"Brent $113–114 (5-month high), Houthi attacks on Saudi, Aramco HQ evacuation report (12:31); US Nasdaq −2.5% overnight (AI doubts); midcap/smallcap −4%; FM chaired the 30th FSDC meeting (~12:16–13:28 IST; no market-moving remark found) — the 13:55 'Sensex jumps over 1,100 pts as Finance Minister's tax comments…' item (INDIA New England News) is a repost of the 13-Oct story, not 23-Oct news; Jio IPO final day; banking liquidity surplus ₹541 cr."} for d in SESS: H.append(f"") H+=["
SessionCatalysts
{d}{E(CAT[d])}

Full keyword-filtered headline list: news_by_session.csv. Headlines are reported as published; not independently verified.

", "

6. Data gaps, methods and caveats

", "

Facts vs interpretation

Facts = every number in the tables (prices, OI, participant contracts, FII/DII, delivery, volume ratios). Interpretation = the 'Reading' lines, the word 'short covering' for a whole day (it is the standard price/OI rule, which cannot separate who closed), the IPO-funding link to small-cap selling, and the block-trade guess for BHARTIARTL on 16-Oct. With 9 sessions none of the patterns is statistically tested; treat them as a description of this fortnight only.

", (lambda p:(lambda t:t.replace('',''))(open(p).read()) if __import__('os').path.exists(p) else '')('lows/section_lows.html'), (lambda p:(lambda t:t.replace('',''))(open(p).read()) if __import__('os').path.exists(p) else '')('whoflow/section_whoflow.html'), "

Files

All CSVs in results/: daily_summary, contrib_daily_pts, contrib_windows_long, window_recon, swing_legs, bursts, stock_volume_spikes, stock_day_flow (per stock per day: volume ratio, up-vol share, VWAP, delivery), minute_timeline, participant_oi, fii_deriv_stats, nifty_options_daily, nifty_options_strikes, market_breadth, volume_coverage_check, news_by_session. Scripts: scripts/.

"] open('index.html','w').write('\n'.join(H)); print('ok',len('\n'.join(H)))