92 行
4.1 KiB
Python
92 行
4.1 KiB
Python
|
|
"""The last claim left standing: is a broken edge a WORSE place to buy than a random level?
|
||
|
|
|
||
|
|
Everything else closed negative tonight. One sub-result survived: on EURUSD H1, a limit order
|
||
|
|
resting at the actual broken range edge did worse than the same order the same distance away
|
||
|
|
at a permuted level - `real - placebo` of -0.077 and -0.074 at phi >= 1. That is adverse
|
||
|
|
selection, and it is the mechanism book 2's A/B test proposed (a pullback deep enough to
|
||
|
|
reach the level is disproportionately a breakout that has already failed).
|
||
|
|
|
||
|
|
It is not tradeable - it is a reason NOT to do something - but it is a claim about market
|
||
|
|
structure and it was measured on one instrument. The five breadth instruments never had a
|
||
|
|
hand in finding it, so they can settle it the same way they settled the context score.
|
||
|
|
|
||
|
|
arm REAL buy limit at price_now - phi*(price_now - broken_edge)
|
||
|
|
arm PLACEBO the same distance from the same starting price, distances permuted across
|
||
|
|
events: geometry identical, level identity destroyed
|
||
|
|
|
||
|
|
Both arms pay the same spread and meet the same tie convention, so cost cancels in the
|
||
|
|
difference. The prediction, fixed in advance from the mechanism: real - placebo is NEGATIVE,
|
||
|
|
and MORE negative as phi rises, because a deeper level selects harder against you.
|
||
|
|
|
||
|
|
Note the sign convention: a negative number CONFIRMS the hypothesis here.
|
||
|
|
"""
|
||
|
|
import numpy as np, sys
|
||
|
|
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
||
|
|
import fills, book, wyckoff, breadth
|
||
|
|
|
||
|
|
NATIVE = ('EURUSD', 'USDJPY', 'XAUUSD', 'SP500')
|
||
|
|
PHIS = (0.5, 1.0, 1.5)
|
||
|
|
|
||
|
|
|
||
|
|
def cells(tfs):
|
||
|
|
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'
|
||
|
|
|
||
|
|
|
||
|
|
def gap(bk, f, sym, tf, phi, ev, seeds=(11, 23, 37)):
|
||
|
|
"""real minus placebo, averaging the placebo over several permutations."""
|
||
|
|
a = wyckoff.retest(sym, tf, phi, mrisk=2.0, kR=2.0, wait=40, H=200,
|
||
|
|
bk=bk, f=f, ev=ev)
|
||
|
|
if a is None:
|
||
|
|
return None
|
||
|
|
A = a['R'][a['indep']]
|
||
|
|
bs = []
|
||
|
|
for sd in seeds:
|
||
|
|
b = wyckoff.retest(sym, tf, phi, mrisk=2.0, kR=2.0, wait=40, H=200,
|
||
|
|
bk=bk, f=f, ev=ev, placebo=sd)
|
||
|
|
if b is not None:
|
||
|
|
bs.append(b['R'][b['indep']])
|
||
|
|
if not bs:
|
||
|
|
return None
|
||
|
|
B = np.concatenate(bs)
|
||
|
|
se = np.sqrt(A.var(ddof=1) / len(A) + B.var(ddof=1) / len(B))
|
||
|
|
return len(A), A.mean(), B.mean(), A.mean() - B.mean(), (A.mean() - B.mean()) / max(se, 1e-12)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == '__main__':
|
||
|
|
tfs = tuple(a for a in sys.argv[1:] if a in ('M15', 'H1', 'H4')) or ('H1',)
|
||
|
|
print("=== ADVERSE SELECTION AT THE BROKEN EDGE ===")
|
||
|
|
print(" prediction: real - placebo is NEGATIVE and grows more negative with phi.")
|
||
|
|
print(" a NEGATIVE number confirms the hypothesis.\n")
|
||
|
|
print(f" {'sym':>9}{'tf':>5}{'set':>10}" + "".join(f"{'phi='+str(p):>22}" for p in PHIS))
|
||
|
|
print(f" {'':>24}" + "".join(f"{'gap':>13}{'t':>9}" for p in PHIS))
|
||
|
|
acc = {p: {'original': [], 'new': []} for p in PHIS}
|
||
|
|
for s, tf, bk, f, kind in cells(tfs):
|
||
|
|
ev = wyckoff.breakouts(f, score=False)
|
||
|
|
if ev is None:
|
||
|
|
continue
|
||
|
|
line = f" {s:>9}{tf:>5}{kind:>10}"
|
||
|
|
any_ = False
|
||
|
|
for p in PHIS:
|
||
|
|
g = gap(bk, f, s, tf, p, ev)
|
||
|
|
if g is None:
|
||
|
|
line += f"{'-':>13}{'-':>9}"; continue
|
||
|
|
n, a, b, d, t = g
|
||
|
|
acc[p][kind].append(d)
|
||
|
|
any_ = True
|
||
|
|
line += f"{d:>+13.4f}{t:>+9.2f}"
|
||
|
|
if any_:
|
||
|
|
print(line)
|
||
|
|
print()
|
||
|
|
for p in PHIS:
|
||
|
|
o, nw = np.array(acc[p]['original']), np.array(acc[p]['new'])
|
||
|
|
al = np.concatenate([o, nw])
|
||
|
|
print(f" phi={p}: original {o.mean():+.4f} ({int((o<0).sum())}/{len(o)} negative)"
|
||
|
|
f" NEW {nw.mean():+.4f} ({int((nw<0).sum())}/{len(nw)} negative)"
|
||
|
|
f" all {al.mean():+.4f} ({int((al<0).sum())}/{len(al)})")
|
||
|
|
print("\n The NEW column is out of sample: those instruments had no hand in finding this.")
|