# YouTube-calls section for gen_page.py (exec'd); builds YT_HTML import pandas as pd,json,html RSY=f'{L}/results' YS=pd.read_csv(f'{RSY}/yt_summary.csv').iloc[0]; YC=pd.read_csv(f'{RSY}/yt_calls_scored.csv'); YG=pd.read_csv(f'{RSY}/yt_by_group.csv'); YL=pd.read_csv(f'{RSY}/yt_vs_selflog.csv') YI=pd.read_csv(f'{RSY}/yt_stream_inventory.csv'); YD=pd.read_csv(f'{RSY}/yt_trading_day_coverage.csv'); YM=json.load(open(f'{RSY}/yt_disc_model.json')); YF=pd.read_csv(f'{RSY}/yt_disc_feature_contrast.csv'); YT=pd.read_csv(f'{RSY}/yt_disc_taken_vs_skipped.csv') if __import__('os').path.exists(f'{RSY}/yt_disc_taken_vs_skipped.csv') else None nos=YD[YD.flag.fillna('').str.startswith('NO_STREAM')].date.tolist(); part=int(YD.flag.fillna('').str.startswith('PARTIAL').sum()) sc=YC[YC.status=='scored'].copy(); sc['stream']=[f"{d} {t}" for u,d,t in zip(sc.url,sc.date,sc.entry_ist.str[11:16])] rows=''.join(f"
| Stream time (IST, links to the original stream at that second) | Contract | SL / target pts (*=fallback) | Entry bar @ price | Exit | Net pts | His stated outcome | Setup |
|---|
Added after Satya's 23:15 IST (26-Oct) request. Source: the trader's public live streams at youtube.com/@KarolSEBIRegisteredIITian/streams. We read stream metadata and Hindi auto-captions with yt-dlp, with no login, cookies or credentials. 360p two-second clips were used only to read the strike label on screen, then deleted. No video is embedded or redistributed; the links below go to the original streams. Design pre-registered at 23:40 IST in PREREG.md (YOUTUBE-CALLS), before any call was scored. Research only, not advice.
{len(YI)} past live streams, {YI.start_ist.min()[:16]} to {YI.start_ist.max()[:16]} IST ({YI.duration_s.sum()/3600:.0f} hours). All have Hindi auto-captions. Over the {len(YD)} trading days from 06-May to 23-Oct-2026: {int((YD.flag.isna()).sum())} days have full market-hours coverage, {part} partial (<80% of 09:15–15:30), and {len(nos)} have no stream ({', '.join(d[5:] for d in nos)}). Some may have been deleted or never streamed; we cannot tell which. Files: yt_stream_inventory.csv · yt_trading_day_coverage.csv.
289 caption-rule candidates → 110 dropped as promo/gold/crypto talk → 179 reviewed → 58 fresh calls. The other 121 were retrospective, commentary, vague, or conditional plans with no activation. Of the 58: 29 scored, 13 not scorable (Sensex after 05-Oct, no real bars), 9 strike unreadable, 7 side not stated. That is about 1.9 extractable calls per session, against the ~10 per day in his self-reported log.
{CT}Entry = open of the next 1m bar after the call minute, +0.5 slippage. SL/target are from his spoken points (fallback SL 12 Nifty / 20 Sensex, target 2×SL, marked *). Same-bar SL+target counts as SL. Time exit 15:15. −0.5 slippage at exit plus Rs20/order, STT 0.15%, exchange, SEBI, stamp and GST (Nifty lot 65, Sensex 20). Nifty and Sensex points are different sizes (Sensex premiums are roughly 3× Nifty), so the pooled mean is only indicative. Before charges: {sc.gross_pts.mean():+.1f} per trade. With target forced to 2×SL: {sc.net_1to2.mean():+.1f}.
His stated outcomes are the first “target done/touched” or “SL hit” phrase within 40 minutes of the call. They agree with real bars on {(cl.claim==cl.real).mean()*100:.0f}% of the {len(cl)} scored calls where he stated one. A stated “target done” was a real target hit {nTT} of {nT} times. By stated outcome: “target” calls {G.set_index('group').loc['T','pts']:+.1f} per trade (n={int(G.set_index('group').loc['T','n'])}), “SL” calls {G.set_index('group').loc['SL','pts']:+.1f} (n={int(G.set_index('group').loc['SL','n'])}), no claim {G.set_index('group').loc['no_claim','pts']:+.1f} (n={int(G.set_index('group').loc['no_claim','n'])}).
The log covers only 6 dates in this window. On 25-Sep there was no stream, yet the log shows {len(S25)} trades for {S25.result_pts.sum():+.0f} pts. On 05-Oct the log's strikes (Nifty 24800CE, Sensex 79500) are 2,200 Nifty and 7,300 Sensex points away from that day's market (spot ≈22,580 / ≈72,200). On 01-Sep the log has {int(ovs.set_index('date').loc['2026-09-01','log_rows'])} trades ({int(ovs.set_index('date').loc['2026-09-01','log_wins'])} wins), but the stream that day gives no fresh call with an activation. Overall, {NM} of {len(ov)} log rows match a stream call (same side, ±10 min). The self-reported log is not a record of the live calls.
Same method as the Trader discretion section (s9/s10 code unchanged; YouTube calls with known side as “taken”; fit 25-Aug..30-Sep, holdout 1–23-Oct). 51 calls with a known side → 50 with entry-time features; 315 candidates; fit base take rate {YM.get('base_take_rate_fit',0)*100:.0f}%. 48% of his calls have one of our V1–V4/P1–P8 candidates within ±10 min, same direction. The strongest contrasts: he takes trades after a strong move in his direction (side-aligned spot move over 15 min, standardised difference ≈1.0; 15-min premium change 19.5 vs 9.5 for skipped; BH q<0.01). In plain words, he chases momentum.
{tb(FC,3)}Tree CV AUC {YM['tree']['lodo_auc']:.2f} / holdout {YM['tree']['holdout_auc']:.2f}; logistic {YM['logit']['lodo_auc']:.2f} / {YM['logit']['holdout_auc']:.2f}. No tree leaf had ≥10 takes at ≥1.2× the base rate, so the pre-registered extraction gives no filter. There is nothing to test on held-out data or 2024–26 history, and we did not go looking for one after the fact. Candidates he took: X_OLD −0.8 pts per trade (n=46). Skipped: −4.2 (n=269). Both are ≤0.
Files: yt_calls_scored.csv · yt_review_adjudicated.csv · yt_random_bench.csv · yt_by_group.csv · yt_vs_selflog.csv · yt_disc_candidates.csv · yt_disc_model.json · scripts scripts/yt_*.py, s12_yt_discretion.py, s13_yt_disc_model.py.