forked from animatedread/Warrior_EA
41 lines
2.2 KiB
Python
41 lines
2.2 KiB
Python
"""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}")
|