Verlustbegrenzung: Notfall-Stop und HTF-Flip-Close gemessen - beide durchgefallen
User-Frage nach automatischem Notfall-Close (30 %?) und alternativ einem Flip-Close bei entgegengerichtetem Trend. 1) NOTFALL-STOP. 30 % waere ohnehin wirkungslos: Einsatz 670 EUR/Lot, Median-Verlust 20 EUR/Lot = 3 % der Margin. 30 % erreichen 1 % aller Verluste. Kontrafaktisch ueber 1022 echte Trades (MAE aus M5-Bars, 87 EUR/$/Lot aus den Trades selbst geschaetzt): ohne Stop +358 EUR 3 % -293 | 5 % -639 | 8 % -14 | 15 % -416 | 30 % -331 Keine Schwelle schlaegt "gar kein Stop". Nach Einstiegsart: bei "ohne Signal" sieht 8-10 % mit +298/+290 gut aus, aber beide Nachbarn kippen (-292 / -106) -> Rauschen. 2) FLIP-CLOSE AUF DEN HTF-TREND (backtest_flipclose_htf.py) - war nie gemessen. Alle sechs Varianten in BEIDEN Haelften schlechter: BASIS H1 -548 H2 -154 M30 ab +0,0R -629 -247 M30 ab +0,5R -574 -234 M30 ab +1,0R -549 -183 M30 auch im Minus -616 -327 M30+H1 ab +0,5R -570 -222 M30+H1 auch im Minus -616 -290 Die mildeste Variante ist die, die kaum feuert - exakt das Muster der 15-Minuten-Regel. Kontrolle: die Basis (-548/-154) reproduziert backtest_flipclose2.py (-537/-140), die Pipeline ist in Ordnung. Methodik: feste, geteilte Entry-Liste ueber alle Varianten. backtest_flipclose2.py laeuft nach jedem Exit bei xb+1 weiter, wodurch jede Variante eine andere Trade-Folge bekommt (der am 31.07. bei backtest_exit_combo.py korrigierte Fehler). Hier von vornherein vermieden. Mechanismus in allen Faellen derselbe: Trefferquote steigt (38->44 %, 42->51 %), Ertrag faellt = Gewinner-Kappen. Fuenfte unabhaengige Messung dieser Klasse, alle negativ. Nichts gebaut. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
59e9498237
commit
cef6646a17
@@ -4942,6 +4942,66 @@ Modell schliesst keine Trades.
|
|||||||
„die Rangfolge ist kaputt" ist **nicht** belegt; belegt ist nur die
|
„die Rangfolge ist kaputt" ist **nicht** belegt; belegt ist nur die
|
||||||
Basisraten-/Kalibrierungslücke.
|
Basisraten-/Kalibrierungslücke.
|
||||||
|
|
||||||
|
## ⚠⚠ VERLUSTBEGRENZUNG BEI „FALSCHEN" EINSTIEGEN — BEIDE IDEEN GEMESSEN, BEIDE DURCHGEFALLEN (2026-08-07)
|
||||||
|
|
||||||
|
User: „um meine Verluste bei falschen Einstiegen zu begrenzen würde ich gerne den
|
||||||
|
Notfall-Close automatisch setzen — 30 %?" und „oder doch lieber ein Flip-Close
|
||||||
|
bei entgegengerichtetem Trend?"
|
||||||
|
|
||||||
|
**(1) AUTOMATISCHER NOTFALL-STOP — 30 % wäre ohnehin wirkungslos gewesen.**
|
||||||
|
Maßstab zuerst: Einsatz **670 €/Lot**, Median-Verlust **20 €/Lot = 3 % der
|
||||||
|
Margin**. 30 % (=201 €/Lot) erreichen **1 %** aller Verluste.
|
||||||
|
**Kontrafaktisch über 1.022 echte Trades** (MAE aus M5-Bars zwischen Ein- und
|
||||||
|
Ausstieg; 87 €/$/Lot als Median aus den Trades selbst geschätzt):
|
||||||
|
| Schwelle | gefeuert | Σ P&L | Δ gegen IST |
|
||||||
|
|---|---|---|---|
|
||||||
|
| **ohne Stop (IST)** | — | **+358 €** | — |
|
||||||
|
| 3 % | 492 | +65 € | −293 € |
|
||||||
|
| 5 % | 317 | −280 € | −639 € |
|
||||||
|
| 8 % | 165 | +345 € | −14 € |
|
||||||
|
| 15 % | 70 | −58 € | −416 € |
|
||||||
|
| 30 % | 28 | +27 € | −331 € |
|
||||||
|
**Keine Schwelle schlägt „gar kein Stop".** Nach Einstiegsart (Δ gegen IST):
|
||||||
|
mit Signal −162…−278 · gegen Signal −69…−148 · **ohne Signal −292 / +298 / +290
|
||||||
|
/ −106** (5/8/10/15 %). Die +298 sehen gut aus, aber **beide Nachbarn kippen** →
|
||||||
|
Rauschen, dieselbe Regel, an der ORB und die SMC-Sweeps gescheitert sind.
|
||||||
|
|
||||||
|
**(2) FLIP-CLOSE AUF DEN HTF-TREND — war nie gemessen, jetzt schon
|
||||||
|
(`backtest_flipclose_htf.py`).** Abzugrenzen vom Flip auf das
|
||||||
|
**Empfehlungs**-Signal (gemessen, am 05.08. abgeschaltet): der HTF ist träger,
|
||||||
|
dreht seltener, und als FILTER ist er belegt (Edge ×2). Als EXIT nicht:
|
||||||
|
| Variante | H1 ΣR (Δ) | H2 ΣR (Δ) |
|
||||||
|
|---|---|---|
|
||||||
|
| **BASIS (kein Flip)** | **−548** | **−154** |
|
||||||
|
| M30 dagegen, ab +0,0R | −629 (−80) | −247 (−93) |
|
||||||
|
| M30 dagegen, ab +0,5R | −574 (−25) | −234 (−79) |
|
||||||
|
| M30 dagegen, ab +1,0R | −549 (−0) | −183 (−29) |
|
||||||
|
| M30 dagegen, auch im Minus | −616 (−68) | −327 (−172) |
|
||||||
|
| M30+H1, ab +0,5R | −570 (−22) | −222 (−67) |
|
||||||
|
| M30+H1, auch im Minus | −616 (−68) | −290 (−136) |
|
||||||
|
**Alle sechs Varianten in BEIDEN Hälften schlechter.** Die „mildeste" ist die,
|
||||||
|
die kaum feuert (ab +1,0R, Δ −0/−29) — exakt das Muster der 15-Minuten-Regel.
|
||||||
|
✅ **Kontrolle:** die Basis (−548/−154) reproduziert `backtest_flipclose2.py`
|
||||||
|
(−537/−140) — die Pipeline ist in Ordnung.
|
||||||
|
⚠ Methodik: **feste, geteilte Entry-Liste** über alle Varianten.
|
||||||
|
`backtest_flipclose2.py` läuft nach jedem Exit bei `xb+1` weiter, wodurch jede
|
||||||
|
Variante eine ANDERE Trade-Folge bekommt (der am 31.07. bei
|
||||||
|
`backtest_exit_combo.py` korrigierte Fehler). Hier von vornherein vermieden.
|
||||||
|
|
||||||
|
⚠⚠ **DER MECHANISMUS IST IN ALLEN FÄLLEN DERSELBE: Trefferquote STEIGT
|
||||||
|
(38→44 %, 42→51 %), Ertrag FÄLLT = Gewinner-Kappen.** Ein Früh-Ausstieg kappt
|
||||||
|
einige Trades vor dem vollen SL, schneidet aber weit öfter Trades ab, die sich
|
||||||
|
erholt hätten. Damit ist es die **fünfte** unabhängige Messung dieser Klasse
|
||||||
|
(15-Minuten-Regel · `backtest_adverse_nosignal` · Flip auf das Signal ·
|
||||||
|
Notfall-Stop · Flip auf den HTF-Trend) — **alle negativ.**
|
||||||
|
|
||||||
|
✅ **Was stattdessen belegt ist:** der Verlust-Hebel liegt in der **SL-Breite**
|
||||||
|
(live 2,0×ATR_M15 ≈ 3,6×ATR_M5, Worst bis −5,6×ATR; per Broker-SL geschlossene
|
||||||
|
Trades hätten mit dem kanonischen Exit **1.229 €** weniger verloren) und damit
|
||||||
|
im **Sizing**, nicht im Exit. Gegen „falsche Einstiege" ist die gemessene Bremse
|
||||||
|
das **Veto** (gegen das Signal −6,60 €/Lot, beidhälftig) — es steht bereits im
|
||||||
|
Order-Dialog. **Nichts gebaut.**
|
||||||
|
|
||||||
## ⚠⚠ DIE PRÜFUNG HING AM COMMIT, NICHT AM DEPLOYMENT — behoben 2026-08-07
|
## ⚠⚠ DIE PRÜFUNG HING AM COMMIT, NICHT AM DEPLOYMENT — behoben 2026-08-07
|
||||||
|
|
||||||
User-Frage „wird die Pipeline bei jedem Deployment ausgeführt?". **Antwort war
|
User-Frage „wird die Pipeline bei jedem Deployment ausgeführt?". **Antwort war
|
||||||
|
|||||||
@@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Flip-Close auf dem HÖHEREN TREND (M30 / H1) — trägt er als EXIT?
|
||||||
|
|
||||||
|
ANLASS (2026-08-07, User: „oder doch lieber ein Flip-Close bei entgegen-
|
||||||
|
gerichtetem Trend?"). Zu unterscheiden sind ZWEI Dinge:
|
||||||
|
· Flip auf das EMPFEHLUNGS-Signal — gemessen (`backtest_flipclose2.py`), in
|
||||||
|
JEDER Variante und BEIDEN Hälften schlechter, am 05.08. abgeschaltet.
|
||||||
|
Mechanik: die nachlaufende EMA dreht oft mitten im Pullback → Gewinner-Kappen.
|
||||||
|
· Flip auf den HTF-TREND (M30/H1) — **war nie gemessen**. Der HTF ist träger,
|
||||||
|
dreht viel seltener, und als FILTER ist er im Projekt belegt (Edge ×2). Ob er
|
||||||
|
auch als EXIT trägt, ist damit keineswegs entschieden.
|
||||||
|
|
||||||
|
⚠⚠ ENTSCHEIDUNGSREGEL, VORAB FESTGELEGT:
|
||||||
|
Eine Variante gilt nur dann als besser, wenn sie
|
||||||
|
(1) den ΣR in BEIDEN Halbjahren erhöht, UND
|
||||||
|
(2) den Worst-Case nicht verschlechtert, UND
|
||||||
|
(3) bei den Nachbar-Einstellungen (minR) nicht das Vorzeichen kippt.
|
||||||
|
Sonst: kein Einbau. Punkt (3), weil in diesem Projekt schon mehrfach eine
|
||||||
|
einzelne Zelle gut aussah, deren Nachbarn kippten (ORB, SMC-Sweeps, und heute
|
||||||
|
der Notfall-Stop bei 8 % gegen −292/−106 bei 5 %/15 %).
|
||||||
|
|
||||||
|
⚠ FESTE, GETEILTE ENTRY-LISTE. `backtest_flipclose2.py` lässt die sequentielle
|
||||||
|
Sim nach jedem Exit bei `xb+1` weiterlaufen — dadurch bekommt JEDE Variante eine
|
||||||
|
andere Trade-Folge (steigt eine früher aus, verschiebt sich alles Nachfolgende)
|
||||||
|
und die Zahlen sind nicht vergleichbar. Genau dieser Fehler wurde am 31.07. bei
|
||||||
|
`backtest_exit_combo.py` schon einmal korrigiert; hier wird er von vornherein
|
||||||
|
vermieden: alle Varianten laufen auf DENSELBEN Einstiegen.
|
||||||
|
|
||||||
|
Exit-Kern = `core/exit_model.simulate()` mit LIVE-Parametern (geteilte Quelle,
|
||||||
|
kein Nachbau) + `stop_when`-Hook für den Flip. Kosten = echter Bar-Spread/ATR.
|
||||||
|
|
||||||
|
Aufruf: python backtest_flipclose_htf.py [n_bars] (Default 80000)
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import MetaTrader5 as mt5
|
||||||
|
|
||||||
|
from backtest_auto_signal import _atr_series, _ema_series, _htf_signs
|
||||||
|
# ⚠ `_ATRMIN` aus `backtest_flipclose2` uebernehmen, NICHT neu setzen — der
|
||||||
|
# Vergleich mit dem dortigen Befund gilt nur bei identischem ATR-Floor.
|
||||||
|
from backtest_flipclose2 import _ATRMIN, signal_series
|
||||||
|
from core.exit_model import LIVE, simulate
|
||||||
|
from core.wave_rec import _EMA_FAST, _EMA_SLOW, _N_BARS
|
||||||
|
|
||||||
|
_M30_STEP = 6 # 6 M5-Bars = M30
|
||||||
|
_H1_STEP = 12 # 12 M5-Bars = H1
|
||||||
|
|
||||||
|
|
||||||
|
def entries(sig, lo, hi, H, L, C, AT, SP):
|
||||||
|
"""EINE feste Einstiegsliste, sequentiell mit dem BASIS-Exit ermittelt.
|
||||||
|
|
||||||
|
⚠ Bewusst mit der Basis (ohne Flip) bestimmt: nur so handeln alle Varianten
|
||||||
|
dieselben Trades und der Vergleich misst den EXIT, nicht eine verschobene
|
||||||
|
Trade-Folge."""
|
||||||
|
out = []
|
||||||
|
i = lo
|
||||||
|
while i < hi:
|
||||||
|
d = sig[i]
|
||||||
|
if d == 0:
|
||||||
|
i += 1
|
||||||
|
continue
|
||||||
|
atr = max(AT[i] or 0, _ATRMIN)
|
||||||
|
kosten = (SP[i] if SP[i] > 0 else 0.0225) / atr
|
||||||
|
_, xb = simulate(C[i], d, atr, H, L, C, i + 1, LIVE, ret_bar=True)
|
||||||
|
out.append((i, d, atr, kosten))
|
||||||
|
i = xb + 1
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
def lauf(ein, H, L, C, htf, h1, *, flip=None, min_r=0.0, auch_im_minus=False):
|
||||||
|
"""`flip`: None = Basis · "m30" · "m30+h1" (beide müssen dagegen stehen)."""
|
||||||
|
Rs = []
|
||||||
|
for i, d, atr, kosten in ein:
|
||||||
|
haken = None
|
||||||
|
if flip:
|
||||||
|
def haken(j, prof_atr, _d=d):
|
||||||
|
gegen = htf[j] == -_d
|
||||||
|
if flip == "m30+h1":
|
||||||
|
gegen = gegen and h1[j] == -_d
|
||||||
|
if not gegen:
|
||||||
|
return False
|
||||||
|
return auch_im_minus or prof_atr > min_r
|
||||||
|
R = simulate(C[i], d, atr, H, L, C, i + 1, LIVE, stop_when=haken)
|
||||||
|
Rs.append(R - kosten)
|
||||||
|
return Rs
|
||||||
|
|
||||||
|
|
||||||
|
def kz(Rs):
|
||||||
|
if not Rs:
|
||||||
|
return "—"
|
||||||
|
n = len(Rs); w = sum(1 for x in Rs if x > 0); s = sum(Rs)
|
||||||
|
g = sum(x for x in Rs if x > 0); v = -sum(x for x in Rs if x < 0)
|
||||||
|
return (f"n={n:>4} WR={100*w/n:>3.0f}% ØR={s/n:+.3f} "
|
||||||
|
f"PF={(g/v if v > 0 else 9.99):>4.2f} ΣR={s:>+6.0f} Worst={min(Rs):+.2f}")
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
n = int(sys.argv[1]) if len(sys.argv) > 1 else 80000
|
||||||
|
mt5.initialize()
|
||||||
|
sym = next((c for c in ("SpotCrude", "USOIL", "WTI", "XTIUSD")
|
||||||
|
if mt5.symbol_info(c)), None)
|
||||||
|
bars = mt5.copy_rates_from_pos(sym, mt5.TIMEFRAME_M5, 0, n)
|
||||||
|
si = mt5.symbol_info(sym); point = si.point
|
||||||
|
mt5.shutdown()
|
||||||
|
H = [float(b["high"]) for b in bars]; L = [float(b["low"]) for b in bars]
|
||||||
|
C = [float(b["close"]) for b in bars]
|
||||||
|
SP = [float(b["spread"]) * point for b in bars]
|
||||||
|
EF = _ema_series(C, _EMA_FAST); ES = _ema_series(C, _EMA_SLOW)
|
||||||
|
AT = _atr_series(H, L, C)
|
||||||
|
sig = signal_series(H, L, C, EF, ES, AT)
|
||||||
|
htf = _htf_signs(H, L, C, _M30_STEP)
|
||||||
|
h1 = _htf_signs(H, L, C, _H1_STEP)
|
||||||
|
|
||||||
|
mid = len(C) // 2
|
||||||
|
print("=" * 96)
|
||||||
|
print(f" FLIP-CLOSE auf dem HTF-TREND — {sym} M5, {len(C)} Bars")
|
||||||
|
print(" Regel vorab: ΣR in BEIDEN Hälften besser · Worst nicht schlechter · "
|
||||||
|
"Nachbarn kippen nicht")
|
||||||
|
print("=" * 96)
|
||||||
|
|
||||||
|
for name, (lo, hi) in (("H1", (_N_BARS, mid)), ("H2", (mid, len(C) - LIVE.max_hold - 2))):
|
||||||
|
ein = entries(sig, lo, hi, H, L, C, AT, SP)
|
||||||
|
print(f"\n ── {name} ── {len(ein)} feste Einstiege, alle Varianten identisch")
|
||||||
|
basis = lauf(ein, H, L, C, htf, h1)
|
||||||
|
b_sum = sum(basis)
|
||||||
|
print(f" {'BASIS (kein Flip-Close)':<34}{kz(basis)}")
|
||||||
|
for etikett, kw in (
|
||||||
|
("M30 dagegen, ab +0,0R", dict(flip="m30", min_r=0.0)),
|
||||||
|
("M30 dagegen, ab +0,5R", dict(flip="m30", min_r=0.5)),
|
||||||
|
("M30 dagegen, ab +1,0R", dict(flip="m30", min_r=1.0)),
|
||||||
|
("M30 dagegen, AUCH im Minus", dict(flip="m30", auch_im_minus=True)),
|
||||||
|
("M30+H1 dagegen, ab +0,5R", dict(flip="m30+h1", min_r=0.5)),
|
||||||
|
("M30+H1, AUCH im Minus", dict(flip="m30+h1", auch_im_minus=True))):
|
||||||
|
Rs = lauf(ein, H, L, C, htf, h1, **kw)
|
||||||
|
d = sum(Rs) - b_sum
|
||||||
|
print(f" {etikett:<34}{kz(Rs)} Δ{d:>+6.0f}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user