The MI sample builder used `MathAbs(labelBarOffset)` as a padding, causing rows from offset and non-offset builds to be paired with a double shift. This broke the positive control, failed the 5× gate, and voided all reported mutual‑information figures. Replace with the fixed `MiShiftPad` constant to ensure builds enumerate the same set of bars and row-k alignment is preserved. Add `BatchOptionsTotal()` to `CNeuronBatchNormOCL` and split the packed BN weight array in the learning report into separate norms for the outgoing dense matrix, gamma, beta, running statistics, and Adam moment buffers. This turns an ambiguous single‑norm reading into precise diagnostics that distinguish weight divergence from scaling issues.
89 lines
3.8 KiB
Python
89 lines
3.8 KiB
Python
"""Is "breakouts underperform nearby random entries" a finding, or a property of the control?
|
|
|
|
The drift run reported real minus local control at -0.045 R, negative for longs AND shorts,
|
|
and it did not go away when the barriers were re-sized from a slow ATR. The tempting reading
|
|
is that breakout continuation is anti-predictive and the fade is worth +0.045.
|
|
|
|
Before believing that, look at what the control actually is. A breakout bar is BY
|
|
CONSTRUCTION a local price extreme - price has just traded beyond the top of a range that
|
|
contained it for many bars. A control bar drawn uniformly from +/-250 bars around it is
|
|
therefore drawn from a window in which the real entry sits near the high (for an upward
|
|
breakout) or near the low (for a downward one).
|
|
|
|
Within any window, buying at the top and selling at the bottom is the worst possible entry
|
|
for a mean-reverting series. So real-minus-control would be negative for both directions even
|
|
if the breakout carried no information at all. The two arms differ in ENTRY PRICE, not only
|
|
in timing.
|
|
|
|
THE CHECK
|
|
---------
|
|
For each event, the percentile of the entry price within the +/-250 bar window, for the real
|
|
arm and the control arm, oriented so that HIGH means "a worse place to enter for this trade's
|
|
direction". A fair control sits near 50 for both. If the real arm sits near 90 while the
|
|
control sits near 50, the -0.045 is the control's geometry and there is nothing to fade.
|
|
"""
|
|
import numpy as np, sys
|
|
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
import fills, book, wyckoff
|
|
|
|
SYMS = ('EURUSD', 'USDJPY', 'XAUUSD', 'SP500')
|
|
|
|
|
|
def pct_in_window(c, bars, span):
|
|
"""Percentile of c[bar] within c[bar-span : bar+span], per event."""
|
|
out = np.empty(len(bars))
|
|
n = len(c)
|
|
for k, b in enumerate(bars):
|
|
lo, hi = max(0, b - span), min(n, b + span + 1)
|
|
w = c[lo:hi]
|
|
out[k] = 100.0 * (w < c[b]).mean()
|
|
return out
|
|
|
|
|
|
def run(sym, tf='H1', span=250, seed=3):
|
|
bk = fills.Book(sym)
|
|
f = book.frame(sym, tf, bk)
|
|
ev = wyckoff.breakouts(f, score=False)
|
|
if ev is None:
|
|
return None
|
|
rng = np.random.default_rng(seed)
|
|
rows = []
|
|
for d0 in (+1, -1):
|
|
m = ev['d'] == d0
|
|
if m.sum() < 150:
|
|
continue
|
|
bars = ev['i'][m] + 1
|
|
bars = bars[(bars > 300) & (bars < f.n - 5)]
|
|
ctl = np.clip(bars + rng.integers(-span, span + 1, len(bars)), 301, f.n - 6)
|
|
pr = pct_in_window(f.c, bars, span)
|
|
pc = pct_in_window(f.c, ctl, span)
|
|
#--- orient so HIGH = a worse place to enter for this direction
|
|
if d0 < 0:
|
|
pr, pc = 100 - pr, 100 - pc
|
|
rows.append((d0, len(bars), pr.mean(), pc.mean()))
|
|
return rows
|
|
|
|
|
|
if __name__ == '__main__':
|
|
syms = [s for s in sys.argv[1:] if s in SYMS] or list(SYMS)
|
|
print("=== IS THE LOCAL CONTROL FAIR? ===")
|
|
print(" entry-price percentile within the +/-250 bar window, oriented so HIGH = a")
|
|
print(" worse entry for that direction. A fair control sits near 50 on both arms.\n")
|
|
print(f" {'sym':>7}{'tf':>4}{'side':>6}{'n':>6}"
|
|
f"{'real pct':>10}{'ctrl pct':>10}{'difference':>12}")
|
|
d = []
|
|
for sym in syms:
|
|
for tf in ('H1', 'H4'):
|
|
r = run(sym, tf)
|
|
if not r:
|
|
continue
|
|
for d0, n, a, b in r:
|
|
d.append(a - b)
|
|
print(f" {sym:>7}{tf:>4}{'long' if d0>0 else 'short':>6}{n:>6}"
|
|
f"{a:>10.1f}{b:>10.1f}{a-b:>+12.1f}")
|
|
d = np.array(d)
|
|
print(f"\n mean real-minus-control percentile: {d.mean():+.1f} points "
|
|
f"({int((d>0).sum())}/{len(d)} cells worse)")
|
|
print("\n A large positive number means the two arms are not comparable: the breakout")
|
|
print(" arm is entering at a systematically worse price within the same window, so")
|
|
print(" real-minus-control measures the control's geometry, not the signal.")
|