Legacy-Recheck vervollstaendigt: Bounce und ER-Chop-Gate nachgerechnet
backtest_legacy_recheck.py um zwei Abschnitte erweitert (Reversal-Flag und
Efficiency Ratio je Trade), damit alle vier Befunde abgedeckt sind, die auf
dem vereinfachten Legacy-Exit ruhten.
BOUNCE / REVERSAL - relative Aussage haelt, absolute NICHT:
H1 Reversal -0,034 (PF 0,93) vs Trend -0,174 (PF 0,68)
H2 Reversal +0,029 (PF 1,06) vs Trend -0,073 (PF 0,86)
Reversal schlaegt Trend in BEIDEN Haelften (+0,140/+0,102) - robust. Aber
die dokumentierte Kennzahl "OeR +0,185 / PF 1,35 / 70 % Treffer"
REPRODUZIERT NICHT: mit echtem Exit + Echtkosten liegt das Setup bei
~Breakeven. Die alten Werte stammen aus dem vereinfachten Exit ohne Kosten.
Das Setup bleibt sinnvoll als nachrangiges Zweitsignal (so ist es live auch
eingebaut), ist aber kein +0,185-Ertragsbringer.
ER-CHOP-GATE - Ablehnung BESTAETIGT: alle vier ER-Baender liegen gleichauf
(H1 -0,137..-0,172, H2 -0,049..-0,067). Die Efficiency Ratio trennt auch mit
dem echten Exit nicht. Gate bleibt zu Recht verworfen.
Damit sind alle sechs Legacy-Skripte abgedeckt: EIA bestaetigt, Dead-Hours
nicht selektiv, Bounce nur relativ, ER-Gate zu Recht verworfen.
Einschraenkung unveraendert: der Recheck handelt die UNGEGATETE EMA-Richtung
(ohne min_conf, Breakout-Bestaetigung, HTF-Filter, Raum-Gate) - fuer die
Vergleiche neutral, die absoluten Werte sind nicht das Live-Signal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
bb17ecff0a
commit
fe5c2aae0a
@@ -2050,6 +2050,16 @@ konstant; (d) es gab **keine Telemetrie über die Entscheidung selbst**.
|
|||||||
Stunden herausgehoben; wenn fast alles negativ ist, ist diese Auswahl nicht mehr
|
Stunden herausgehoben; wenn fast alles negativ ist, ist diese Auswahl nicht mehr
|
||||||
gestützt. (Praktisch folgenlos, weil `dead_hours` ohnehin leer ist — aber eine
|
gestützt. (Praktisch folgenlos, weil `dead_hours` ohnehin leer ist — aber eine
|
||||||
Reaktivierung auf der alten Begründung wäre nicht gedeckt.)
|
Reaktivierung auf der alten Begründung wäre nicht gedeckt.)
|
||||||
|
· ⚠ **BOUNCE/Reversal — relative Aussage hält, absolute NICHT.** Reversal schlägt
|
||||||
|
Trend in BEIDEN Hälften (H1 −0,034 vs −0,174 · H2 **+0,029** vs −0,073, also
|
||||||
|
+0,140/+0,102) — robust. **Aber die dokumentierte Kennzahl „ØR +0,185 · PF 1,35 ·
|
||||||
|
70 % Treffer" REPRODUZIERT NICHT**: mit echtem Exit + Echtkosten liegt das Setup bei
|
||||||
|
~**Breakeven** (PF 0,93/1,06). Die alten Werte stammen aus dem vereinfachten Exit
|
||||||
|
OHNE Kosten. Das Setup bleibt sinnvoll als *nachrangiges, markiertes* Zweitsignal
|
||||||
|
(so ist es live auch eingebaut), aber es ist **kein +0,185-Ertragsbringer**.
|
||||||
|
· ✅ **ER-CHOP-GATE — Ablehnung BESTÄTIGT.** Alle vier ER-Bänder liegen gleichauf
|
||||||
|
(H1 −0,137…−0,172 · H2 −0,049…−0,067); die Efficiency Ratio trennt auch mit dem
|
||||||
|
echten Exit nicht. Gate bleibt zu Recht verworfen.
|
||||||
⚠ **Einschränkung des Rechecks (selbst benannt):** er handelt die **ungegatete**
|
⚠ **Einschränkung des Rechecks (selbst benannt):** er handelt die **ungegatete**
|
||||||
EMA-Richtung — ohne Mindest-Konfidenz, Breakout-Bestätigung, HTF-Filter und
|
EMA-Richtung — ohne Mindest-Konfidenz, Breakout-Bestätigung, HTF-Filter und
|
||||||
Raum-Gate. Für den VERGLEICH (Fenster gegen Rest, Stunde gegen Stunde) ist das
|
Raum-Gate. Für den VERGLEICH (Fenster gegen Rest, Stunde gegen Stunde) ist das
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ from core.wave_rec import (_EMA_FAST, _EMA_SLOW, _N_BARS, _ANGLE_LR, _ANGLE_DEAD
|
|||||||
_REVERSAL_STRETCH, _STRETCH_MAX)
|
_REVERSAL_STRETCH, _STRETCH_MAX)
|
||||||
|
|
||||||
_ATRMIN = 0.12
|
_ATRMIN = 0.12
|
||||||
|
NL = chr(10)
|
||||||
_BROKER_OFF_H = 3 # Brokerzeit = UTC+3
|
_BROKER_OFF_H = 3 # Brokerzeit = UTC+3
|
||||||
_BERLIN_OFF_H = 2 # Sommerzeit (die History liegt im Sommerhalbjahr)
|
_BERLIN_OFF_H = 2 # Sommerzeit (die History liegt im Sommerhalbjahr)
|
||||||
|
|
||||||
@@ -64,8 +65,18 @@ def _berlin(ts_broker: int) -> datetime:
|
|||||||
- timedelta(hours=_BROKER_OFF_H) + timedelta(hours=_BERLIN_OFF_H)
|
- timedelta(hours=_BROKER_OFF_H) + timedelta(hours=_BERLIN_OFF_H)
|
||||||
|
|
||||||
|
|
||||||
|
def _er(C, i, n=14):
|
||||||
|
"""Efficiency Ratio: Netto-Weg / Summe der Einzelschritte. 1 = glatter Trend,
|
||||||
|
~0 = Chop. Grundlage des verworfenen ER-Chop-Gates (`backtest_chopgate.py`)."""
|
||||||
|
if i - n < 1:
|
||||||
|
return None
|
||||||
|
net = abs(C[i] - C[i - n])
|
||||||
|
path = sum(abs(C[k] - C[k - 1]) for k in range(i - n + 1, i + 1))
|
||||||
|
return (net / path) if path > 0 else 0.0
|
||||||
|
|
||||||
|
|
||||||
def trades(T, H, L, C, EF, ES, AT, SP, lo, hi, step=2):
|
def trades(T, H, L, C, EF, ES, AT, SP, lo, hi, step=2):
|
||||||
"""→ [(berlin_dt, R_netto)] mit dem ECHTEN Exit + Echtkosten."""
|
"""→ [(berlin_dt, R_netto, is_reversal, er)] mit dem ECHTEN Exit + Echtkosten."""
|
||||||
TH = _REVERSAL_STRETCH; out = []
|
TH = _REVERSAL_STRETCH; out = []
|
||||||
for i in range(max(lo, _N_BARS), min(hi, len(C) - LIVE.max_hold - 1), step):
|
for i in range(max(lo, _N_BARS), min(hi, len(C) - LIVE.max_hold - 1), step):
|
||||||
atr = AT[i]
|
atr = AT[i]
|
||||||
@@ -74,15 +85,15 @@ def trades(T, H, L, C, EF, ES, AT, SP, lo, hi, step=2):
|
|||||||
atr = max(atr, _ATRMIN); es = ES[i]; ef = EF[i]
|
atr = max(atr, _ATRMIN); es = ES[i]; ef = EF[i]
|
||||||
stretch = (C[i] - es) / atr
|
stretch = (C[i] - es) / atr
|
||||||
ang = calc_trend_angle(C[i - _ANGLE_LR - 2:i], _ANGLE_LR); ad = ang - 90.0
|
ang = calc_trend_angle(C[i - _ANGLE_LR - 2:i], _ANGLE_LR); ad = ang - 90.0
|
||||||
d = 0
|
d = 0; rev = False
|
||||||
if stretch <= -TH and ad >= _ANGLE_DEAD: d = 1
|
if stretch <= -TH and ad >= _ANGLE_DEAD: d, rev = 1, True
|
||||||
elif stretch >= TH and ad <= -_ANGLE_DEAD: d = -1
|
elif stretch >= TH and ad <= -_ANGLE_DEAD: d, rev = -1, True
|
||||||
elif abs(stretch) < _STRETCH_MAX: d = 1 if ef > es else -1 if ef < es else 0
|
elif abs(stretch) < _STRETCH_MAX: d = 1 if ef > es else -1 if ef < es else 0
|
||||||
if not d:
|
if not d:
|
||||||
continue
|
continue
|
||||||
cost = (SP[i] if SP[i] > 0 else 0.0225) / atr
|
cost = (SP[i] if SP[i] > 0 else 0.0225) / atr
|
||||||
R = simulate(C[i], d, atr, H, L, C, i + 1, LIVE) - cost
|
R = simulate(C[i], d, atr, H, L, C, i + 1, LIVE) - cost
|
||||||
out.append((_berlin(int(T[i])), R))
|
out.append((_berlin(int(T[i])), R, rev, _er(C, i)))
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
@@ -126,9 +137,9 @@ def main():
|
|||||||
print(" 1) EIA-BLACKOUT (Mi 15:30–16:30 Berlin) — blockt live echte Trades")
|
print(" 1) EIA-BLACKOUT (Mi 15:30–16:30 Berlin) — blockt live echte Trades")
|
||||||
print("=" * 90)
|
print("=" * 90)
|
||||||
for lbl, _, _ in halves:
|
for lbl, _, _ in halves:
|
||||||
inw = [r for t, r in data[lbl]
|
inw = [r for t, r, _rv, _e in data[lbl]
|
||||||
if t.weekday() == 2 and (15, 30) <= (t.hour, t.minute) < (16, 30)]
|
if t.weekday() == 2 and (15, 30) <= (t.hour, t.minute) < (16, 30)]
|
||||||
out = [r for t, r in data[lbl]
|
out = [r for t, r, _rv, _e in data[lbl]
|
||||||
if not (t.weekday() == 2 and (15, 30) <= (t.hour, t.minute) < (16, 30))]
|
if not (t.weekday() == 2 and (15, 30) <= (t.hour, t.minute) < (16, 30))]
|
||||||
print(f" {lbl} im Fenster : {stat(inw)}")
|
print(f" {lbl} im Fenster : {stat(inw)}")
|
||||||
print(f" {lbl} ausserhalb : {stat(out)}")
|
print(f" {lbl} ausserhalb : {stat(out)}")
|
||||||
@@ -144,8 +155,8 @@ def main():
|
|||||||
print(f" {'Std':<5}{'H1 n':>7}{'H1 ØR':>9}{'H2 n':>7}{'H2 ØR':>9} Urteil")
|
print(f" {'Std':<5}{'H1 n':>7}{'H1 ØR':>9}{'H2 n':>7}{'H2 ØR':>9} Urteil")
|
||||||
robust_neg, robust_pos = [], []
|
robust_neg, robust_pos = [], []
|
||||||
for h in range(24):
|
for h in range(24):
|
||||||
a = [r for t, r in data["H1"] if t.hour == h]
|
a = [r for t, r, _rv, _e in data["H1"] if t.hour == h]
|
||||||
b = [r for t, r in data["H2"] if t.hour == h]
|
b = [r for t, r, _rv, _e in data["H2"] if t.hour == h]
|
||||||
if len(a) < 30 or len(b) < 30:
|
if len(a) < 30 or len(b) < 30:
|
||||||
continue
|
continue
|
||||||
ma, mb = sum(a) / len(a), sum(b) / len(b)
|
ma, mb = sum(a) / len(a), sum(b) / len(b)
|
||||||
@@ -160,6 +171,37 @@ def main():
|
|||||||
print(" ⚠ Alt (vereinfachter Exit) waren 0–7 sowie 12 und 16 die Kandidaten.")
|
print(" ⚠ Alt (vereinfachter Exit) waren 0–7 sowie 12 und 16 die Kandidaten.")
|
||||||
print(" Deckt sich das? Falls nicht, ruht das Dead-Hours-Gate auf dem alten Exit.")
|
print(" Deckt sich das? Falls nicht, ruht das Dead-Hours-Gate auf dem alten Exit.")
|
||||||
|
|
||||||
|
# ── 3) BOUNCE / Reversal — AKTIVES Setup (WAVE_REV_*)
|
||||||
|
print(NL + "=" * 90)
|
||||||
|
print(" 3) BOUNCE / REVERSAL — aktives Setup, alt gemessen ØR +0,185 · PF 1,35")
|
||||||
|
print("=" * 90)
|
||||||
|
for lbl, _, _ in halves:
|
||||||
|
rev = [r for _t, r, rv, _e in data[lbl] if rv]
|
||||||
|
trd = [r for _t, r, rv, _e in data[lbl] if not rv]
|
||||||
|
print(f" {lbl} Reversal : {stat(rev)}")
|
||||||
|
print(f" {lbl} Trend : {stat(trd)}")
|
||||||
|
rr = [sum(1 for _t, _r, rv, _e in data[l] if rv) for l in ("H1", "H2")]
|
||||||
|
print(f"{NL} ⚠ Alt: ØR +0,185 / PF 1,35 / Treffer 70 % (vereinfachter Exit, ohne Kosten).")
|
||||||
|
print(f" Reversal-Anteil hier: {rr[0]} (H1) / {rr[1]} (H2) Trades.")
|
||||||
|
print(" Urteil: traegt das Setup mit dem ECHTEN Exit noch, und schlaegt es Trend?")
|
||||||
|
|
||||||
|
# ── 4) ER-CHOP-GATE — verworfen; haelt die Ablehnung?
|
||||||
|
print(NL + "=" * 90)
|
||||||
|
print(" 4) ER-CHOP-GATE (verworfen) — trennt Efficiency Ratio mit echtem Exit?")
|
||||||
|
print("=" * 90)
|
||||||
|
print(f" {'ER-Band':<14}{'H1 n':>7}{'H1 ØR':>9}{'H2 n':>7}{'H2 ØR':>9} Urteil")
|
||||||
|
bands = [(0.0, 0.15), (0.15, 0.30), (0.30, 0.50), (0.50, 1.01)]
|
||||||
|
for lo_e, hi_e in bands:
|
||||||
|
a = [r for _t, r, _rv, e in data["H1"] if e is not None and lo_e <= e < hi_e]
|
||||||
|
b = [r for _t, r, _rv, e in data["H2"] if e is not None and lo_e <= e < hi_e]
|
||||||
|
if len(a) < 50 or len(b) < 50:
|
||||||
|
continue
|
||||||
|
ma, mb = sum(a) / len(a), sum(b) / len(b)
|
||||||
|
v = "konsistent" if (ma - mb) * 0 == 0 and ((ma < 0) == (mb < 0)) else "kippt"
|
||||||
|
print(f" {lo_e:.2f}–{hi_e:<9.2f}{len(a):>7}{ma:>+9.3f}{len(b):>7}{mb:>+9.3f} {v}")
|
||||||
|
print(NL + " ⚠ Alt: Chop-Signale NICHT robust schlechter (H1 Trend leicht besser,")
|
||||||
|
print(" H2 umgekehrt) -> Gate verworfen. Bestaetigt sich das mit echtem Exit?")
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
Reference in New Issue
Block a user