Tag P/L war falsch: Fehlbuchungen beim Schliessen behoben + repariert
User-Frage "ueberpruefe ob Tag P/L richtig berechnet wird". Die Formel (realisiert + offen) war bitgenau richtig - die Datenbasis nicht: Anzeige +14,26 EUR gegen -74,08 EUR realisiert beim Broker. Ursache, im Log im Sekundentakt (#49926460): 20:04:10 eroeffnet -> 20:04:10 "extern geschlossen" -> "kein OUT-Deal in 1 Deals" -> Fallback bucht 0,00 -> 20:11:42 der echte Close lief ins Leere. Drei Defekte: (1) positions_get sieht die frische Position einen Tick lang nicht, (2) _log_external_close buchte TROTZ "kein OUT-Deal" einen Close - dabei ist genau das der Beweis, dass sie noch offen ist, (3) log_trade_close fasste nur exit_time IS NULL an, die Fehlbuchung blockierte den echten Close dauerhaft. Bei #49852362 kostete das +5,87 statt -95,38 EUR und den falschen Tag. Behoben: (1) Abbruch statt Fallback bei "kein OUT-Deal"; (2) eine erkennbare Fehlbuchung (closed_by='unknown') darf von einem echten Close korrigiert werden - eng gefasst, gute Zeilen bleiben unberuehrt. 4 Tests inkl. Gegenprobe. Altlast: tools/repair_closes.py (Trockenlauf Standard, Backup automatisch). 18 Zeilen ueber 60 Tage korrigiert. Heute von +7,63 auf -72,67 (Restfehler 1,41). Gesamt-P&L von -282,78 auf +169,98. Zeitfalle zweimal getroffen: history_deals_get filtert nach Broker-Wallclock, und fromtimestamp(d.time, BROKER) rendert 3 h zu spaet. Aufgefallen nur, weil eine Deal-Zeit 23:11 lautete, das Log aber 20:11:42 sagte. Statistik-Modul separat geprueft: Arithmetik in allen drei Zeitraeumen bitgenau korrekt (Abweichung 0,00). Der Netto-Defekt vom 05.08. besteht weiter und ist groesser als damals: angezeigt -2.449,95 EUR, real verblieben -17,06 (99 % der Steuer werden erstattet). Nicht gebaut - die Loesung ist dokumentiert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
19ee379f20
commit
d8839ef7c5
+26
-1
@@ -779,9 +779,34 @@ class TradeManager:
|
||||
f"Externer Close: T={ticket} {closed_by} @ "
|
||||
f"{close_deal.price:.3f} pnl={total_profit:.2f}")
|
||||
return
|
||||
log_hist.warning(f"T={ticket}: kein OUT-Deal in {len(own)} Deals")
|
||||
# ⚠⚠ HIER LAG DER FEHLER (behoben 2026-08-12). Vorher fiel dieser
|
||||
# Zweig in den Fallback durch und buchte den zuletzt bekannten
|
||||
# SCHWEBE-Gewinn als realisierten Close.
|
||||
# Das ist genau falsch herum: wir haben die Deals der Position
|
||||
# GEFUNDEN und festgestellt, dass **kein OUT-Deal existiert**.
|
||||
# Das ist positive Evidenz, dass die Position NOCH OFFEN ist —
|
||||
# typischerweise ein transient leeres `positions_get` direkt
|
||||
# nach dem Eröffnen.
|
||||
# Real am 12.08.: #49926460 wurde 0 Sekunden nach dem Öffnen als
|
||||
# „extern geschlossen" mit pnl 0,00 und exit_price 0,0 gebucht;
|
||||
# der ECHTE Close 7 min später lief ins Leere, weil
|
||||
# `log_trade_close` nur Zeilen mit `exit_time IS NULL` anfasst.
|
||||
# Bei #49852362 kostete dasselbe **+5,87 statt −95,38 €** und
|
||||
# buchte den Trade auf den FALSCHEN TAG.
|
||||
# ➜ Nicht schreiben. Der nächste Tick prüft erneut; bleibt die
|
||||
# Position wirklich weg, liefert der Broker dann einen
|
||||
# OUT-Deal. `reconcile_open_trades` ist das zweite Netz.
|
||||
log_hist.warning(
|
||||
f"T={ticket}: kein OUT-Deal in {len(own)} Deals — Position gilt "
|
||||
f"als WEITER OFFEN, kein Close gebucht (Fallback uebersprungen)")
|
||||
return
|
||||
|
||||
# ── Methode 3: Fallback — letzter bekannter PnL ───────────────────
|
||||
# ⚠ Nur noch fuer den WIRKLICH blinden Fall: es liess sich KEIN
|
||||
# einziger Deal der Position abrufen (MT5-Aussetzer, Broker setzt
|
||||
# `position_id` nicht). Dann ist „offen oder zu" nicht entscheidbar,
|
||||
# und eine Zeile mit `closed_by='unknown'` ist besser als ein Trade,
|
||||
# der ewig offen in der DB haengt.
|
||||
if fallback_pnl is not None:
|
||||
self.history.log_trade_close(
|
||||
ticket=ticket,
|
||||
|
||||
Reference in New Issue
Block a user