Warum BRK heute nicht ausgeloest hat: drei Ursachen, zwei behoben

User: "warum wurde beim letzten anstieg kein Break Out trade ausgeloest?"

Der Squeeze HAT gefeuert - mit der echten `_squeeze_one` nachgerechnet: 8 Bars
`active` heute, davon 6 LONG (00:55 / 03:00 / 07:40 / 08:35 / 11:50 / 13:00).
`squeeze_entry_count` steht trotzdem auf 0. Im Log stehen 8
`AUTO-SQUEEZE-ENTRY`-Zeilen - die Order scheiterte JEDES MAL.

URSACHE 1 - "Position bereits offen!" (1x, 08:30:34). Der Market-Fallback lief
noch ueber Slot 1, der vom manuellen Trade belegt war. Genau die Zwei-Slot-
Luecke; der `_slot()`-Fix kam um 08:32 und hat sie geschlossen.

URSACHE 2 - "Lot-Fehler" (140x, ab 13:02 JEDER Versuch). Das ist der Hauptgrund
und er ist eine Einstellung, kein Defekt: `margin_brk = 10 %`, und `calc_lots`
nimmt einen Prozentsatz der FREIEN Margin, nicht des Kontos. Die manuelle
Position bindet 707 von 776 EUR -> 10 % von ~100 EUR frei = ~10 EUR, ein
Mindestlot braucht 7,47 EUR, und die freie Margin schwankt mit dem P&L. Damit
lag BRK den ganzen Tag auf der Kippe. NICHT eigenmaechtig geaendert - das Feld
ist eine User-Entscheidung.

URSACHE 3 - "Kurs hat das Level bereits passiert" (129x). Die BUY_STOP-Seite
war nicht platzierbar, weil das Box-Dach dem Kurs ENTGEGENKAM (rollierendes
Fenster) - die wandernde Marke aus backtest_squeeze_frozen.py, hier live.

BEHOBEN (1): LOG-DROSSEL GRIFF NIE. Der Merker lag in EINER Variable, die
beiden Seiten scheitern aber im selben Tick mit VERSCHIEDENEN Fehlern
("Level passiert" oben, "Lot-Fehler" unten) - der Wert wechselte bei jedem
Aufruf. Real: 269 Zeilen an einem Tag, 2 je Sekunde. Jetzt je Order-Seite
gemerkt. Eine Drossel, die nie drosselt, ist schlimmer als keine: sie verdeckt
im Log genau die Meldung, die zaehlt.

BEHOBEN (2): "Lot-Fehler" erklaert sich jetzt selbst (`mt5_utils.lot_grund`).
Statt zwei Woertern steht dort
  "Einsatz 2 % von 101.90 EUR freier Margin = 2.04 EUR, Mindestlot 0.01
   braucht aber 7.47 EUR"
Beide Aufrufer (Market `_send` und Pending `place_stop`) nutzen ihn. Live
gegengeprueft an drei Einsatz-Werten.

Pipeline gruen (check_nfalle, Stufe E, 97 Tests), deployt und verifiziert:
seit dem Neustart 0 Zeilen "nicht platzierbar".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-20 14:26:43 +02:00
co-authored by Claude Opus 5
parent a35ea38d31
commit b448a7ade8
3 changed files with 50 additions and 9 deletions
+14 -5
View File
@@ -471,7 +471,7 @@ class TradingEngine:
# sich die adoptierte Position nachtraeglich dem Bot zuordnen.
self._pending_tickets: dict[int, str] = {}
self._pending_tagged: set = set()
self._squeeze_pending_err = None
self._squeeze_pending_err: dict = {} # je Order-Seite, s. unten
self._squeeze_chase_logged = None
self._squeeze_reverse_sig = None # Dedup Reverse-Close (Gegen-Trade)
self._squeeze_entry_count = 0
@@ -1774,10 +1774,19 @@ class TradingEngine:
log.info(f"🎯 Pending-Entry ({quelle}) gesetzt: "
f"{'BUY_STOP' if otype == mt5.ORDER_TYPE_BUY_STOP else 'SELL_STOP'}"
f" @ {preis:.3f} (T={t})")
elif err and self._squeeze_pending_err != err:
# ⚠ Nur bei ÄNDERUNG loggen: „Kurs hat das Level bereits passiert"
# tritt im 1-s-Takt auf, sobald der Kurs am Level klebt.
self._squeeze_pending_err = err
elif err and self._squeeze_pending_err.get(otype) != err:
# ⚠ Nur bei ÄNDERUNG loggen: „Kurs hat das Level bereits
# passiert" tritt im 1-s-Takt auf, sobald der Kurs am Level
# klebt.
# ⚠⚠ JE SEITE gemerkt (Fix 2026-08-20). Vorher lag der
# Merker in EINER Variable — und weil die beiden Seiten
# im selben Tick mit VERSCHIEDENEN Fehlern scheitern
# ("Level passiert" oben, "Lot-Fehler" unten), wechselte
# der Wert bei jedem Aufruf und die Sperre griff NIE.
# Real am 20.08.: 269 Zeilen an einem Tag, 2 je Sekunde.
# Eine Drossel, die nie drosselt, ist schlimmer als keine:
# sie verdeckt im Log genau die Meldung, die zaehlt.
self._squeeze_pending_err[otype] = err
log.info(f"Pending-Entry ({quelle}) nicht platzierbar "
f"({preis:.3f}): {err}")
self._pending_levels = ziel