69 lines
3.3 KiB
Python
69 lines
3.3 KiB
Python
|
|
"""Retail's own side looked positive once the fill was fixed. Is that the pattern or the drift?
|
||
|
|
|
||
|
|
Retrial 1 killed the fade and inverted it: on USDJPY, XAUUSD and SP500 the fade loses 0.05
|
||
|
|
to 0.14 R because retail's trend-following setups are on the right side of instruments that
|
||
|
|
rose for the whole sample. Several cells show retail's own expR positive - SP500 H1 engulf
|
||
|
|
+0.113, XAUUSD H1 engulf +0.095 - and a POSITIVE base would be better than the near-zero one
|
||
|
|
step 2 is hunting for.
|
||
|
|
|
||
|
|
Before any of that is believed it has to beat the control that makes the boring explanation
|
||
|
|
explicit:
|
||
|
|
|
||
|
|
CONTROL = random bars drawn from the SAME trend-filter state, same direction, same entry
|
||
|
|
mechanics (a stop through the bar's extreme), same stop rule, same n.
|
||
|
|
|
||
|
|
Everything is held fixed except the candlestick itself. If retail's edge is really "buy the
|
||
|
|
break of any bar's high while the 20-MA is rising, on something that went up", the control
|
||
|
|
matches it and the pattern is worth nothing. That is the same shape of control that killed
|
||
|
|
"stops are a farmable magnet".
|
||
|
|
|
||
|
|
Reported on the NON-OVERLAPPING subset, and the difference carries its own standard error
|
||
|
|
rather than being eyeballed from two columns.
|
||
|
|
"""
|
||
|
|
import numpy as np, sys
|
||
|
|
sys.stdout.reconfigure(encoding='utf-8', errors='replace')
|
||
|
|
import fills, book, retrial
|
||
|
|
|
||
|
|
SYMS = ('EURUSD', 'USDJPY', 'XAUUSD', 'SP500')
|
||
|
|
|
||
|
|
|
||
|
|
def diff_t(a, b):
|
||
|
|
"""Welch t for the difference of two independent means."""
|
||
|
|
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("=== RETRIAL 2: is retail's trend side a PATTERN, or just drift? ===")
|
||
|
|
print(" control = same trend state, same direction, same entry, random bar.")
|
||
|
|
print(" 'excess' is pattern minus control on independent trades - the real claim.\n")
|
||
|
|
print(f" {'sym':>7}{'tf':>5}{'setup':>8}{'dir':>4}{'k':>3}"
|
||
|
|
f"{'n':>6}{'pattern':>9}{'t':>6}{'ctrl n':>7}{'control':>9}{'t':>6}"
|
||
|
|
f"{'EXCESS':>9}{'t':>6}")
|
||
|
|
tally = []
|
||
|
|
for sym in syms:
|
||
|
|
bk = fills.Book(sym)
|
||
|
|
for tf in ('M15', 'H1'):
|
||
|
|
f = book.frame(sym, tf, bk)
|
||
|
|
for k in (1.0, 2.0):
|
||
|
|
pat = retrial.retail_arm(sym, tf, k=k, bk=bk, f=f)
|
||
|
|
ctl = retrial.retail_arm(sym, tf, k=k, control=True, bk=bk, f=f)
|
||
|
|
cmap = {(nm, d): o for nm, d, o in ctl}
|
||
|
|
for nm, d, o in pat:
|
||
|
|
c = cmap.get((nm, d))
|
||
|
|
if c is None:
|
||
|
|
continue
|
||
|
|
A = o['R'][o['indep']]; B = c['R'][c['indep']]
|
||
|
|
ex = A.mean() - B.mean()
|
||
|
|
t = diff_t(A, B)
|
||
|
|
tally.append(ex)
|
||
|
|
print(f" {sym:>7}{tf:>5}{nm:>8}{d:>+4}{k:>3.0f}"
|
||
|
|
f"{len(A):>6}{A.mean():>+9.4f}{book.tstat(A):>+6.2f}"
|
||
|
|
f"{len(B):>7}{B.mean():>+9.4f}{book.tstat(B):>+6.2f}"
|
||
|
|
f"{ex:>+9.4f}{t:>+6.2f}")
|
||
|
|
ex = np.array(tally)
|
||
|
|
print(f"\n {len(ex)} cells mean excess {ex.mean():+.4f} "
|
||
|
|
f"positive {int((ex>0).sum())}/{len(ex)}")
|
||
|
|
print(" A pattern with real content clears its control in most cells and by a margin")
|
||
|
|
print(" that does not shrink when the sample is made independent.")
|