FIX: setup-Nachtrag bei Pending-Fill scheiterte an einem Rennen
User: "dann sieh dir die Luecke an" (nach "DB-Nachtrag fehlgeschlagen" im Log, 20.08. 07:40:12, T=50371599). URSACHE - ein Rennen zwischen zwei Pfaden: _check_pending_fill erkennt den Fill aus trader_brk.snapshot(), die DB-ZEILE schreibt aber trader._refresh_locked -> log_trade_open. War der noch nicht durch, traf das UPDATE keine Zeile und der Nachtrag scheiterte STILL. Der Trade blieb setup=NULL und war damit von einem manuellen nicht unterscheidbar - genau die Buchfuehrungs-Luecke, gegen die tag_bot_trade ueberhaupt gebaut wurde (Deployment-Drift Fall 8), nur eine Ebene tiefer. Folge: squeeze_entry_count blieb 0, der Trade fehlte in B4/B5. BEHOBEN: gescheiterte Nachtraege landen in `_tag_nachtrag` und werden im _pos_loop wiederholt, bis die Zeile da ist - dasselbe Retry-Muster wie beim Gewinn-Close (23.07.). Nach 60 Versuchen (~1 min) wird aufgegeben und LAUT gemeldet: eine Zeile, die nach einer Minute nicht existiert, kommt nicht mehr, und dann soll es nicht still bleiben. T=50371599 nachgetragen (DB-Backup oil_widget_history.db.bak-2026-08-20). ✅ NEBENBEFUND, und zwar ein guter: derselbe Logausschnitt enthaelt "🧷 BRK-Slot uebernimmt Pending-Fill T=50371599" - das ist der ERSTE Live-Beleg, dass der Zwei-Slot-Umbau vom 19.08. funktioniert. Der BRK-Slot hat die gefuellte Pending-Order korrekt uebernommen. ⚠ ZWEITER NEBENBEFUND, NICHT behoben (User-Entscheidung): die Order wurde mit 0,01 Lots platziert. Das ist die direkte Folge von margin_brk = 10 % auf eine fast erschoepfte freie Margin - die Einstellung wirkt also, nur vermutlich anders als gedacht. Dazu steht margin_pct in runtime_state auf 95, waehrend die ini 40 sagt (runtime gewinnt). Beides gemeldet, nichts geaendert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
4ebc55c49b
commit
d87bda1461
@@ -865,6 +865,7 @@ class TradingEngine:
|
||||
# erkannt und die Benachrichtigung vorgemerkt.
|
||||
self._check_close_notify() # Telegram bei jedem Close ab Schwelle
|
||||
self._check_open_notify() # Telegram bei jeder Eröffnung
|
||||
self._retry_tag_nachtrag() # gescheiterte setup-Nachtraege
|
||||
self._check_slot_reichweite() # meldet ungedeckte 2. Position
|
||||
self._check_adverse15() # 15-Min-Regel (nur Bot-Trades)
|
||||
self._check_flip_close() # Empfehlung dreht → schließen
|
||||
@@ -949,6 +950,41 @@ class TradingEngine:
|
||||
return False
|
||||
return self._circuit_tripped_date == datetime.now(_BERLIN).date()
|
||||
|
||||
def _retry_tag_nachtrag(self):
|
||||
"""Gescheiterte `setup`-Nachträge erneut versuchen (2026-08-20).
|
||||
|
||||
⚠ Der Fill wird aus dem Positions-Snapshot erkannt, die DB-Zeile
|
||||
schreibt aber ein anderer Pfad. Ist der beim ersten Versuch noch nicht
|
||||
durch, trifft das UPDATE keine Zeile. Ohne Wiederholung bliebe der Trade
|
||||
dauerhaft `setup=NULL` — und damit unsichtbar für B4-Monitor,
|
||||
`squeeze_b5` und `squeeze_entry_gap`.
|
||||
⚠ Nach 60 Versuchen (~1 min) aufgeben und LAUT melden: eine Zeile, die
|
||||
nach einer Minute nicht existiert, kommt nicht mehr — dann ist etwas
|
||||
anderes kaputt, und das soll nicht still bleiben.
|
||||
"""
|
||||
offen = getattr(self, "_tag_nachtrag", None)
|
||||
if not offen or not self.history:
|
||||
return
|
||||
if not hasattr(self, "_tag_versuche"):
|
||||
self._tag_versuche = {}
|
||||
for tk in list(offen):
|
||||
setup = offen[tk]
|
||||
try:
|
||||
if self.history.tag_bot_trade(int(tk), setup):
|
||||
offen.pop(tk, None)
|
||||
self._tag_versuche.pop(tk, None)
|
||||
log.info(f"✅ DB-Nachtrag erfolgreich: T={tk} → {setup}")
|
||||
continue
|
||||
except Exception as e:
|
||||
log.debug(f"_retry_tag_nachtrag: {e}")
|
||||
n = self._tag_versuche.get(tk, 0) + 1
|
||||
self._tag_versuche[tk] = n
|
||||
if n >= 60:
|
||||
offen.pop(tk, None)
|
||||
self._tag_versuche.pop(tk, None)
|
||||
log.warning(f"⚠ DB-Nachtrag T={tk} nach {n} Versuchen aufgegeben "
|
||||
f"— der Trade bleibt setup=NULL und fehlt in B4/B5.")
|
||||
|
||||
def _check_open_notify(self):
|
||||
"""Telegram bei JEDER Eröffnung — beide Slots (User-Vorgabe 2026-08-19).
|
||||
|
||||
@@ -1481,6 +1517,22 @@ class TradingEngine:
|
||||
self._pending_tagged.add(tk)
|
||||
self._pending_tickets.pop(int(tk), None)
|
||||
ok = self.history.tag_bot_trade(int(tk), setup) if self.history else False
|
||||
# ⚠⚠ RENNEN, real am 2026-08-20: der Fill wird hier aus
|
||||
# `trader_brk.snapshot()` erkannt, die DB-ZEILE schreibt aber ein
|
||||
# anderer Pfad (`trader._refresh_locked` → `log_trade_open`). Ist
|
||||
# der noch nicht durch, trifft das UPDATE keine Zeile und der
|
||||
# Nachtrag scheitert STILL — der Trade bleibt `setup=NULL` und ist
|
||||
# von einem manuellen nicht unterscheidbar. Genau die
|
||||
# Buchfuehrungs-Luecke, gegen die `tag_bot_trade` gebaut wurde
|
||||
# (Deployment-Drift Fall 8), nur eine Ebene tiefer.
|
||||
# ⚠ Der Fall ist NICHT theoretisch: T=50371599 lag danach mit
|
||||
# `setup=NULL` in der DB, obwohl die Zeile Sekunden spaeter da war.
|
||||
# Deshalb nachreichen statt aufgeben — dasselbe Retry-Muster wie
|
||||
# beim Gewinn-Close (`_sr_close_min_gain_armed_ticket`, 23.07.).
|
||||
if not ok:
|
||||
if not hasattr(self, "_tag_nachtrag"):
|
||||
self._tag_nachtrag = {}
|
||||
self._tag_nachtrag[int(tk)] = setup
|
||||
# Dieselbe Buchfuehrung wie beim Market-Pfad, damit B4/B5 zaehlen
|
||||
self._bot_open_ticket = tk
|
||||
self._bot_open_source = "auto_squeeze"
|
||||
|
||||
Reference in New Issue
Block a user