Files
AH-Oil-Trader/docs/brk-eigener-slot.md
T
Axel HocksandClaude Opus 5 815b6a77b8 Entwurf: BRK mit eigenem Positions-Slot (docs/brk-eigener-slot.md)
User: "der brk trade soll komplett unabhaengig von m15 oder manuellen trades
laufen". Der Entwurf ist am echten Code verifiziert, aber NICHT gebaut -
Umsetzung gehoert in eine eigene Sitzung mit flachem Konto.

DER ENTSCHEIDENDE BEFUND macht den Umbau viel kleiner als gedacht:
TrailingManager.__init__ nimmt BEREITS einen Trader entgegen (trailing.py:146)
und liest ausschliesslich ueber self.trader.snapshot(). Es haengt also nicht an
einer globalen Position, sondern an SEINEM Trader. Damit ist die Loesung ein
ZWEITER, ticket-gebundener TradeManager fuer BRK samt eigenem Trailing - statt
29 Stellen in engine.py umzubauen. Der validierte Pfad (manuell + M15) bleibt
dabei vollstaendig unangetastet, also kein Regressionsrisiko auf der gemessen
besseren Population.

DER KRITISCHE PUNKT ist die Adoption: TradeManager.refresh() greift heute jede
Position auf dem Symbol (positions_get(symbol=sym) mit Fallback auf alle). Mit
zwei Managern wuerden sich beide dieselbe Position schnappen. Der BRK-Manager
muss deshalb STRIKT ticket-gebunden sein - das ist die eine Aenderung, an der
der ganze Entwurf haengt.

Dokumentiert sind ausserdem die sieben Bauschritte in Reihenfolge, vier
Vorbedingungen (flaches Konto, RETAIL_HEDGING bestaetigt, doppeltes Risiko und
damit die Breaker-Frage, Margin-Semantik des Feldes "Einsatz je Pfad") und die
Erfolgskontrolle.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 19:54:08 +02:00

5.5 KiB
Raw Blame History

BRK mit eigenem Positions-Slot — Entwurf

Auftrag (User, 2026-08-19): „der brk trade soll komplett unabhängig von m15 oder manuellen trades laufen".

Status: Entwurf, am echten Code verifiziert. Nicht gebaut. Umsetzung gehört in eine eigene Sitzung mit flachem Konto.


Warum der naheliegende Weg falsch ist

Die erste Idee wäre, die beiden Sperren zu entfernen:

Stelle heutiges Verhalten
trader.open_long/short (Z. 320/333) lehnt ab, wenn self.ticket gesetzt ist
engine._manage_squeeze_pending storniert die Pendings, sobald irgendeine Position offen ist

Das wäre an einem Abend gemacht — und falsch. trader hält EIN Ticket (self.ticket), und trailing, Notfall-Stop, S/R-Close und Time-Stop hängen alle daran (29 Stellen in engine.py). Der zweite Trade hätte nur den Broker-SL.

⚠⚠ Und das ist gemessen nicht tragfähig (backtest_brk_slonly.py, 2026-08-19, 80k M5, 2 Halbjahre): keine der fünf Exit-Varianten erfüllt die vorab fixierte Regel, alle zehn Konfidenzintervalle enthalten die Null. SL-only sieht im ØR zwar nicht schlechter aus, aber die Trefferquote fällt 40 → 21 % und die KI-Breite vervierfacht sich — ein Varianz-Befund, kein Edge.


Der Entwurf: ein ZWEITER, ticket-gebundener Trader

Der entscheidende Befund aus der Code-Sichtung: TrailingManager.__init__ nimmt bereits einen Trader entgegen (core/trailing.py:146, self.trader = trader) und liest ausschließlich über self.trader.snapshot(). Es ist also nicht an eine globale Position gebunden, sondern an seinen Trader.

Damit entfällt der 29-Stellen-Umbau:

engine.trader      ─ TradeManager (wie heute)  ─ trail      ─ manuell + M15
engine.trader_brk  ─ TradeManager (NEU)        ─ trail_brk  ─ nur BRK

Der validierte Pfad bleibt unangetastet. Manuelle Trades und der Schutz-Stack laufen unverändert über self.trader — kein Regressionsrisiko auf der Population, die gemessen die bessere ist (+1,56 gegen 4,71 €/Lot).


⚠⚠ Der kritische Punkt: Adoption abschalten

TradeManager.refresh() (core/trader.py:511) macht heute:

on_sym  = mt5.positions_get(symbol=sym) or []
all_pos = on_sym if on_sym else (mt5.positions_get() or [])

Es adoptiert also jede Position auf dem Symbol. Mit zwei Managern würden sich beide dieselbe Position greifen und gegeneinander arbeiten — Trailing zweimal auf demselben Ticket, oder beide auf dem falschen.

➜ Der BRK-Manager muss STRIKT ticket-gebunden sein: positions_get(ticket=…), keine Adoption, kein Symbol-Fallback. Das ist die eine Änderung, an der der ganze Entwurf hängt.

Umsetzung: TradeManager(..., nur_ticket: bool = False). Bei True:

  • refresh() fragt ausschließlich positions_get(ticket=self.ticket)
  • ist self.ticket is None, ist der Manager flat — er sucht sich nichts
  • _refresh_locked adoptiert nicht per magic-match

Schritte (in dieser Reihenfolge)

  1. TradeManager um nur_ticket erweitern. Default False → der bestehende Manager verhält sich bitgenau wie heute. Test, der das festnagelt (Muster tests/test_room_info.py: alte Fassung eingefroren, über Zufallslagen gegengerechnet).
  2. engine.trader_brk + engine.trail_brk anlegen. Noch ohne Nutzung.
  3. BRK-Pfad umhängen: _manage_squeeze_pending, _check_pending_fill, _check_auto_squeeze benutzen trader_brk. Die FLAT-Bedingung wird zu trader_brk.ticket is None — BRK sieht die andere Position nicht mehr.
  4. Schutz-Stack für BRK zweimal aufrufen: trail_brk.tick() im _pos_loop, dazu _check_sr_close / _check_auto_close / _check_adverse15 mit dem jeweiligen Trader parametrisieren (sie lesen heute self.trader fest).
  5. Snapshot: zweites Positionsobjekt (position_brk) + Dashboard-Zeile. ⚠ Ohne Anzeige wäre eine offene Position unsichtbar — das ist die Buchführungs-Lücke von Deployment-Drift Fall 8 in neuer Form.
  6. Circuit-Breaker und Tages-P&L müssen beide Positionen summieren, sonst greift die Notbremse zu spät.
  7. Margin: calc_lots rechnet auf margin_free. Läuft schon eine Position, ist die frei verfügbare Margin kleiner — BRK würde automatisch kleiner sizen. Das ist gewollt, aber das Feld „Einsatz je Pfad" muss dann als Anteil der GESAMT-Margin gelesen werden, nicht der freien. Vor dem Bau entscheiden.

Was vorher geklärt sein muss

  • Konto muss FLAT sein. Ein halb umgebauter Schutz-Stack hängt an der falschen Position.
  • RETAIL_HEDGING ist bestätigt (Broker erlaubt mehrere Positionen) — geprüft 2026-08-19.
  • Zwei Positionen = zweimal Risiko. Bei 40 % Einsatz je Position sind 80 % gebunden. Der Circuit-Breaker (aktuell aus) wäre dann kein Luxus mehr — das gehört mitentschieden.
  • Die Squeeze-Zahlen gelten weiter nur mit dem kanonischen Exit. Nach dem Umbau muss trail_brk nachweislich laufen (Log + Snapshot), sonst ist man ungewollt in der gemessen durchgefallenen SL-only-Variante.

Erfolgskontrolle nach dem Bau

  • Ein BRK-Trade läuft, während eine manuelle Position offen ist — beide mit eigenem SL und beide mit aktivem Trailing (im Log sichtbar).
  • squeeze_entry_count steigt wieder (heute: 0 bei fünf stornierten Fenstern).
  • analyze_squeeze_entry_gap.py: der Abstand Einstieg↔Level bleibt bei ~0.
  • Die B5-Zählung läuft auf einer NEU vorab fixierten Latte weiter (die alte ist am 2026-08-17 gefallen und rechnerisch unerreichbar).