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.
172 lines
7.4 KiB
Python
172 lines
7.4 KiB
Python
"""Range structure, the five-trace context score, and the retest as a CONTINUUM of depths.
|
|
|
|
Two findings set this up:
|
|
|
|
the CONTEXT score is real +0.045 R per agreeing trace, replicated on two triggers
|
|
the retest level matters, and price edge > value-area edge > VPOC, monotone in 8/8
|
|
it matters in the book's - the deeper the level you wait at, the more your fills
|
|
opposite direction are breakouts that have already failed (adverse selection)
|
|
|
|
That second result was measured at three discrete locations. Since the ordering was monotone
|
|
at all three, the interesting question is not "which of the three" but "what does the curve
|
|
do if you keep going" - and in particular whether it crosses zero on the SHALLOW side, which
|
|
is where a base near zero would have to live for the context modifier to be worth bolting on.
|
|
|
|
THE DESIGN
|
|
----------
|
|
After a breakout, place a BUY LIMIT (long case) at
|
|
|
|
level = broken_edge + u * ATR u > 0 shallow, never reaching the old edge
|
|
u = 0 the price edge itself
|
|
u < 0 deep, back inside the old range
|
|
|
|
and sweep u. The depth is a level YOU CHOOSE when the order is placed, not a property of
|
|
what price went on to do, so there is no selection bias in the x-axis itself. Everything -
|
|
level, stop, target - is fixed at placement time from bars already closed.
|
|
|
|
Orders that would fill instantly are DROPPED, not filled at market: a buy limit already
|
|
above the ask is not a retest, and letting `fills.py` cap it at the open would quietly mix
|
|
market entries into a test about waiting.
|
|
|
|
THE CONTROL
|
|
-----------
|
|
The same orders at the same DISTANCE from the current price, but with that distance permuted
|
|
across events - geometry preserved exactly, the identity of the level destroyed. Without it,
|
|
"buy pullbacks" and "buy pullbacks TO THIS LEVEL" are indistinguishable, and the first is
|
|
just drift.
|
|
"""
|
|
import numpy as np, sys
|
|
import fills, book
|
|
from fills import LIMIT, MARKET
|
|
|
|
SYMS = ('EURUSD', 'USDJPY', 'XAUUSD', 'SP500')
|
|
|
|
|
|
def traces(f, s, i, top, bot, dd, htf):
|
|
"""The five traces of book 2 2.3 / 7.1. +1 each if it agrees with direction dd.
|
|
|
|
Reads only bars in [s, i], all closed before the order is placed.
|
|
"""
|
|
h, l, c, vol = f.h, f.l, f.c, f.v
|
|
mid = 0.5 * (top + bot)
|
|
Lq = i - s
|
|
th = max(Lq // 3, 2)
|
|
segA, segB, segC = slice(s, s + th), slice(s + th, s + 2 * th), slice(s + 2 * th, i)
|
|
t1 = 1 if (h[segA].max() - mid) > (mid - l[segA].min()) else -1
|
|
t2 = 1 if (h[segB].max() - mid) > (mid - l[segB].min()) else -1
|
|
t3 = 0
|
|
if segC.stop > segC.start:
|
|
if t2 > 0:
|
|
t3 = 1 if l[segC].min() > bot + 0.25 * (top - bot) else -1
|
|
else:
|
|
t3 = -1 if h[segC].max() < top - 0.25 * (top - bot) else 1
|
|
rr = max(h[i] - l[i], 1e-12)
|
|
clspos = (c[i] - l[i]) / rr if dd > 0 else (h[i] - c[i]) / rr
|
|
vavg = vol[s:i].mean() if i > s else vol[i]
|
|
t4 = 1 if (clspos > 0.6 and vol[i] > 1.2 * max(vavg, 1e-12)) else -1
|
|
t5 = 1 if htf == dd else -1
|
|
return sum(1 for x in (t1 * dd, t2 * dd, t3 * dd, t4, t5) if x > 0)
|
|
|
|
|
|
def breakouts(f, theta=0.60, htf=200, score=True):
|
|
"""Range breakouts with their structure, one row per event.
|
|
|
|
-> dict of arrays: i (breakout bar), s (range start), d, top, bot, atr, ag (trace count)
|
|
"""
|
|
atr = f.atr(14)
|
|
L, hi_, lo_ = book.find_ranges(f.h, f.l, atr, theta=theta)
|
|
up = (L > 0) & (f.c > hi_)
|
|
dn = (L > 0) & (f.c < lo_)
|
|
fire = np.nonzero(up | dn)[0]
|
|
fire = fire[(fire > max(300, htf + 5)) & (fire < f.n - 400)]
|
|
if not len(fire):
|
|
return None
|
|
d = np.where(up[fire], 1, -1)
|
|
s = fire - L[fire]
|
|
ok = s >= 1
|
|
fire, d, s = fire[ok], d[ok], s[ok]
|
|
htf_sig = np.sign(f.c[fire] - f.c[fire - htf]).astype(int)
|
|
ag = np.zeros(len(fire), np.int8)
|
|
if score:
|
|
for q in range(len(fire)):
|
|
ag[q] = traces(f, int(s[q]), int(fire[q]), hi_[fire[q]], lo_[fire[q]],
|
|
int(d[q]), int(htf_sig[q]))
|
|
return dict(i=fire, s=s, d=d, top=hi_[fire], bot=lo_[fire], atr=atr[fire],
|
|
L=L[fire], ag=ag)
|
|
|
|
|
|
def retest(sym, tf, phi, mrisk=1.0, kR=2.0, wait=40, H=200, theta=0.60,
|
|
bk=None, f=None, ev=None, placebo=0):
|
|
"""One depth arm, parameterised by RETRACE FRACTION rather than distance in ATR.
|
|
|
|
level = price_now - phi * (price_now - broken_edge)
|
|
|
|
phi -> 0 at market, no pullback demanded
|
|
phi = 1 the price edge itself - the classic Last Point of Support
|
|
phi > 1 through the edge, into the old range: value-area and VPOC territory
|
|
|
|
Why not "edge + u*ATR": that version only lets an order exist when the breakout has
|
|
already extended past u*ATR, so the shallow arms were quietly a strong-breakout filter
|
|
and the curve mixed depth with extension. As a fraction of the CURRENT distance to the
|
|
edge, every event qualifies at every phi and the arms are the same sample throughout.
|
|
|
|
stop = entry - d * mrisk * ATR fixed multiple, known at placement
|
|
target= entry + d * kR * risk
|
|
"""
|
|
bk = bk or fills.Book(sym)
|
|
f = f or book.frame(sym, tf, bk)
|
|
ev = ev or breakouts(f, theta=theta)
|
|
if ev is None:
|
|
return None
|
|
step = book.TF_SEC[tf] // 60
|
|
i, d, atr = ev['i'], ev['d'], ev['atr']
|
|
edge = np.where(d > 0, ev['top'], ev['bot'])
|
|
#--- the order is placed after bar i closes and is live from bar i+1
|
|
e = i + 1
|
|
start = f.i0[e]
|
|
ask0, bid0 = bk.ao[start], bk.bo[start]
|
|
here = np.where(d > 0, ask0, bid0)
|
|
#--- extension of the breakout beyond the edge, at the moment the order is placed
|
|
ext = (here - edge) * d
|
|
lvl = here - d * phi * ext
|
|
dist = phi * ext
|
|
if placebo:
|
|
#--- same distance from the same starting price, level identity destroyed
|
|
rng = np.random.default_rng(placebo)
|
|
dist = dist[rng.permutation(len(dist))]
|
|
lvl = here - d * dist
|
|
#--- a buy limit must sit strictly BELOW the ask (a sell limit above the bid), else it
|
|
#--- would fill instantly at the open and a market entry would be mixed into a test
|
|
#--- about waiting
|
|
live = (dist > 0) & np.where(d > 0, lvl < ask0, lvl > bid0)
|
|
keep = live & np.isfinite(lvl) & (atr > 0)
|
|
if keep.sum() < 100:
|
|
return None
|
|
idx = np.nonzero(keep)[0]
|
|
risk = mrisk * atr[idx]
|
|
stop = lvl[idx] - d[idx] * risk
|
|
targ = lvl[idx] + d[idx] * kR * risk
|
|
out = fills.simulate(bk, start[idx], d[idx], stop, targ, H * step,
|
|
entry=LIMIT, entry_px=lvl[idx], entry_window=wait * step)
|
|
if out is None:
|
|
return None
|
|
sel = idx[np.nonzero(out['filled'])[0][out['kept']]]
|
|
out['event'] = sel
|
|
out['ag'] = ev['ag'][sel]
|
|
out['start'] = start[sel]
|
|
#--- overlapping trades share price path; the honest n is the independent one
|
|
out['indep'] = book.nonoverlap(out['idx'], out['exit_idx'] - out['idx'])
|
|
out['placed'] = int(keep.sum())
|
|
return out
|
|
|
|
|
|
def line(tag, out, extra=''):
|
|
if out is None or out['n'] < 60:
|
|
return f" {tag:<26} - too few"
|
|
R = out['R']; ind = out['indep']
|
|
Ri = R[ind]
|
|
return (f" {tag:<26} n={out['n']:>6} ({int(ind.sum()):>5} ind)"
|
|
f" expR {R.mean():+7.4f} t {book.tstat(R):+6.2f}"
|
|
f" ind {Ri.mean():+7.4f} t {book.tstat(Ri):+6.2f}"
|
|
f" fill {100*out['n']/max(out['placed'],1):5.1f}%"
|
|
f" amb {100*out['ambiguous']:4.1f}% unres {100*out['unresolved']:4.1f}%{extra}")
|