"""Confirmation of G2a (VRP>5) -- NO new thresholds, trial counter stays N=6.""" import sys, numpy as np, pandas as pd sys.path.insert(0, ".") import backtest as bt, macro_gates as mg from scipy import stats from run_screen import zscore_entries spx = bt.load("SP500", "PERIOD_D1") gt = mg.gate_table(pd.Series(spx["c"], index=pd.DatetimeIndex(spx["ts"]).normalize())) G2a, G2b = mg.GATES["G2a"], mg.GATES["G2b"] # D1: per-symbol split and Welch t of G2a vs G2b trade returns a, b = mg.collect(G2a, gt), mg.collect(G2b, gt) print("D1 G2a vs G2b trades:", len(a), len(b)) for s in mg.IDX: x = [t["ret"] * 1e4 for t in a if t["symbol"] == s]; y = [t["ret"] * 1e4 for t in b if t["symbol"] == s] print(f" {s:<7} G2a n={len(x):>3} {np.mean(x):7.1f}bp | G2b n={len(y):>3} {np.mean(y):7.1f}bp") ra = [t["ret"] * 1e4 for t in a]; rb = [t["ret"] * 1e4 for t in b] print(" Welch t(G2a-G2b) = %.2f p=%.4f" % stats.ttest_ind(ra, rb, equal_var=False)) print(" G2a alone vs 0: t=%.2f" % stats.ttest_1samp(ra, 0).statistic) # H4 2021+: gate by PRIOR day's macro value (conservative; bar may be intraday) def collect_h4(gate): out = [] for s in mg.IDX: d = bt.load(s, "PERIOD_H4"); e, xma = zscore_entries(d, 20, -1.5, 0) if gate is not None: day = pd.DatetimeIndex(d["ts"]).normalize() - pd.Timedelta(days=1) ok = gate(gt).reindex(day, method="ffill").to_numpy() if False else gate(gt).reindex(gt.index).ffill() prev = ok.shift(1).reindex(pd.DatetimeIndex(d["ts"]).normalize(), method="ffill").to_numpy() e = e & np.where(pd.isna(prev), False, prev).astype(bool) tr = bt.simulate(d, e, 1, xma, 10, 3.0); tr = bt.add_r(tr, d, 3.0) for t in tr: t["symbol"] = s; t["exit_t"] = d["ts"][t["exit_i"]] out += tr return out print("\nH4 2021+ (independent bars/trades)") for name, g in (("BASE", None), ("G2a", G2a), ("G2b", G2b)): tr = collect_h4(g) for w, lo, hi in (("FULL", "2021-01-01", "2030-01-01"), ("2022", "2022-01-01", "2023-01-01"), ("2023+", "2023-01-01", "2030-01-01")): s = mg.window_stats(tr, lo, hi) if s: print(f" {name:<5}{w:<6} n={s['n']:>4} {s['pm']:>5.1f}/mo {s['bp']:>6.1f}bp R={s['R']:>6.3f} tot={s['tot']:>6.1%} DD={s['dd']:>5.1%} ret/DD={s['rdd']:>6.2f}")