15-Minuten-Regel ganz abgeschaltet (adverse_15min_atr = 0)
User-Frage "vielleicht die auto close auf 30 min setzen?" -> Zeit-Achse
mitgemessen (backtest_adverse15_squeeze.py um Zeitpunkt und zweite
Population erweitert): 15/30/45/60 min x 0,5/0,8xATR, Squeeze- UND
Wave-Signal-Entries, kanonischer Exit, Echtkosten, 2 Halbjahre.
Zeit Schwelle Squeeze H1/H2 Wave H1/H2
15 0,5 -18 / -34 -25 / -41 (war live)
30 0,5 -20 / -35 -22 / -13
45 0,8 -12 / -18 -3 / -7
60 0,8 -8 / -10 -3 / -3
ALLE 16 Kombinationen sind in BEIDEN Haelften negativ. Die Regel wird nur
monoton weniger schaedlich, je spaeter und lockerer sie prueft - die
"beste" Variante ist praktisch die, die nie feuert. 30 min haette den
Schaden halbiert, nicht beendet.
Damit ist auch meine Einschaetzung von vor einer Stunde korrigiert ("auf
dem Auto-Signal-Pfad ~neutral"): sie stuetzte sich auf
backtest_auto_signal.py mit eigenem Exit-Modell (+0,001 vs +0,026); mit dem
kanonischen Exit sind es -25/-41. Sechster Fall desselben Musters an einem
Tag.
Schutz-Stack bleibt vollstaendig: Broker-SL 2xATR + Trailing + Time-Stop
120 min. Die Squeeze-Ausnahme bleibt im Code, falls die Regel je wieder
eingeschaltet wird.
Config-Waechter-Anker auf 0 gezogen, mit Begruendung im Eintrag.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6cf2730dc3
commit
00ca2406f1
@@ -990,6 +990,28 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche:
|
|||||||
weil gemessen nicht tragfähig; zeigt die Schwelle an), neustart-fest via
|
weil gemessen nicht tragfähig; zeigt die Schwelle an), neustart-fest via
|
||||||
`runtime_state.json`. **B5-Pflicht:** Live-ØR/PF gegen die Backtest-Erwartung halten
|
`runtime_state.json`. **B5-Pflicht:** Live-ØR/PF gegen die Backtest-Erwartung halten
|
||||||
(H2-Regime +0,14 vs H1-Regime −0,05) — driftet es weg, **zurückbauen** (`=false`).
|
(H2-Regime +0,14 vs H1-Regime −0,05) — driftet es weg, **zurückbauen** (`=false`).
|
||||||
|
- **⚠⚠ 15-MINUTEN-REGEL GANZ ABGESCHALTET (`adverse_15min_atr = 0`, 2026-07-31,
|
||||||
|
User-Entscheidung nach der Messung).** Auf die User-Frage „vielleicht die Auto-Close
|
||||||
|
auf 30 min setzen?" wurde die **ZEIT-Achse** mitgemessen
|
||||||
|
(`backtest_adverse15_squeeze.py`, 15/30/45/60 min × 0,5/0,8×ATR, BEIDE Populationen,
|
||||||
|
kanonischer Exit, Echtkosten, 2 Halbjahre):
|
||||||
|
| Zeitpunkt | Schwelle | Squeeze Δ H1/H2 | Wave Δ H1/H2 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| 15 min | 0,5 | −18 / −34 ← war live | −25 / −41 |
|
||||||
|
| 30 min | 0,5 | −20 / −35 | −22 / −13 |
|
||||||
|
| 45 min | 0,8 | −12 / −18 | −3 / −7 |
|
||||||
|
| 60 min | 0,8 | −8 / −10 | −3 / −3 |
|
||||||
|
**ALLE 16 Kombinationen sind in BEIDEN Hälften negativ** — die Regel wird nur
|
||||||
|
*monoton weniger schädlich*, je später und lockerer sie prüft. Die „beste" Variante
|
||||||
|
ist praktisch die, die nie feuert. **Es gibt keine Einstellung, bei der sie hilft**
|
||||||
|
→ 30 min hätte den Schaden halbiert, nicht beendet. Deshalb ganz aus.
|
||||||
|
⚠ **Damit ist auch die frühere Einschätzung „auf dem Auto-Signal-Pfad ~neutral"
|
||||||
|
korrigiert**: sie stützte sich auf `backtest_auto_signal.py` (eigenes Exit-Modell,
|
||||||
|
+0,001 vs +0,026); mit dem kanonischen Exit sind es −25/−41. Sechster Fall desselben
|
||||||
|
Musters an einem Tag (gemessen unter X, betrieben unter Y).
|
||||||
|
Der Schutz-Stack bleibt vollständig: **Broker-SL 2×ATR + Trailing + Time-Stop 120 min**.
|
||||||
|
Die Squeeze-Ausnahme (unten) bleibt im Code — falls die Regel je reaktiviert wird,
|
||||||
|
gilt sie weiterhin nicht für den Squeeze.
|
||||||
- **⚠ 15-MINUTEN-REGEL: SQUEEZE-TRADES AUSGENOMMEN (gemessen
|
- **⚠ 15-MINUTEN-REGEL: SQUEEZE-TRADES AUSGENOMMEN (gemessen
|
||||||
`backtest_adverse15_squeeze.py`, 2026-07-31).** Die Schwelle 0,5×ATR wurde in
|
`backtest_adverse15_squeeze.py`, 2026-07-31).** Die Schwelle 0,5×ATR wurde in
|
||||||
`backtest_auto_signal.py` auf **WAVE-SIGNAL-Entries** kalibriert und danach auf ALLE
|
`backtest_auto_signal.py` auf **WAVE-SIGNAL-Entries** kalibriert und danach auf ALLE
|
||||||
|
|||||||
@@ -66,8 +66,9 @@ def squeeze_signals(H, L, C, AT, lo, hi):
|
|||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
def run(sig, H, L, C, SP, adverse=None):
|
def run(sig, H, L, C, SP, adverse=None, minutes=15):
|
||||||
"""`adverse` = Schwelle in ×ATR (None = Regel aus)."""
|
"""`adverse` = Schwelle in ×ATR (None = Regel aus), `minutes` = Prüfzeitpunkt."""
|
||||||
|
bars = max(1, minutes // 5)
|
||||||
Rs = []
|
Rs = []
|
||||||
for (j, d, atr, lvl) in sig:
|
for (j, d, atr, lvl) in sig:
|
||||||
cost = (SP[j] if SP[j] > 0 else 0.0225) / atr
|
cost = (SP[j] if SP[j] > 0 else 0.0225) / atr
|
||||||
@@ -75,13 +76,41 @@ def run(sig, H, L, C, SP, adverse=None):
|
|||||||
if adverse is not None:
|
if adverse is not None:
|
||||||
j0 = j + 1
|
j0 = j + 1
|
||||||
|
|
||||||
def hook(k, prof_atr, _j0=j0, _x=adverse):
|
def hook(k, prof_atr, _j0=j0, _x=adverse, _b=bars):
|
||||||
# 1× genau beim 15-Min-Zeitpunkt prüfen (wie live)
|
# 1× genau zum Prüfzeitpunkt (wie live: einmal je Ticket)
|
||||||
return (k - _j0) == _BARS_15MIN - 1 and prof_atr <= -_x
|
return (k - _j0) == _b - 1 and prof_atr <= -_x
|
||||||
Rs.append(simulate(lvl, d, atr, H, L, C, j + 1, LIVE, stop_when=hook) - cost)
|
Rs.append(simulate(lvl, d, atr, H, L, C, j + 1, LIVE, stop_when=hook) - cost)
|
||||||
return Rs
|
return Rs
|
||||||
|
|
||||||
|
|
||||||
|
def wave_signals(H, L, C, AT, lo, hi, step=6):
|
||||||
|
"""WAVE-Signal-Entries — die Population, auf der die Regel kalibriert WURDE
|
||||||
|
und auf der sie live noch gilt (Auto-Signal-Pfad)."""
|
||||||
|
from core.analysis import calc_trend_angle
|
||||||
|
from core.wave_rec import (_EMA_FAST, _EMA_SLOW, _ANGLE_LR, _ANGLE_DEAD,
|
||||||
|
_REVERSAL_STRETCH, _STRETCH_MAX)
|
||||||
|
def ema(v, p):
|
||||||
|
k = 2.0 / (p + 1); o = []; e = v[0]
|
||||||
|
for i, x in enumerate(v):
|
||||||
|
e = x if i == 0 else x * k + e * (1 - k); o.append(e)
|
||||||
|
return o
|
||||||
|
EF = ema(C, _EMA_FAST); ES = ema(C, _EMA_SLOW)
|
||||||
|
out = []
|
||||||
|
for i in range(max(lo, _N_BARS), min(hi, len(C) - LIVE.max_hold - 1), step):
|
||||||
|
atr = AT[i]
|
||||||
|
if not atr or atr < _ATRMIN:
|
||||||
|
continue
|
||||||
|
stretch = (C[i] - ES[i]) / atr
|
||||||
|
ang = calc_trend_angle(C[i - _ANGLE_LR - 2:i], _ANGLE_LR) - 90.0
|
||||||
|
d = 0
|
||||||
|
if stretch <= -_REVERSAL_STRETCH and ang >= _ANGLE_DEAD: d = 1
|
||||||
|
elif stretch >= _REVERSAL_STRETCH and ang <= -_ANGLE_DEAD: d = -1
|
||||||
|
elif abs(stretch) < _STRETCH_MAX: d = 1 if EF[i] > ES[i] else -1 if EF[i] < ES[i] else 0
|
||||||
|
if d:
|
||||||
|
out.append((i, d, atr, C[i]))
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
def st(Rs):
|
def st(Rs):
|
||||||
if not Rs:
|
if not Rs:
|
||||||
return " —"
|
return " —"
|
||||||
@@ -115,17 +144,31 @@ def main():
|
|||||||
for lbl, _, _ in halves:
|
for lbl, _, _ in halves:
|
||||||
print(f" {lbl}: {len(SIG[lbl])} Squeeze-Entries")
|
print(f" {lbl}: {len(SIG[lbl])} Squeeze-Entries")
|
||||||
|
|
||||||
base = {}
|
WAV = {lbl: wave_signals(H, L, C, AT, a, b) for lbl, a, b in halves}
|
||||||
for name, adv in (("OHNE Regel", None), ("0,3×ATR", 0.3),
|
for lbl, _, _ in halves:
|
||||||
("0,5×ATR ← live", 0.5), ("0,8×ATR", 0.8), ("1,2×ATR", 1.2)):
|
print(f" {lbl}: {len(WAV[lbl])} Wave-Signal-Entries")
|
||||||
print(f"\n{name}")
|
|
||||||
|
# ZEIT-Achse mitmessen (User-Frage 2026-07-31 „vielleicht die auto close auf
|
||||||
|
# 30 min setzen?"): nicht nur WIE WEIT gegen die Richtung, sondern auch WANN
|
||||||
|
# geprüft wird. Beide Populationen, weil die Regel auf der einen kalibriert
|
||||||
|
# wurde und auf der anderen (bis heute) angewandt.
|
||||||
|
for pop, SETS in (("SQUEEZE-Entries", SIG), ("WAVE-SIGNAL-Entries", WAV)):
|
||||||
|
print(f"\n{'=' * 92}\n {pop}\n{'=' * 92}")
|
||||||
|
base = {}
|
||||||
for lbl, _, _ in halves:
|
for lbl, _, _ in halves:
|
||||||
Rs = run(SIG[lbl], H, L, C, SP, adverse=adv)
|
Rs0 = run(SETS[lbl], H, L, C, SP, adverse=None)
|
||||||
s = sum(Rs)
|
base[lbl] = sum(Rs0)
|
||||||
if adv is None:
|
print(f" {lbl} OHNE Regel {st(Rs0)}")
|
||||||
base[lbl] = s
|
print(f"\n {'Zeitpunkt':<12}{'Schwelle':<12}"
|
||||||
d = f" Δ ohne Regel {s - base.get(lbl, 0):+.0f}" if adv is not None else ""
|
+ "".join(f"{l[:2]:>11}" for l, _, _ in halves) + " (Δ gegen OHNE Regel)")
|
||||||
print(f" {lbl} {st(Rs)}{d}")
|
for mins in (15, 30, 45, 60):
|
||||||
|
for adv in (0.5, 0.8):
|
||||||
|
cells = []
|
||||||
|
for lbl, _, _ in halves:
|
||||||
|
tot = sum(run(SETS[lbl], H, L, C, SP, adverse=adv, minutes=mins))
|
||||||
|
cells.append(f"{tot - base[lbl]:>+11.0f}")
|
||||||
|
mark = " ← live" if (mins == 15 and adv == 0.5) else ""
|
||||||
|
print(f" {mins:>4} min {adv:>5.1f}×ATR " + "".join(cells) + mark)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|||||||
@@ -194,10 +194,14 @@ CONFIG_DEPS = [
|
|||||||
"P(DD>80 %)). Ändert sich er, ändert sich das Ruin-Risiko.",
|
"P(DD>80 %)). Ändert sich er, ändert sich das Ruin-Risiko.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "adverse_15min_atr", "test": "backtest_auto_signal.py (15-Min-Achse)",
|
"key": "adverse_15min_atr", "test": "backtest_adverse15_squeeze.py",
|
||||||
"validated": "0.5",
|
"validated": "0",
|
||||||
"why": "0,5 war die beste Regel-Variante; 0,0 (sofort im Minus schliessen) war "
|
"why": "0 = AUS (2026-07-31). Nachgemessen mit dem kanonischen Exit über die "
|
||||||
"die SCHLECHTESTE (WR bricht 39→31 %). Andere Werte sind ungemessen.",
|
"ZEIT- und Schwellen-Achse (15/30/45/60 min × 0,5/0,8×ATR) auf BEIDEN "
|
||||||
|
"Populationen: **alle 16 Kombinationen sind in beiden Hälften negativ**, "
|
||||||
|
"nur monoton weniger schädlich je später/lockerer. Es gibt keine "
|
||||||
|
"Einstellung, bei der die Regel hilft. Wiedereinschalten wäre nicht "
|
||||||
|
"gedeckt — der Schutz läuft über Broker-SL 2×ATR, Trailing und Time-Stop.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "auto_signal_min_conf", "test": "backtest_auto_signal.py",
|
"key": "auto_signal_min_conf", "test": "backtest_auto_signal.py",
|
||||||
|
|||||||
Reference in New Issue
Block a user