Trailing: ATR fest auf M5 (Drift behoben) + trail_start 0,3 -> 1,3

User: "ueberpruefe die trailing logik und passe ggf an", nach drei Trades in
Folge, die per nachgezogenem Stop schlossen. Beide Aenderungen auf Zustimmung.

(1) DEPLOYMENT-DRIFT: der Trail-ATR kam aus der WELLEN-Zeitebene, und die
    wechselt. Gemessen an 90 echten Aktivierungen im Log:
        M5   Ø ATR 0,1877  n=51   -> 1,00x wie validiert
        M15  Ø ATR 0,2586  n= 9   -> 1,38x
        M30  Ø ATR 0,4751  n=30   -> 2,53x
    In 43 % der Faelle lief der Trail also mit einem Abstand, der NIE gemessen
    wurde. `backtest_trailmult.py` misst mult=1,0 auf M5-Bars mit M5-ATR; auf
    M30 entspricht das effektiv ~2,5 in M5-Einheiten, und 2,5 ist dort KLAR
    schlechter gemessen (H1 ΣR -1174 gegen -73 bei 1,0).
    ⚠⚠ Am 31.07. wurde `_MULT_BY_TF` GENAU gegen diese Fehlerklasse auf
    durchgehend 1,0 geglaettet. Der Multiplikator war aber nie die Ursache - es
    ist der ATR. Die Variabilitaet kam durch die Hintertuer zurueck.
    `_atr_tf_override` bleibt unberuehrt: den setzt engine bewusst, das ist eine
    explizite Vorgabe und kein Automatismus. Zurueck: vier auskommentierte
    Zeilen in `_pick_tf` wieder aktivieren.

(2) trail_start 0,3 -> 1,3. `backtest_trail_start.py` (14.08.) zaehlt den Anteil
    "war im Plus, schloss im Minus": 0,3 -> 47,6 % / 38,2 %, bei 1,3 -> 0,0 % /
    0,5 %. ⚠ Der ERTRAG unterscheidet sich gepaart NICHT messbar - alle zwoelf
    KI enthalten die Null. Es ist also eine KOMFORT-Entscheidung, und sie ist
    gemessen gratis. Mechanik: der Trail sitzt mult×ATR (=1,0) hinter dem
    Bestkurs und erreicht den Einstand erst bei 1,0×ATR Gewinn; mit Start bei
    0,3 lag der Stop im Band dazwischen zwangslaeufig auf der VERLUSTSEITE.

⚠⚠ FOLGE FUER DIE BACKTESTS, ausdruecklich benannt: `LIVE` ist die GETEILTE
Quelle. Alle Skripte, die sie nutzen, rechnen ab jetzt mit trail_start 1,3 -
ihre dokumentierten Zahlen wurden mit 0,3 erzeugt und reproduzieren daher NICHT
mehr. Wer eine alte Zahl nachrechnen will, muss `LIVE.with_(trail_start=0.3)`
pinnen. Das ist der Preis der geteilten Quelle und zugleich ihr Zweck: Live und
Messung bewegen sich gemeinsam. Der veraltete Kommentar "start 0,3" in
exit_model.py wurde mitgezogen, damit die Begruendung nicht gegen die
Einstellung steht.

⚠ Am Verlust-Trade von heute frueh (-22,36) haette KEINE der beiden etwas
geaendert: er war nie im Plus und traf den regulaeren Initial-SL. Dort ist die
Schraube die Positionsgroesse, nicht der Exit.

91 Tests gruen, Deploy ueber tools/deploy.py --feld position_brk.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-20 08:01:20 +02:00
co-authored by Claude Opus 5
parent d3d613068c
commit 4ebc55c49b
2 changed files with 56 additions and 10 deletions
+28 -8
View File
@@ -225,14 +225,34 @@ class TrailingManager:
angle = self._trend_angle
if override is not None:
return override
if angle is None:
return _TF_RANGE
strength = abs(angle - 90.0)
if strength > 45:
return _TF_STRONG # starker Trend → H1
elif strength > 20:
return _TF_MODERATE # moderater Trend → M30
return _TF_RANGE # Seitwärts → M15
# ⚠⚠ FEST AUF M5 (2026-08-20) — DEPLOYMENT-DRIFT BEHOBEN.
# `backtest_trailmult.py` misst `mult = 1,0` auf M5-Bars mit M5-ATR.
# Live kam der ATR bis heute aus der WELLEN-Zeitebene, und die wechselt.
# Gemessen an 90 echten Aktivierungen:
# M5 Ø ATR 0,1877 (n=51) → 1,00× wie validiert
# M15 Ø ATR 0,2586 (n= 9) → 1,38×
# M30 Ø ATR 0,4751 (n=30) → 2,53×
# In 43 % der Faelle lief der Trail also mit einem Abstand, der NIE
# gemessen wurde — auf M30 entspricht `mult 1,0` effektiv ≈2,5 in
# M5-Einheiten, und 2,5 ist gemessen KLAR schlechter (H1 ΣR 1174
# gegen 73 bei 1,0).
# ⚠ Am 31.07. wurde `_MULT_BY_TF` genau gegen diese Fehlerklasse auf
# durchgehend 1,0 geglaettet. Der Multiplikator war aber nie die
# Ursache — es ist der ATR. Die Variabilitaet kam durch die Hintertuer
# zurueck; das hier schliesst sie.
# ⚠ `_atr_tf_override` bleibt unberuehrt: `engine` setzt ihn bewusst
# (u. a. fuer Squeeze-Trades), und das ist eine EXPLIZITE Vorgabe, kein
# Automatismus.
# ZURUECK auf das alte Verhalten: die vier Zeilen unten einkommentieren.
return mt5.TIMEFRAME_M5
# if angle is None:
# return _TF_RANGE
# strength = abs(angle - 90.0)
# if strength > 45:
# return _TF_STRONG # starker Trend → H1
# elif strength > 20:
# return _TF_MODERATE # moderater Trend → M30
# return _TF_RANGE # Seitwärts → M15
# ── ATR (gecacht, refresht nur bei neuer Kerze des gewählten TF) ─────────
def _refresh_atr(self, sym: str, tf: int) -> bool: