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:
co-authored by
Claude Opus 5
parent
d3d613068c
commit
4ebc55c49b
+28
-2
@@ -40,7 +40,21 @@ from dataclasses import dataclass, replace
|
|||||||
class ExitParams:
|
class ExitParams:
|
||||||
"""Alle Größen in ×ATR, Zeiten in Bars der jeweiligen Basis-TF."""
|
"""Alle Größen in ×ATR, Zeiten in Bars der jeweiligen Basis-TF."""
|
||||||
sl_atr: float = 2.0 # Initial-SL (Live-Band 1,8–2,2 → Ziel 2,0)
|
sl_atr: float = 2.0 # Initial-SL (Live-Band 1,8–2,2 → Ziel 2,0)
|
||||||
trail_start: float = 0.3 # Phase Init→Trail
|
# ⚠⚠ 0,3 → 1,3 am 2026-08-20 (User-Entscheidung nach drei Trades in Folge,
|
||||||
|
# die per nachgezogenem Stop schlossen). BEGRUENDUNG AUS DER MESSUNG:
|
||||||
|
# `backtest_trail_start.py` (14.08.) hat den Anteil "war im Plus, schloss
|
||||||
|
# im Minus" ausgezaehlt — 0,3 → 47,6 % / 38,2 %, bei 1,3 → 0,0 % / 0,5 %.
|
||||||
|
# ⚠ Der ERTRAG unterscheidet sich dabei NICHT messbar: der gepaarte Test
|
||||||
|
# (gleiche Einstiege, nur der Exit variiert) liefert fuer alle zwoelf
|
||||||
|
# Zellen ein 95-%-KI, das die Null enthaelt. Es ist also eine KOMFORT-,
|
||||||
|
# keine Edge-Entscheidung — und sie ist gemessen gratis.
|
||||||
|
# ⚠ MECHANIK, die man kennen muss: der Trail sitzt `mult`×ATR (=1,0)
|
||||||
|
# hinter dem Bestkurs und erreicht den Einstand daher erst bei 1,0×ATR
|
||||||
|
# Gewinn. Startete er schon bei 0,3, lag der Stop im Band dazwischen
|
||||||
|
# zwangslaeufig auf der VERLUSTSEITE. Mit 1,3 greift er erst oberhalb des
|
||||||
|
# Einstands; bis dahin schuetzt der Initial-SL.
|
||||||
|
# ZURUECK: 0.3
|
||||||
|
trail_start: float = 1.3 # Phase Init→Trail
|
||||||
mult: float = 1.0 # Trail-Abstand HW ∓ mult×ATR (1,5 → 1,0 am 2026-07-31)
|
mult: float = 1.0 # Trail-Abstand HW ∓ mult×ATR (1,5 → 1,0 am 2026-07-31)
|
||||||
be: float = 1.3 # Breakeven-Boden (Entry) ab diesem Profit
|
be: float = 1.3 # Breakeven-Boden (Entry) ab diesem Profit
|
||||||
lock_start: float = 3.5 # Phase Trail→Lock
|
lock_start: float = 3.5 # Phase Trail→Lock
|
||||||
@@ -70,7 +84,19 @@ class ExitParams:
|
|||||||
# Grund: die Sim modelliert **keine Exit-Slippage**; ein engerer Trail
|
# Grund: die Sim modelliert **keine Exit-Slippage**; ein engerer Trail
|
||||||
# löst deutlich häufiger aus und ist damit stärker davon betroffen
|
# löst deutlich häufiger aus und ist damit stärker davon betroffen
|
||||||
# (real gemessen: bis 0,75 ATR über den Stop hinaus).
|
# (real gemessen: bis 0,75 ATR über den Stop hinaus).
|
||||||
# start 0,3 `backtest_trailing.py` (0,6/1,0 schlechter)
|
# start 1,3 ⚠ WAR 0,3 (`backtest_trailing.py`: 0,6/1,0 schlechter). Am
|
||||||
|
# 2026-08-20 auf 1,3 gesetzt — s. Begruendung an `trail_start`.
|
||||||
|
# Der alte Befund ist NICHT widerlegt: er mass den ERTRAG, und der
|
||||||
|
# unterscheidet sich gepaart nicht messbar (alle 12 KI enthalten
|
||||||
|
# die Null). Geaendert wurde aus KOMFORT — der Anteil "war im
|
||||||
|
# Plus, schloss im Minus" faellt von 47,6 % auf 0,0 %.
|
||||||
|
# ⚠⚠ FOLGE FUER BACKTESTS: `LIVE` ist die geteilte Quelle, alle
|
||||||
|
# Skripte, die sie nutzen, rechnen ab jetzt mit 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 genau ihr Zweck: Live und Messung
|
||||||
|
# bewegen sich gemeinsam (Deployment-Drift Fall 3).
|
||||||
# be 1,3 `backtest_exit.py be` (0,6 → 21 % Breakeven-Scratches)
|
# be 1,3 `backtest_exit.py be` (0,6 → 21 % Breakeven-Scratches)
|
||||||
# timestop 24 `backtest_timestop.py` (120 min; 30/60 min kippten)
|
# timestop 24 `backtest_timestop.py` (120 min; 30/60 min kippten)
|
||||||
LIVE = ExitParams()
|
LIVE = ExitParams()
|
||||||
|
|||||||
+28
-8
@@ -225,14 +225,34 @@ class TrailingManager:
|
|||||||
angle = self._trend_angle
|
angle = self._trend_angle
|
||||||
if override is not None:
|
if override is not None:
|
||||||
return override
|
return override
|
||||||
if angle is None:
|
# ⚠⚠ FEST AUF M5 (2026-08-20) — DEPLOYMENT-DRIFT BEHOBEN.
|
||||||
return _TF_RANGE
|
# `backtest_trailmult.py` misst `mult = 1,0` auf M5-Bars mit M5-ATR.
|
||||||
strength = abs(angle - 90.0)
|
# Live kam der ATR bis heute aus der WELLEN-Zeitebene, und die wechselt.
|
||||||
if strength > 45:
|
# Gemessen an 90 echten Aktivierungen:
|
||||||
return _TF_STRONG # starker Trend → H1
|
# M5 Ø ATR 0,1877 (n=51) → 1,00× wie validiert
|
||||||
elif strength > 20:
|
# M15 Ø ATR 0,2586 (n= 9) → 1,38×
|
||||||
return _TF_MODERATE # moderater Trend → M30
|
# M30 Ø ATR 0,4751 (n=30) → 2,53×
|
||||||
return _TF_RANGE # Seitwärts → M15
|
# 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) ─────────
|
# ── ATR (gecacht, refresht nur bei neuer Kerze des gewählten TF) ─────────
|
||||||
def _refresh_atr(self, sym: str, tf: int) -> bool:
|
def _refresh_atr(self, sym: str, tf: int) -> bool:
|
||||||
|
|||||||
Reference in New Issue
Block a user