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.
93 lines
4.3 KiB
Python
93 lines
4.3 KiB
Python
"""Settling the context score with nine instruments instead of four.
|
|
|
|
On the honest engine the Wyckoff context slope landed at +0.0239 R/trace, t +1.37, sign held
|
|
in 6 of 8 cells - too weak to trade, too consistent to dismiss. `sqxbars.py` has since made
|
|
five more instruments readable, sharing no data path with the original four: FTSE100, UK100,
|
|
WTI (two independent feeds) and USDCAD.
|
|
|
|
The test is unchanged and was fixed before any of this ran: the ORIGINAL LPS configuration
|
|
(market entry at the next bar's open, stop at the retest extreme, 2R target), scored by the
|
|
five traces of book 2 2.3 / 7.1, with the single pre-specified prediction that expR rises
|
|
monotonically with the number of agreeing traces. Nothing is tuned per instrument.
|
|
|
|
WHAT WOULD SETTLE IT EITHER WAY
|
|
-------------------------------
|
|
real the pooled slope holds near +0.024 with t comfortably past 2, and the new
|
|
instruments - which had no hand in choosing anything - carry their share of it
|
|
nothing the slope drifts toward zero as power rises, and the new instruments split evenly
|
|
|
|
The second is what a small sample of noisy cells looks like when it is finally given enough
|
|
data to speak. The five new instruments are the honest out-of-sample here: every parameter in
|
|
this test was set on the original four.
|
|
|
|
Bases on the breadth instruments use a SYNTHESISED spread and are approximate; the slope is
|
|
not, because cost is nearly uncorrelated with the context score (measured: +0.0008 R/trace).
|
|
"""
|
|
import numpy as np, sys, time
|
|
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
|
import fills, book, breadth, test_lps2
|
|
|
|
NATIVE = ('EURUSD', 'USDJPY', 'XAUUSD', 'SP500')
|
|
|
|
|
|
def cells(tfs=('M15', 'H1')):
|
|
for tf in tfs:
|
|
for s in NATIVE:
|
|
bk = fills.Book(s)
|
|
yield s, tf, bk, book.frame(s, tf, bk), 'original'
|
|
for s in breadth.SPREAD_BP:
|
|
bk, f = breadth.get(s, tf)
|
|
yield breadth.NICE[s], tf, bk, f, 'new'
|
|
|
|
|
|
if __name__ == '__main__':
|
|
tfs = tuple(a for a in sys.argv[1:] if a in ('M15', 'H1', 'H4')) or ('M15', 'H1')
|
|
print("=== CONTEXT SLOPE: NINE INSTRUMENTS ===")
|
|
print(" same LPS configuration, unchanged. The five 'new' instruments had no hand")
|
|
print(" in choosing any parameter, so they are the out-of-sample arm.\n")
|
|
print(f" {'sym':>9}{'tf':>5}{'set':>10}{'n':>7} "
|
|
+ "".join(f"{k:>12}" for k in range(5)) + f"{'slope':>9}{'t':>7}{'base':>9}")
|
|
PR, PA, PT, tag = [], [], [], []
|
|
for s, tf, bk, f, kind in cells(tfs):
|
|
try:
|
|
a = test_lps2.events(s, tf, bk=bk, f=f)
|
|
except Exception as ex:
|
|
print(f" {s:>9}{tf:>5}{kind:>10} failed: {ex}")
|
|
continue
|
|
if a is None:
|
|
print(f" {s:>9}{tf:>5}{kind:>10} - too few")
|
|
continue
|
|
R, ag = a['R'], a['ag']
|
|
txt = [f"{R[ag==k].mean():+6.3f}({int((ag==k).sum()):>4})"
|
|
if (ag == k).sum() >= 25 else f"{'-':>12}" for k in range(5)]
|
|
sl, tt = book.slope_t(R, ag)
|
|
print(f" {s:>9}{tf:>5}{kind:>10}{a['n']:>7} " + "".join(txt)
|
|
+ f"{sl:>+9.4f}{tt:>+7.2f}{R.mean():>+9.4f}")
|
|
PR.append(R); PA.append(ag); PT.append(a['t']); tag.append((kind, sl, R.mean()))
|
|
if not PR:
|
|
sys.exit()
|
|
|
|
def pooled(sel, label):
|
|
R = np.concatenate([r for r, k in zip(PR, tag) if sel(k)])
|
|
A = np.concatenate([a for a, k in zip(PA, tag) if sel(k)])
|
|
sl, tt = book.slope_t(R, A)
|
|
pos = sum(1 for k in tag if sel(k) and k[1] > 0)
|
|
tot = sum(1 for k in tag if sel(k))
|
|
print(f" {label:<26} n={len(R):>7,} slope {sl:>+8.4f} t {tt:>+6.2f}"
|
|
f" base {R.mean():>+8.4f} positive-slope cells {pos}/{tot}")
|
|
return R, A
|
|
|
|
print()
|
|
Rn, An = pooled(lambda k: k[0] == 'original', 'ORIGINAL four')
|
|
Rb, Ab = pooled(lambda k: k[0] == 'new', 'NEW five (out of sample)')
|
|
R, A = pooled(lambda k: True, 'ALL nine')
|
|
print()
|
|
for k in range(6):
|
|
m = A == k
|
|
if m.sum() < 25:
|
|
continue
|
|
se = R[m].std(ddof=1) / np.sqrt(m.sum())
|
|
print(f" {k} agree n={int(m.sum()):>6} expR {R[m].mean():+7.4f} +/- {se:.4f}"
|
|
f" t {book.tstat(R[m]):+6.2f}")
|
|
print("\n The out-of-sample line is the one that matters: those five instruments")
|
|
print(" had no hand in choosing the trigger, the traces, or any threshold.")
|