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

126 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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:
```python
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).