"""The only base that has ever been positive - and whether anything can be bolted onto it. Every trigger tested in this project starts at -0.15 to -0.33 R, so the context modifier has never had anything to lift. But one thing HAS survived every test: drift. SP500 and gold rose for the whole sample, the engine null re-measured it independently (random longs beat random shorts by +0.08 to +0.10 R), and [[project_anomaly_families_tested]] found it was the single family to clear cost. So the question step 2 really asks is: **does a long-only breakout on a drifting instrument give a base at or above zero, and does anything add to it?** THREE ARMS, AND THE SECOND IS THE ONE THAT MATTERS -------------------------------------------------- REAL range breakout in direction d, market entry at the next bar's open LOCAL the same trade at a RANDOM bar within +/-250 bars - same instrument, same regime, same drift rate, same barrier geometry, same n. Only the breakout is gone. GLOBAL a random bar anywhere in the sample If REAL - LOCAL is zero, the breakout contributes nothing and whatever expectancy the trade has is exposure, not timing. That is the honest way to report a drift-powered result: it is beta, and beta is available by buying and holding without paying a spread 3,000 times. EURUSD and USDJPY are included as NEGATIVE CONTROLS. They barely drifted, so if the "edge" is drift they should show nothing, and if a cell there lights up while the mechanism says it should not, the mechanism is wrong rather than the cell being lucky. """ import numpy as np, sys, time sys.stdout.reconfigure(encoding='utf-8', errors='replace') import fills, book, wyckoff SYMS = ('EURUSD', 'USDJPY', 'XAUUSD', 'SP500') MRISK, KR, H = 3.0, 2.0, 200 def trade(bk, f, bars, d, mrisk, kR, H, step): """Market entry at the open of `bars`, stop mrisk*ATR away, target kR*risk.""" atr = f.atr(14) ok = (bars > 300) & (bars < f.n - 5) & np.isfinite(atr[bars]) & (atr[bars] > 0) bars, d = bars[ok], d[ok] start = f.i0[bars] ent = np.where(d > 0, bk.ao[start], bk.bo[start]) risk = mrisk * atr[bars] o = fills.simulate(bk, start, d, ent - d * risk, ent + d * kR * risk, H * step, entry=fills.MARKET) if o is None: return None o['indep'] = book.nonoverlap(o['idx'], o['exit_idx'] - o['idx']) o['bars'] = bars[np.nonzero(o['filled'])[0][o['kept']]] return o def run(sym, tf, mrisk=MRISK, kR=KR, seed=3, span=250): bk = fills.Book(sym) f = book.frame(sym, tf, bk) step = book.TF_SEC[tf] // 60 ev = wyckoff.breakouts(f) if ev is None: return None rng = np.random.default_rng(seed) out = {} for d0, tag in ((+1, 'long'), (-1, 'short')): m = ev['d'] == d0 if m.sum() < 150: continue bars = ev['i'][m] + 1 ag = ev['ag'][m] real = trade(bk, f, bars, np.full(m.sum(), d0), mrisk, kR, H, step) loc = trade(bk, f, np.clip(bars + rng.integers(-span, span + 1, len(bars)), 301, f.n - 6), np.full(m.sum(), d0), mrisk, kR, H, step) glo = trade(bk, f, rng.integers(301, f.n - 6, len(bars)), np.full(m.sum(), d0), mrisk, kR, H, step) if real is None: continue sel = np.nonzero(real['filled'])[0][real['kept']] out[tag] = dict(real=real, loc=loc, glo=glo, ag=ag[sel]) return out def stat(o): if o is None: return np.array([0.0]) return o['R'][o['indep']] def diff_t(a, b): se = np.sqrt(a.var(ddof=1) / len(a) + b.var(ddof=1) / len(b)) return (a.mean() - b.mean()) / max(se, 1e-12) if __name__ == '__main__': syms = [s for s in sys.argv[1:] if s in SYMS] or list(SYMS) print("=== DRIFT AS A BASE: does the breakout add anything to the exposure? ===") print(f" stop {MRISK} ATR, target {KR}R, market entry. EURUSD/USDJPY are the") print(" negative controls - little drift, so they should show little.\n") print(f" {'sym':>7}{'tf':>4}{'side':>6}{'n':>6}{'REAL':>9}{'t':>6}" f"{'local':>9}{'global':>9}{'R-local':>9}{'t':>6}{'ctx slope':>11}{'t':>6}") rows = [] for sym in syms: for tf in ('H1', 'H4'): r = run(sym, tf) if not r: continue for tag, v in r.items(): A = stat(v['real']); Lc = stat(v['loc']); G = stat(v['glo']) sl, tt = book.slope_t(v['real']['R'][v['real']['indep']], v['ag'][v['real']['indep']]) ex = A.mean() - Lc.mean() rows.append((sym, tf, tag, ex, A.mean(), sl)) print(f" {sym:>7}{tf:>4}{tag:>6}{len(A):>6}{A.mean():>+9.4f}" f"{book.tstat(A):>+6.2f}{Lc.mean():>+9.4f}{G.mean():>+9.4f}" f"{ex:>+9.4f}{diff_t(A, Lc):>+6.2f}{sl:>+11.4f}{tt:>+6.2f}") if rows: ex = np.array([r[3] for r in rows]) base = np.array([r[4] for r in rows]) print(f"\n breakout excess over local control: mean {ex.mean():+.4f}, " f"positive {int((ex>0).sum())}/{len(ex)}") print(f" base expR: mean {base.mean():+.4f}, positive {int((base>0).sum())}/{len(base)}") for tag in ('long', 'short'): b = np.array([r[4] for r in rows if r[2] == tag]) print(f" {tag:>5}: base mean {b.mean():+.4f} positive {int((b>0).sum())}/{len(b)}")