# Builds section_trail50.html (#trail50) for the buyer-method-audit page.
import pandas as pd,numpy as np,html
L='/workspace/research/buyer-method-audit'; R=lambda f:pd.read_csv(f'{L}/results/{f}')
def tb(df,fl=2): return df.to_html(index=False,float_format=lambda x:f'{x:,.{fl}f}',border=0,na_rep='–')
P=R('trail50_primary.csv'); Y=R('trail50_by_year.csv'); S=R('trail50_sensitivity.csv'); C=R('trail50_vs_old.csv'); SP=R('trail50_spot_proxy_by_year.csv'); CP=R('trail50_spot_capture.csv'); TD=R('trail50_today_20261026.csv')
cols=['cand','mode','inst','split','n','mean','median','win','avg_win','avg_loss','payoff','rs_per_trade','rs_total','maxdd_rs','worst_month','worst_month_rs','random_mean','random_pctile','t_p_one','q_bh']
pm=P[(P['mode']=='spot')&P.cand.isin(['A','B15','B30','C','D','E'])][cols]; sec=P[(P['mode']=='prem')][cols]; lead=P[P.cand.str.startswith('L')][cols]
te=P[(P['mode']=='spot')&(P.split=='test')].set_index('cand'); tr=P[(P['mode']=='spot')&(P.split=='train')].set_index('cand')
td=TD[TD['mode'].isin(['spot','prem','old_E0','old_E1'])][['cand','signal','dir','R','mode','inst','K','typ','fill','exit_min','why','pnl','pnl_rs','spot_pts']]
H=f"""
6. Follow-up (asked 26-Oct-2026 18:06 IST): “trail the profit at 50% after 1:2” instead of a fixed exit
Verdict: the trail does not rescue any strategy.
- Train results got worse on 5 of 6 strategies compared with the old exits. O30 is the exception, and it has only 17 trades. The 2026 results moved in both directions.
- Only the trend-day filter E is positive in 2026 at +{te.loc['E','mean']:.1f} pts/trade (₹{te.loc['E','rs_per_trade']:,.0f}/lot, n={te.loc['E','n']:.0f}, p={te.loc['E','t_p_one']:.2f}). The same rule lost {tr.loc['E','mean']:.1f} pts/trade on train and sits at the {tr.loc['E','random_pctile']:.0f}th percentile versus random there. That is a regime flip, not an edge.
- BH over the 6 primary tests: all q≈0.99.
- The post-hoc gap-down ORB put lead (2-ITM put) is +6.7 / +7.3 pts in 2026 against −1.2 / +0.4 on train. It stays forward-watch only.
- Honesty note: this exit was proposed after the 2026 results were seen, so 2026 is no longer fully untouched for it. Train-vs-random and the per-year rows are the fairer read, and they are negative.
Exit rules.
- The initial stop is each strategy's structural spot stop (R clipped to 15–70 pts). It is checked on 1-min high/low, exactly as before.
- There is no breakeven move, no scale-out and no target.
- Once the peak open profit on 1-min spot closes reaches 2R, the stop becomes entry + 50% of peak profit. It only ratchets up and is checked on 1-min closes.
- Every exit fills at the next minute's option open. The time exit is the 15:15 option open (the last real spot minute is 15:14). No overnight holds.
- Premium version (secondary): same structural spot stop, but the trail runs on option 1-min closes with Rprem=0.5×R (ATM delta ≈0.5).
- Everything else is identical to sections 3–4: ATM, nearest weekly with DTE≥1, 0.5 pt slippage per side plus real charges, and STT 0.15% from 1-Apr-2026.
- Lot sizes: 25 before 20-Nov-2024, 75 to Dec-2025, 65 in 2026.
- Random baseline: same time, same direction and same R on 30 random days from the same period, with the same exit.
Disclosure: rule C allows up to 3 triggers a day, as in the recoveries rule. 20 trades in 15 days were extra. With the first trigger only, C is −5.4 (train) and −11.7 (2026), so the verdict does not change.
Primary: spot-based trail, 6 pre-declared strategies
{tb(pm)}
Trail vs the old exits (same trades, pts/trade)
{tb(C)}
Per year (primary trail; the L rows are the post-hoc lead, 2-ITM puts)
{tb(Y,1)}per-month CSV
Sensitivity (spot trail, ATM; activation 1.5/2/3R at 50%, lock 40/50/60% at 2R). Reported only; nothing was picked from it.
{tb(S)}
Secondary: premium-based trail
{tb(sec)}
Post-hoc lead: gap-down ORB, puts 2/4 ITM, spot trail. Labelled post-hoc.
{tb(lead)}
How much of the spot ORB edge does the option keep with this exit?
Spot proxy with the same trail (index points, no costs), 2022–2026:
{tb(SP,1)}
Option gross before slippage versus spot points on the same trades:
{tb(CP)}
With this exit, ORB30 still makes about +7 spot pts/trade over 2022–26 (p=0.05). The ATM option keeps about 0% of it (ORB15 about 21% in 2026 and negative in train). ITM puts on the gap-down side keep 45–50% in 2026 but only 1–29% in train.
Case: 26-Oct-2026 (full-session Upstox intraday, fetched read-only after the close; spot 15:15+ treated as missing)
Gap −75.6 (open 22,524.4 vs the 23-Oct close of 22,600). No ORB with-gap signal and no O30 or VWAP-pullback signal fired. Rule C fired at 09:16 and 09:26, and E fired at 10:14 (long).
{tb(td)}
Trail result today: C 09:16 −28.6, C 09:26 +79.1 (trailed out at 11:34), E −56.6. Net −6.2 pts (≈−₹400/lot). Holding the 09:26 call to the close (old E1) would have made +210.5. One day like this is what makes the tail look attractive, but over two years the stops cost more than the tail pays.
"""
open(f'{L}/section_trail50.html','w').write(H); print('ok',len(H))