Commit Graph
342 Commits
Author SHA1 Message Date
Axel HocksandClaude Opus 5 df7163bf18 M15 -> "AT" (Auto Trader), Trail -> "TR", beide als runde Knoepfe neben CB (v=212)
User-Vorgabe. Balance-Feld jetzt: Wert - CB - AT - TR.

M15 heisst "AT" (Auto Trader), die ID wurde von `btn-m15` auf `btn-at`
mitgezogen; Endpoint (/api/autom15) und Backend-Zustand (`auto_m15`) bleiben
unveraendert - nur die Beschriftung und der Platz aendern sich.
Der Trail-Knopf heisst "TR".
⚠ Fuer TR war KEIN Name vorgegeben ("bennene den Trail Button" - der Satz
nennt kein Ziel). "TR" ist analog zu CB/AT gewaehlt, zwei Buchstaben,
Mono-Schrift. Umbenennen ist ein Einzeiler, falls etwas anderes gemeint war.

⚠ Beide VERSCHOBEN, nicht kopiert - zwei Elemente mit derselben ID waeren ein
stiller Fehler, weil getElementById nur das erste findet.

⚠⚠ ZWEI LESARTEN NEBENEINANDER, und das ist Absicht:
  CB  gruen = AUS   (inaktiv, nichts begrenzt)   <- ausdrueckliche User-Vorgabe
  AT  gruen = AN    (laeuft)
  TR  gruen = AN    (laeuft)
Drei Knoepfe nebeneinander mit zwei Farb-Bedeutungen sind eine Falle. Deshalb
steht die Begruendung im Markup, in der CSS UND im JS, und jeder Tooltip sagt
ausdruecklich, was SEIN Zustand bedeutet. Wer die CB-Logik spaeter "geradezieht",
soll vorher lesen, dass sie so gewollt ist.

Am ausgelieferten HTML geprueft: Reihenfolge balance -> btn-cb -> btn-at ->
btn-trail, Beschriftungen CB/AT/TR, 0 doppelte IDs, `btn-m15` nicht mehr
vorhanden.
Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen, deployt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 10:54:54 +02:00
Axel HocksandClaude Opus 5 75e783e882 CB-Knopf ins Balance-Feld, rechts neben den Wert (v=211)
User-Vorgabe. Der Knopf sass seit v=210 NEBEN dem Feld; jetzt sitzt er DRIN.

Umsetzung: der Wert und der Knopf liegen in einer gemeinsamen Flex-Zeile
(`.px-zeile`, space-between), damit der Knopf rechtsbuendig steht und die
Feldhoehe nicht springt.
⚠ `.px span` setzt 1,1111rem - eine Zeile, die das erbt, wuerde den
Knopf-Text mitskalieren. Deshalb bekommt `#balance` seine Groesse explizit und
`.cb-dot` im Balance-Feld eine eigene (1,7222rem statt 2,0556rem, damit die
Box nicht hoeher wird als ihre Nachbarn).

⚠ Farb-Logik unveraendert und weiterhin die Vorgabe des Nutzers: GRUEN =
inaktiv (aus), ROT = aktiv (scharf) - bewusst nicht die uebliche
"gruen = geschuetzt"-Lesart. Der Grund steht im Markup UND im JS, damit es
niemand spaeter "korrigiert".

Struktur am ausgelieferten HTML geprueft: Knopf liegt im Balance-Feld, Wert vor
Knopf, 0 doppelte IDs, span-Balance 58/58.
⚠ Die div-Differenz von 1 ist VORBESTEHEND (ein `<div` in einem Kommentar) -
gegen HEAD verglichen, nicht angenommen: ohne Kommentare 90/90.

Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen, deployt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 10:50:35 +02:00
Axel HocksandClaude Opus 5 0dd2e524b7 S/R-Auto-Close komplett entfernt + Circuit-Breaker als runder CB-Knopf (v=210)
(1) S/R-AUTO-CLOSE RAUS (User-Vorgabe: "die brauche ich nicht mehr").
Der Schalter stand seit dem 19.08. ohnehin auf AUS - abgeschaltet, nachdem
analyze_pbreak_live.py das P(break)-Modell live als INVERTIERT gemessen hatte
(AUC 0,452, Klassen monoton rueckwaerts). Ohne funktionierendes Gate ist der
S/R-Close faktisch der PAUSCHALE, und der ist 2x gemessen und verworfen
(Gewinner-Kappen). Die Entfernung vollzieht den gemessenen Stand nach.

WEG: _check_sr_close, set_sr_autoclose, set_sr_close_min_gain, die
Konstruktor-Felder, die %-Armierung des Gewinn-Close, drei Snapshot-Felder,
beide runtime_state-Schluessel, die Reichweiten- und Systemstatus-Zeilen,
/api/srclose und /api/srclose_min, der Knopf S/R, das Gewinn-Close-Feld, der
Toast "Bot hat am Level geschlossen".
BLEIBT: `_sr_close_hint` (App-Hinweis, P(break)-Chartlinien, Copilot-Kontext,
pbreak_predictions-Tracking), `stop_approach`, das Modell selbst und die
closed_by=sr_close-Historie in der DB. Live gegengeprueft: die drei Felder sind
aus dem Snapshot verschwunden, sr_close_hint und stop_approach sind da, beide
Endpunkte antworten 405.
Sicherung: .removed_backup/sr_auto_close_2026-08-21.py

⚠ Der Close-Alarm gilt jetzt schlicht ab jedem Gewinn (`minGain = 0`) - die
Schwelle gab es nur fuer den Auto-Close. Das ist der Zustand von vor 2026-07.

⚠ Der Test test_automatik_zeile_nennt_alle_schalter war MITGEZAEHLT und faellt
korrekt - er ist angepasst, nicht entfernt: jetzt zwei Schalter statt drei, und
die Negativ-Pruefungen ("SIG"/"S/R-Close" duerfen NICHT auftauchen) sind der
eigentliche Wert, denn ein wieder auftauchender Pfad waere ein stiller Rueckbau.

(2) CIRCUIT BREAKER als runder Knopf "CB" rechts neben BALANCE.
⚠ Farb-Logik wie vorgegeben: GRUEN = inaktiv (aus), ROT = aktiv (scharf).
Bewusst NICHT die uebliche "gruen = geschuetzt"-Lesart - hier signalisiert Rot,
dass eine Automatik eingreifen kann. Im Code und im Markup steht das dran, damit
es niemand spaeter "korrigiert".
⚠ VERSCHOBEN, nicht kopiert: zwei Elemente mit derselben ID waeren ein stiller
Fehler, weil getElementById nur das erste findet.

⚠ Beim Entfernen zwei eigene Fehler: (a) ein Slice ueber `rindex("try:")`
schnitt durch fremde Konstruktor-Bloecke und riss Kommentar-Fragmente heraus -
zurueckgesetzt und zeilenbasiert von hinten neu gemacht; (b) beim Toast-Block
eine Klammer zu viel entfernt, von `node --check` sofort gefangen.

Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen, deployt und am
ausgelieferten HTML/Snapshot verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 10:47:44 +02:00
Axel HocksandClaude Opus 5 ebf10da00e G/V eingefroren: Trend-Loop haing am mt5_lock + bind() legte keine DB-Zeile an
User: "G/V aktualisiert nicht mehr."

⚠⚠ BEFUND 1 - ES WAR EIN HAENGER, KEIN ANZEIGEFEHLER. Der Snapshot war frisch
(ts lief weiter), aber `position.pnl` und `cur_price` standen still, waehrend
der Broker-Profit zwischen 1,23 und 1,62 pendelte. Die Loop-Spuren im Log:
  _trend_loop   letzte Zeile 22:30:05  (= Serverstart)
  _pos_loop     letzte Zeile 22:31:20
  _price_loop   lief weiter, scheiterte aber: "Time-Stop-Close fehlgeschlagen:
                MT5 belegt" - alle 15 s, ueber vier Minuten.
Jemand hielt den mt5_lock dauerhaft. Folge: KEIN Trailing-Nachzug, KEIN
Time-Stop, KEIN Circuit-Breaker, KEIN Notfall-Stop. Die Position lief nur noch
am Broker-SL.

URSACHE (nicht bewiesen, aber die Gleichzeitigkeit ist eindeutig): heute kamen
VIER zusaetzliche PatternDetector dazu, und der Trend-Loop rief alle FUENF in
EINER Schleife auf. Jeder macht `copy_rates_from_pos(240)` unter
`mt5_lock(timeout=2)`. Die gestaffelten Drosseln (20/25/35/60 s) greifen dabei
NICHT: beim Start sind alle faellig, also liegen fuenf Fetches unmittelbar
hintereinander unter demselben Lock. Der Trend-Loop blieb genau dort stehen.
Behoben: REIHUM statt Pulk - je Durchlauf genau EIN Detektor. Der Trend-Loop
laeuft im Sekundentakt, jede Zeitebene kommt weiterhin oft genug dran.
⚠ Ohne Thread-Dump (py-spy nicht installiert) ist die Ursache nicht bewiesen.
Die Lock-Last je Durchlauf zu fuenfteln ist aber unabhaengig davon richtig.
Nach dem Neustart 3 Minuten beobachtet: 0x "MT5 belegt", _pos_loop lebendig,
G/V folgt dem Kurs wieder.

⚠⚠ BEFUND 2, direkt danach aufgefallen: "DB-Nachtrag T=50454589 nach 60
Versuchen aufgegeben". `TradeManager.bind()` setzt das Ticket DIREKT und
umgeht damit den Adoptions-Zweig in `_refresh_locked`, der sonst
`history.log_trade_open` ruft (ein `nur_ticket`-Manager steigt dort ohne Ticket
sofort aus). Fuer eine gebundene Position gab es also GAR KEINE DB-Zeile, und
`tag_bot_trade` fand nichts zum Aktualisieren.
Das ist Deployment-Drift Fall 8 in neuer Form: nicht die Strategie driftet,
sondern ihre BEOBACHTBARKEIT - der Trade fehlte in B4-Monitor, squeeze_b5 und
squeeze_entry_gap. Genau der Pfad, der seit dem Pending-Umbau 7 von 8
BRK-Trades traegt.
Behoben in `bind()`, gekapselt (ein DB-Fehler darf das Binden nicht
verhindern). Die laufende Position nachgetragen (DB-Backup
oil_widget_history.db.bak-2026-08-20-bind).

 NEBENBEI DER LIVE-BELEG FUER DEN TRAILING-FIX VON HEUTE MORGEN:
  22:39:34 🧷 BRK-Slot uebernimmt Pending-Fill T=50454589
  22:39:34 Trailing des BRK-Slots aktiviert (T=50454589)
Vor dem Fix waere diese Position nur mit dem Broker-SL gelaufen - die gemessen
durchgefallene SL-only-Variante. Snapshot bestaetigt `trail: true`.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:43:19 +02:00
Axel HocksandClaude Opus 5 21f2dda983 Anzeigefelder im aktuellen Trade noch einmal 2 px kleiner (v=208)
User-Vorgabe. Zweite Stufe, gezielt auf die ANZEIGEFELDER.

`.tb-val` 0,8333rem -> 0,7222rem (15 px -> 13 px bei der 18-px-Referenz, in der
die rem-Werte entstanden sind). Betrifft Richtung, Lots, Einsatz, Laufzeit,
SL/TP und TP1/TP3.

⚠ BEWUSST NUR `.tb-val`: die EINGABEfelder (`.tb-field input`) bleiben bei
0,8333rem. Dort wird getippt, und unter rund 16 px zoomt iOS beim Fokus
selbsttaetig ins Feld - das reisst am Handy das Layout auseinander. Die
Anzeigeboxen haben dieses Problem nicht.

⚠ Umgesetzt als eigene, SPAETERE Regel statt einer Aenderung an der
Sammelregel `.tb-field input, .tb-field .tb-val` - so bleiben Eingaben und
Anzeigen getrennt einstellbar. Reihenfolge geprueft: die spezifische Regel
steht spaeter und gewinnt.

Am ausgelieferten CSS verifiziert (input 0,8333rem / tb-val 0,7222rem).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:32:31 +02:00
Axel HocksandClaude Opus 5 71abb49cf7 Meldungen entschlackt, Bild-Modalbox, neues Muster, kleinere Trade-Schrift, M15 eingeklappt (v=207)
Fuenf User-Vorgaben in einem Durchgang.

(1) HYPERLIQUID + MUSTER + TRAILING AUS DER MELDUNGEN-KARTE. Die drei Divs sind
ENTFERNT, nicht nur versteckt; die Render-Bloecke bleiben stehen (null-sicher),
damit ein Zurueckholen eine reine HTML-Aenderung ist. Backend rechnet
unveraendert weiter (hl_ctx, patterns_tf, trail_info stehen im Snapshot).
Stufe F bekam eine dokumentierte Ausnahmeliste - sonst haette sie drei
Dauer-Treffer gemeldet, und eine Pruefung mit Dauer-Treffern wird ignoriert.

⚠⚠ DABEI ZWEI ECHTE ABSTUERZE GEFUNDEN - und der Weg dahin ist der Punkt.
`hl-note` wurde ueber das Auffang-`$` geholt; nach dem Entfernen des Elements
griffen ZWEI Zweige ungeschuetzt auf `hlEl.classList` zu. Im Browser ein
TypeError mitten im Render = das GESAMTE Dashboard friert auf Altwerten ein.
Die Render-Probe blieb zunaechst GRUEN - ihr eigener blinder Fleck: die
DOM-Attrappe lieferte fuer JEDE ID ein Element, `$streng` konnte darin also NIE
`null` zurueckgeben. Genau der Fall, fuer den es `$streng` gibt, war ungeprueft.
Behoben: die Attrappe kennt jetzt die echten IDs aus index.html
(`getElementById: id => HTML_IDS.has(id) ? el() : null`) - und meldete die
beiden Zweige im selben Lauf. Danach beide Waechter ergaenzt.

(2) BILD-MODALBOX. Klick auf ein Chartmuster oeffnet es gross.
⚠⚠ BEWUSST OHNE BIBLIOTHEK: ein Lightbox-Paket waere 15-40 KB plus ein zweites
Bedienkonzept fuer ~30 Zeilen Code. Das Dashboard laeuft nur ueber WireGuard,
ein CDN ist gar nicht erreichbar; das Projekt hat aus demselben Grund Tailwind
abgelehnt und am 05.08. die vendorte lightweight-charts (164 KB) entfernt.
Delegierter Klick auf `document`, weil die Kacheln bei JEDEM Render neu erzeugt
werden - ein Handler am <img> waere nach dem naechsten Snapshot weg.
Grosse Fassung (1408 px, ~133 KB) liegt getrennt unter muster/gross/ und wird
ERST beim Klick geladen; die Kachel bleibt bei 25 KB. Esc und Klick auf den
Hintergrund schliessen.

(3) NEUES BILD gescannt: "Inverse Tasse+Henkel.jpg". `inv_cup` hatte bis dahin
ausdruecklich KEIN Bild ("lieber keins als ein falsches") - jetzt zugeordnet.
Damit 16 Muster, keins ohne Datei, keine Datei ohne Zuordnung.

(4) SCHRIFT IN DER TRADE-LEISTE um 2 px (bezogen auf die 18-px-Referenz)
verkleinert - 4 Regeln: Ueberschrift, Feldbeschriftungen, Werte/Eingaben,
Knoepfe.
⚠ Erster Versuch nahm alles zwischen `.tb-title{` und `.mg-row` und traf 80
Regeln statt 4 - die halbe Oberflaeche. Zurueckgesetzt und namentlich
aufgezaehlt. Ein Zeilenbereich ist kein Selektor.

(5) M15-KARTE PER DEFAULT EINGEKLAPPT. Das `open` am ersten <details> ist weg.
⚠ Zusaetzlich der localStorage-Schluessel gebumpt (oil_m15_akk -> oil_m15_akk2):
bei jedem, der die Karte je aufgeklappt hatte, stand dort `true`, und das
gewinnt gegen den neuen Default. Ein neuer Schluessel setzt genau EINMAL
zurueck; danach merkt sich die Karte die eigene Wahl wie bisher.

Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen (Fixture UND leerer
Snapshot), deployt und am ausgelieferten HTML/JS verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:27:18 +02:00
Axel HocksandClaude Opus 5 06024dd0c1 Muster-Bilder ins Dashboard hinter die Meldungen + M15-Karte sagt jetzt, WARUM kein Setup (v=205)
(1) BILDER INS DASHBOARD (User-Vorgabe). Das Raster `#pt-tfgrid` sitzt jetzt in
einer eigenen Karte `#card-muster` direkt hinter der Meldungen-Karte, vor der
Breakout-Karte. VERSCHOBEN, nicht kopiert: eine zweite Kopie haette eine
doppelte Element-ID erzeugt, und getElementById liefert dann immer nur die
erste - die zweite Karte waere still leer geblieben. Im Tab "SIG Live" bleibt
die M30-Detailliste mit Trigger und Kursziel (sie traegt das Verdict-Gewicht
0,25; die Bilder tragen keins).
Geprueft am ausgelieferten HTML: 0 doppelte IDs, pt-tfgrid genau 1x, Reihenfolge
Meldungen -> Muster -> BRK, Tag-Balance 20/20.

(2) "DIE TP IN DER M15 KARTE SIND NICHT MEHR SICHTBAR" - kein Fehler, aber die
Anzeige war schuld. Der Setup-Block verlangt `sb && erl && nah && atr>0`, und
`erl` (die erlaubte Richtung) kommt aus dem VETO. Live steht bias.verboten auf
None, weil M30 flach ist (m30=0) - also gibt es keine erlaubte Richtung, und
ohne Richtung sind Entry Zone, Stop und TP1-3 nicht bestimmbar. Genau so ist es
am 10.08. entschieden worden ("kein Veto - Richtung offen, kein Ziel
bestimmbar").
Der Block verschwand dabei aber KOMMENTARLOS. Ein leeres und ein blockiertes
Feld sahen identisch aus - dieselbe Klasse wie "Slot frei" beim Breakout und wie
das schweigende Trailing, beide heute aus demselben Grund repariert. Jetzt steht
dort: "Kein Setup: kein Trend-Veto (M30 flach) - ohne erlaubte Richtung sind
Entry Zone, Stop und TP nicht bestimmbar." Die beiden anderen Abbruchgruende
(kein Level in Reichweite / ATR fehlt) werden ebenfalls benannt.

Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen laufen durch (Fixture und
leerer Snapshot), deployt und am ausgelieferten HTML verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:11:59 +02:00
Axel HocksandClaude Opus 5 02bede7ef9 Chartmuster je Zeitebene als Bild + M1/M5 in der Meldungskarte (v=204)
User-Vorgabe: die hinterlegten Muster-Bilder sollen je Minuten-Chart das
gerade entstehende Muster zeigen, M1 und M5 zusaetzlich in der Meldungskarte.

BILDER: 15 Vorlagen aus /Chartmuster, 436-611 KB je Stueck (7,5 MB gesamt).
Das Dashboard uebertraegt ~14 KB je Snapshot ueber WireGuard - ein Originalbild
waere das 40-fache. Verkleinert auf 520 px / JPEG q80 nach web/muster/:
7,5 MB -> 379 KB (Faktor 20), im Frontend zusaetzlich loading="lazy".
Die Originale sind gitignored, nur die Web-Fassungen kommen ins Repo.

DETEKTOR: core/patterns.py bekommt die Zeitebene als PARAMETER. Der Default
bleibt M30 und damit bitgleich - `PatternDetector()` speist das Verdict-Gewicht
0,25, eine stille Verschiebung dort waere eine Strategie-Aenderung durch die
Hintertuer. Daneben laufen vier weitere Instanzen (M1/M5/M15/H1) mit
gestaffelten Refresh-Zeiten (20/25/35/60 s), damit sie den mt5_lock nicht im
Pulk belegen. Sie haben KEINE Stimme.

Neu Snapshot `patterns_tf`: je Zeitebene das STAERKSTE Muster (bestaetigte vor
sich bildenden, dann Symmetrie-Guete; ungueltige fallen raus) samt Bildnamen
ueber die Karte `patterns.BILD`.
Doppeltop/-boden, Dreifach-Top/-Boden und Flagge bull/baer teilen sich je ein
Bild (die Vorlagen zeigen beide Richtungen); `inv_cup` bekommt KEINS - lieber
kein Bild als ein falsches.

⚠⚠ REINE ANZEIGE, und das steht auch dran. Die Muster-Klasse ist als SIGNAL
gemessen und verworfen (Ziel-Trefferquote nur 13-38 %, backtest_patterns.py),
und auf M1 ist sie am schwaechsten: dort liegt der Spread bei 0,319xATR, ein
Muster ueber wenige Bars ist weitgehend Rauschen. Kein Verdict-Gewicht, kein
Trade-Trigger; die Tooltips nennen die Messung.

⚠ Beim Bau zwei eigene Fehler gefangen: (1) ich hatte die Feldnamen GERATEN -
es heisst `type`, nicht `typ`, und der Status ist "confirmed"/"forming"/
"invalidated". Ein falscher Schluessel haette still None geliefert, die Karte
waere leer geblieben ohne jede Fehlermeldung. (2) Der Emoji-Surrogat-Abbruch
zum sechsten Mal - die .tmp-Regel hat app.js erneut gerettet (0 Bytes verhindert),
danach mit literalen Zeichen statt \u-Escapes geschrieben.

Live verifiziert: M1 Doppelboden, M5 Tasse+Henkel, M15 aufsteigendes Dreieck,
M30 Doppeltop; alle Bilder HTTP 200 (22-28 KB). Pipeline A-G gruen, 97 Tests,
14 render*-Funktionen laufen durch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 22:05:18 +02:00
Axel HocksandClaude Opus 5 fd2ca46dc0 Ruhende Orders: aufraeumen statt liegenlassen (User-Vorgabe)
User: "was sind ruhende orders. Loesche die wenn der trade nicht eroeffnet
werden kann." Anlass: MT5 zeichnete SL/TP-Linien, obwohl keine Position lief.
Das waren die liegenden Stop-Orders des Breakout-Traders - MT5 stellt jede
Pending-Order samt mitgeschicktem SL selbst dar. Der Bot exportiert NIE SL/TP
ins Chart (0 Treffer im .mq5, keine SL-Zeile in der CSV). Kein Anzeigefehler.

ZWEI ECHTE VERWAISUNGS-PFADE GEFUNDEN. _manage_squeeze_pending stieg VOR dem
Aufraeum-Block aus, wenn squeeze_pending_entry=false oder kein Symbol da war.
Die Orders sind ORDER_TIME_GTC - sie verfallen NICHT. Eine so verwaiste Order
haengt beim Broker, wird von niemandem mehr bewertet und kann Stunden spaeter
fuellen: ohne Dedup, ohne Guard-Pruefung und (bis heute) ohne Trailing.
Neu engine._pendings_abraeumen(sym, grund) - beide Pfade raeumen jetzt ab.

DIE EIGENTLICHE VORGABE: ein halbes Setup wird aufgeloest. Scheitert eine Seite
mit Lot-Fehler (freie Margin reicht nicht fuers Mindestlot), wird auch die
Gegenseite storniert - der gemessene Squeeze ist ein Ausbruch in BEIDE
Richtungen; laege nur eine Seite, handelte der Bot ihn nur noch in eine.
Ausdruecklich NICHT bei "Kurs hat das Level bereits passiert": das ist
voruebergehend und betrifft nur die eine Seite. Der Lot-Fehler betrifft das
KONTO und damit beide.
Erkannt ueber die Konstante mt5_utils.LOT_ZU_KLEIN, nicht ueber ein deutsches
Wort im Fliesstext - eine Erkennung, die an einer Formulierung haengt, hoert
still auf zu funktionieren und faellt dabei auf die stille Seite.

⚠⚠ DIE LOG-DROSSEL WAR AM SELBEN TAG ZUM ZWEITEN MAL AUSGEHEBELT - durch meine
eigene Verbesserung. Vormittags lag der Merker in EINER Variable fuer beide
Seiten (behoben). Dann bekam die Meldung ueber lot_grund ihre Zahlen, und die
freie Margin aendert sich mit jedem Tick: der Text war jedes Mal neu, der
Vergleich traf immer zu, wieder 2 Zeilen pro Sekunde.
Gedrosselt wird jetzt auf die URSACHE, nicht auf ihre Formulierung (_err_key:
alle Zahlen -> #). Gemessen: 7 Zeilen in 90 s statt ~180, und die verbliebenen
sind echte Wechsel zwischen den beiden Ursachen.
Lehre: eine Drossel, die einen TEXT vergleicht, ist so stabil wie der Text.

Live verifiziert: 0 liegende Orders, keine verwaisten Reste, Startup-Schonfrist
raeumt korrekt ab, Orders kommen danach zurueck sobald die Margin reicht.
Pipeline gruen (A-G), 97 Tests, deployt mit --feld squeeze_block.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 20:29:26 +02:00
Axel HocksandClaude Opus 5 3fb9c3fd2e 6. Durchgang: Slots, JavaScript, Bibliotheken - jede Achse jetzt eine Pipeline-Stufe
Die vorigen Durchgaenge waren Handarbeit und liefen nur, wenn jemand daran
dachte. Jetzt sind alle drei automatisiert.

JAVASCRIPT - DIE RENDER-PROBE DECKTE 2 VON 15 FUNKTIONEN AB.
render_check.mjs schnitt per Regex genau ZWEI Funktionen heraus (renderM15,
renderBrk). renderKontext und 13 weitere waren nie abgedeckt - und genau dort
ist mir heute der d-statt-snap-Beinahefehler unterlaufen. Die Probe haette ihn
DURCHGELASSEN.
Neu geschrieben: die komplette app.js laeuft in einem VM-Kontext gegen ein
Minimal-DOM, jede render*-Funktion wird aufgerufen - zweimal, mit dem Fixture
UND mit einem leeren Snapshot (der Kaltstart, in dem jedes Feld fehlt).
13 Funktionen laufen durch. Mutationsprobe mit genau dem heutigen Fehler:
4 Treffer, waehrend node --check NICHTS meldet - der blinde Fleck ist damit zu.
Kein npm, kein jsdom: das DOM ist eine Attrappe von 20 Zeilen, Pruef- und
Laufumgebung bleiben derselbe Parser.

ZWEI NEUE STUFEN, beide mutationsgeprueft:
  F) ELEMENT-IDs - JS gegen HTML. Stand: 133 IDs, keine verwaist, keine doppelt.
     Kommentare werden vorher entfernt, sonst waeren die Beispiele im
     Kopfkommentar zwei Dauer-Fehlalarme (die Lehre vom Linter).
  G) ABHAENGIGKEITEN - jeder Import aus server.py/core/ gegen requirements.txt.
     Stand: 39 Dateien, alle 9 externen Importe aufgefuehrt, keine Versionsdrift.

UND DIE PIPELINE HAT SICH SELBST ERWISCHT: mein erster Entwurf von Stufe G
importierte `ast` nicht. Der stille except-continue liess JEDE Datei
durchfallen, und die Stufe meldete "alle 0 externen Laufzeit-Importe sind
aufgefuehrt" - ein gruener Haken, hinter dem nichts geprueft wurde. Fuenfte
Wiederholung dieser Fehlerklasse. Gefangen hat es ruff F821 in derselben
Pipeline. Behoben doppelt: Import ergaenzt UND Plausibilitaetspruefung (weniger
Dateien gelesen als vorhanden oder 0 Importe -> Befund).

SLOTS - keine neuen Defekte, drei Punkte praezisiert:
  · Kein geteilter Modul-Zustand. Die modulweiten Container in trailing.py und
    trader.py sind reine Nachschlagetabellen, kein global-Statement. Die beiden
    Instanzen sind tatsaechlich unabhaengig - Voraussetzung des ganzen Umbaus.
  · set_sltp bleibt Slot-1-only, verhaelt sich aber SICHER: liegt nur eine
    BRK-Position, gibt modify_sltp einen Fehlertext zurueck. Es fasst NICHT die
    falsche Position an. Bekannte Grenze, kein Fehler.
  · trail_brk.enabled wird nicht persistiert; _rebind_brk schaltet es nach einem
    Neustart bedingungslos ein. Sichere Richtung, bewusst so gelassen.

BIBLIOTHEKEN: nichts fehlt, nichts driftet. pandas/scikit-learn stehen in
requirements-dev und werden in 0 Dateien importiert (so dokumentiert); numba,
joblib, tqdm, pandas_ta, rich, httpx sind Beifang und ungenutzt - kein
Handlungsbedarf, sie stehen nicht im Laufzeit-Pfad.
Struktureller Rest benannt: engine.py importiert weekly_review und
measurement_reminder, zwei Skripte der obersten Ebene - dieselbe Klasse wie der
frueher direkte backtest-Import. Hier entschaerft, weil lazy und in try, mit
sichtbarer Fehlermeldung. In Stufe G als projekteigen ausgenommen, mit
Begruendung im Code.

Pipeline jetzt A A2 A3 B B2 C C2 D E F G - alle gruen, 97 Tests, deployt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 20:06:46 +02:00
Axel HocksandClaude Opus 5 3391e04f32 Bibliotheken geprueft: zwei Ertraege, keine neue Laufzeit-Abhaengigkeit
Nicht nach Katalog beantwortet, sondern gegen die dokumentierten Schwachstellen
des Projekts - und beide Kandidaten wurden GEMESSEN, nicht empfohlen.

ERTRAG 1 - BLOCK-BOOTSTRAP (core/stichprobe.block_ci95), braucht GAR KEINE
Bibliothek. Die Luecke stand seit dem 07.08. woertlich in backtest_cost_gate:
"fuer ueberlappende Beobachtungen zu optimistisch ... dafuer braeuchte es einen
Block-Bootstrap". Behelf war entkoppeln(). Auf echten Daten (pbreak_predictions):
  naiv, alle Zeilen   n=4702  Breite 0,028   <- 3x zu eng
  entkoppelt (bisher) n= 552  Breite 0,083   <- 88 % Datenverlust
  Block L=30          n=4702  Breite 0,081   <- gleiche Breite, ALLE Daten
Und das Entkoppeln kostet nicht nur Genauigkeit, es VERSCHIEBT die Schaetzung
(0,399 gegen 0,427) - es nimmt systematisch die ERSTE Beruehrung je Level+Stunde.

KALIBRIERUNG GEMESSEN (AR(1), bekanntes Mittel, 200 Laeufe, Soll 95 %):
  rho    naiv   L=10   L=30   L=60
  0,00   94 %   94 %   91 %   92 %
  0,50   76 %   92 %   91 %   91 %
  0,90   40 %   80 %   89 %   90 %
  0,97   18 %   55 %   74 %   83 %
Die naive Zeile ist der Befund: bei rho=0,97 behauptet sie 95 % Sicherheit und
liegt in 18 % der Faelle richtig. Ehrlich zu den Grenzen: bei unabhaengigen
Daten kostet der Block ~3 Punkte (dort bleibt ci95 besser), und bei rho=0,97
deckt auch er nur 83 % - eine Verbesserung, keine Garantie.

ERTRAG 2 - hypothesis (dev-only), aufgenommen NACH einer Gegenprobe. Die Suite
prueft bisher BEISPIELE, und die waehle ich selbst aus. Die teuersten Fehler
sassen auf GRENZEN: room_info musste `frei` auf dem UNGERUNDETEN Abstand
entscheiden, weil 0,5951 gerundet durchs 0,6-Gate rutscht. hypothesis findet
genau diesen Fall (dist=0.59765625) in Sekunden. Erst danach aufgenommen.
Neu tests/test_invarianten.py (4 Eigenschafts-Tests auf REINEN Funktionen), per
importorskip - die Suite laeuft auch ohne.
Beim ersten Lauf fielen zwei Tests, beide waren MEINE Fehler: cluster rundet auf
3 Stellen (Invariante zu streng) und zwei inhaltsgleiche dicts sind ==
(Reihenfolge muss ueber die Identitaet geprueft werden). Genau dafuer sind
Property-Tests da. Mutationsprobe: Rundung verbogen -> 2 Tests fallen.

BEGRUENDET ABGELEHNT: numba (Backtests 11 s/12k Bars = nicht der Engpass, und
ein Rewrite verletzt die Bit-Gleichheits-Regel) · statsmodels/arch (jetzt 15
Zeilen stdlib mit eigener Kalibrierung) · polars/pyarrow (kein DataFrame-
Workload) · loguru/structlog/rich (das Logformat ist forensisch tragend) ·
tenacity (Wiederholungen haben eigene Semantik, _mark_dead) · httpx (requests
laeuft) · pandas_ta (Indikatoren sind validiert, ein Austausch verschoebe jede
dokumentierte Zahl) · mypy (kaum Annotationen, ty deckt die Aritaet ab).

requirements.txt (Laufzeit) bleibt UNVERAENDERT - auf einer frischen Maschine
soll der Bot mit moeglichst kleiner Oberflaeche wieder laufen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 19:57:31 +02:00
Axel HocksandClaude Opus 5 0386497a79 Slot-Pruefung 5. Durchgang: drei Luecken, eine davon gravierend
Diesmal systematisch statt punktuell: alle Methoden von TradingEngine per AST
klassifiziert, welche Slot-Objekte sie beruehren. 36 Funktionen fassen einen
Slot an, 20 davon NUR Slot 1.

⚠⚠⚠ LUECKE 1 (gravierend): EINE FRISCH GEFUELLTE BRK-POSITION HATTE KEIN
TRAILING. trail_brk.toggle() wurde an genau ZWEI Stellen gerufen - _rebind_brk
(nach Neustart) und toggle_trail (der Knopf). Der frische Pending-Fill kam in
keiner davon vor, und das ist der haeufigste Weg, auf dem eine BRK-Position
entsteht (7 von 8 Trades seit dem Pending-Umbau). Sie lief damit nur mit dem
Broker-SL - exakt die Variante, die backtest_brk_slonly.py verworfen hat (alle
zehn KI enthalten die Null, Trefferquote 40 -> 21 %).
Von aussen unsichtbar: die Position sieht in jeder Anzeige normal aus, ihr
fehlt nur der Schutz. Ironie: _rebind_brk loggt "Trailing wiederhergestellt" -
wiederhergestellt wurde etwas, das fuer einen frischen Fill nie an war.

⚠⚠ LUECKE 2: der Market-Fallback schaltete das FALSCHE Trailing ein. _open rief
pauschal self.trail.toggle(). Zwei Schaeden auf einmal: die BRK-Position bleibt
ungeschuetzt UND auf der manuellen Position wird das Trailing wieder
eingeschaltet, auch wenn der Nutzer es dort bewusst abgeschaltet hatte (nach
einer SL-Handeingabe). Sein handgesetzter Stop waere weitergezogen worden.
Noch nicht eingetreten, weil alle acht Fallback-Versuche des 20.08. schon an
der Order scheiterten.

⚠⚠ LUECKE 3: ein geschlossener BRK-Trade loeste KEINE Telegram-Meldung aus.
_close_notify_pending wird in _check_auto_close armiert, das self.trader liest.
Wiegt schwer, weil seit dem 19.08. NUR NOCH "Trade geschlossen" durch den
Telegram-Filter kommt - der autonome Pfad haette vollstaendig still gehandelt.
Behoben in _check_brk_close_cooldown, das den BRK-Flat-Uebergang ohnehin kennt.

Dazu die Reichweiten-Warnung korrigiert: sie sagte "Broker-SL, Trailing und
Circuit-Breaker greifen weiter" - das Trailing tat es eben NICHT.

ABGESICHERT auf zwei Ebenen, beide mutationsgeprueft:
  tests/test_pending_fill.py +2: der Fill MUSS trail_brk einschalten und DARF
    das Trailing von Slot 1 nicht anfassen. Mutation -> Test faellt.
  Pipeline-Stufe E, Regel E: jeder Pfad, der eine BRK-Position eroeffnet
    (_check_pending_fill, _open), MUSS trail_brk erwaehnen. Mutation -> Exit 1.
Die Test-Fixture bekam dafuer erstmals BEIDE Trailing-Attrappen - ohne die war
der gefaehrlichste Slot-Fehler ueberhaupt nicht pruefbar.

GEPRUEFT UND SAUBER: Circuit-Breaker, close(), _check_open_notify, _price_loop,
_write_levels_file, snapshot, die Fill-Bindung, die _pos_loop-Reihenfolge.

BEWUSST NICHT GEAENDERT (Slot-1-only, aber alle Features AUS): _check_auto_close,
_check_sr_close, _check_adverse15, _check_flip_close, _check_auto_m15, set_sltp,
_check_close_alert. _check_slot_reichweite meldet es, sobald eines eingeschaltet
wird. Zweislot-faehig waere ein Umbau der Notfall-Zustandsmaschine - offen.

⚠⚠ ZWEI CONFIG-WERTE SIND AUF 0 ZURUECKGEDRIFTET (nur berichtet):
  close_notify_min_eur      dokumentiert 50 -> ist 0 (Telegram ganz still)
  auto_emergency_margin_pct dokumentiert  8 -> ist 0
Bei close_notify_min_eur = 0 nuetzt auch Luecke 3 nichts - die Vormerkung haengt
an _close_notify_min > 0. Der Bot meldet derzeit gar keinen Trade-Abschluss.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 19:45:05 +02:00
Axel HocksandClaude Opus 5 437ab56598 Trailing tat nichts - beide Gruende waren richtig, nur unsichtbar (v=203)
User: "trailing scheint nicht zu funktionieren wenn man es einmal manuell
aktiviert hat und dann wieder einschaltet."

AM LOG UND AM ZUSTAND NACHGEPRUEFT - es lief die ganze Zeit:
  19:30:52  Manuelle SL/TP-Aenderung erkannt (SL 87.297) -> Trailing abgeschaltet
  19:31:01  AKTIVIERT  ATR=0.5689 (M30)  mult=1.0x
  danach     phase=Init, HW 87.39, enabled=true, trail_mult=1.0
`toggle()` setzt alles sauber zurueck (High-Water, Phase, _last_sl/_last_tp,
TF und Mult werden neu eingefroren). Es war KEIN Defekt.

WARUM ES TROTZDEM NICHTS TAT - zwei Gruende, beide korrekt:
(a) Phase "Init": der Trail springt erst ab `trail_start` an, und der steht
    seit HEUTE auf 1,3xATR (war 0,3). Der Gewinn lag bei 0,13xATR - also
    Faktor 10 zu frueh. Wer die alte Einstellung gewohnt ist, erwartet den
    Trail zehnmal frueher als er kommt.
(b) Er lockert einen Stop NIE. Nach der Handeingabe lag der SL bei 87.300,
    der Trail haette HW-1,0xATR = 86.821 gewollt - deutlich schlechter. Also
    zu Recht keine Aenderung. Um 87.300 zu schlagen, braeuchte es HW >= 87.869.

DER EIGENTLICHE MANGEL WAR DIE SICHTBARKEIT: die Trailing-KARTE ist seit dem
22.07. ausgeblendet (User-Vorgabe). Damit gab es KEINE Stelle mehr, an der man
Phase, High-Water oder den gewollten Stop sehen konnte - "es tut nichts" und
"es wartet zu Recht" sahen identisch aus.

GEBAUT: `engine._trail_info()` -> Snapshot `trail_info` -> Zeile `#trail-note`
in der Meldungen-Karte. Live:
  "Trailing wartet - springt ab 1.3xATR Gewinn an (jetzt 0.38x, also ab Kurs
   88.054)."
Drei weitere Zustaende: "Trailing AUS - nur der Broker-SL schuetzt", "laeuft,
zieht aber NICHT nach: sein Stop waere X, der gesetzte Y ist enger", und
"laeuft - zieht den Stop auf X nach".
⚠ Nur ZUSAMMENGESETZT aus dem, was der Snapshot ohnehin enthaelt - kein
zweiter Rechenweg (der Konsens-Pfeil-Fehler).

⚠⚠ BEINAHE-FEHLER beim Bau, gefangen: der Block landete in `renderKontext(snap)`,
mein Code las aber `d.trail_info`. Ein ReferenceError haette den GESAMTEN Render
abgebrochen (Dashboard friert auf Altwerten ein) - genau die Klasse, die am
01.08. schon einmal zugeschlagen hat. `node --check` sieht das NICHT. Gefunden,
weil ich die umgebende Funktion nachgelesen habe, und danach mit einem
Minimal-DOM gegengeprueft (snap / leer / null - alle drei laufen durch).

NEBENBEI: der Kommentar an `_TRAIL_START_ATR` sagte weiterhin "0,3", der Wert
ist 1,3. Genau diese Zahl macht den Unterschied, um den es hier geht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 19:36:30 +02:00
Axel Hocks b5a841d52e CLAUDE.md: warum BRK nicht eroeffnet (Margin-Kette, runtime_state ueberstimmt ini) 2026-08-20 16:31:15 +02:00
Axel Hocks fe01596020 BRK-Blockade sichtbar machen + runtime_state-Ueberstimmung melden 2026-08-20 16:30:07 +02:00
Axel HocksandClaude Opus 5 b448a7ade8 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>
2026-08-20 14:26:43 +02:00
Axel HocksandClaude Opus 5 a35ea38d31 Tagestrend: vier Varianten gemessen, keine besteht - nichts gebaut
User: "hast du Optimierungsvorschlaege um den Tagestrend mehr Gewicht zu
verleihen?" Vier konkrete Vorschlaege, alle VORHER gemessen statt gebaut.
backtest_tagestrend.py (neu): 60k M5 = 244 Handelstage, voller Live-Gate-Stack
(echtes `_build` + Breakout k=0,3 + `_room_gate`), kanonischer Exit,
Echtkosten, 2 Halbjahre, 95-%-Bootstrap, Schwellen 0,15 / 0,30 / 0,60 %.
Tagestrend = Kurs gegen die TAGESEROEFFNUNG (Berlin, DST-korrekt) - das, was
ein Mensch sieht, und es braucht keinen 16.000-Bar-Vorlauf.

                        H1 OeR/SR        H2 OeR/SR       n
  BASIS               -0,062 / -34,9   -0,107 / -88,9   563/831
  A VETO              -0,058 / -31,5   -0,114 / -89,5   543/785
  B NUR-MIT           -0,010 /  -4,8   -0,126 / -86,1   483/683
  C SPAET (3,5->5,0)  -0,031 / -20,3   -0,089 / -84,8   656/953
  D PULLBACK          -0,008 /  -1,6   -0,012 /  -3,5   196/291

A und B: in H2 an ALLEN DREI Schwellen schlechter als BASIS; die von ihnen
entfernte Gruppe kippt zwischen den Haelften (+0,032 bzw. +0,208 in H2) - sie
werfen also teils die BESSEREN Trades weg. Vierte Messung dieser Klasse nach
Hoeher-TF-Winkel, H1-Staerke und Konfluenz-Strafe.

C sieht beidhaelftig besser aus und ist trotzdem kein Beleg: die zusaetzlich
genommenen Trades sind H1 -0,134 / H2 +0,060, also gegenlaeufig. Aufloesung in
der Mechanik: die Sim hat EINEN Slot, ein Extra-Trade verschiebt die GANZE
Folge. C ist keine Obermenge von BASIS, sondern eine andere Trade-Folge - der
scheinbare Gewinn ist ein Selektionseffekt (die Falle vom 14.08.).

D hat als EINZIGE die richtige Signatur: beidhaelftig besser an allen drei
Schwellen, und die ENTFERNTE Gruppe ist an allen SECHS Stellen negativ
(-0,068/-0,060/-0,063 und -0,072/-0,080/-0,053). Trotzdem kein Bau: jedes
Intervall enthaelt die Null, und der SR-Sprung kommt fast vollstaendig daher,
dass D nur noch 35 % der Trades nimmt - Handelsvermeidung, nicht Edge (Muster
aus backtest_metalabel.py).

INHALTLICHE ANTWORT im Vergleich C gegen D: wenn der Tagestrend etwas
beitraegt, dann NICHT als Erlaubnis fuer den spaeten Einstieg, sondern als
Kontext fuer den RUECKSETZER. Deckt sich mit dem einzigen belegten
Einstiegs-Effekt (Pullback-Bonus +15) und mit dem invertierten Winkel-Befund
vom 04.08.
Ehrlichster Satz zum Lauf: die BASIS-Population ist mit -0,062/-0,107 selbst
negativ. Kein Umgang mit dem Tagestrend macht daraus einen Edge.
29. verworfener Signal-Eingriff.

METHODEN-BEFUND ueber den Lauf hinaus: das Werkzeug fuer den gepaarten
Vergleich war hier das FALSCHE - und es hat es selbst gezeigt (Delta +0,000,
KI von exakt 0,000 bis 0,000 in ALLEN acht Zellen). Diese Varianten aendern
nicht den EXIT, sondern WELCHE Einstiege genommen werden; auf gemeinsamen
Faellen sind die R-Werte per Konstruktion identisch.
Regel: gepaart fuer EXIT-Varianten, Auswertung der entfernten bzw.
hinzugefuegten Gruppe fuer AUSWAHL-Varianten. Ein Intervall von exakt
[0,000 .. 0,000] ist kein Ergebnis, sondern die Fehlermeldung eines falsch
gewaehlten Tests.

Nachtrag: die Nachricht des ersten Commit-Versuchs wurde von der
dokumentierten Backtick-Falle beschaedigt (Kommando-Substitution in der
Bash-Zeile). Diese Fassung kommt ueber eine Datei.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 13:26:37 +02:00
Axel HocksandClaude Opus 5 6ed8980eab Stretch-Gate gemessen: alle 8 gesperrten Baender negativ - Sperre bleibt
User: 'der Tagestrend ist aufwaerts, auch die News bullish - warum wird das in
der Empfehlung nicht beruecksichtigt.'

Praemisse stimmt (+2,47 $ = +2,89 % auf der Tageskerze). Schlussfolgerung nicht:
die Empfehlung WAR LONG - achtmal zwischen 09:13 und 09:51 bei 85,97-86,53,
Kurs steht jetzt 87,70 (+1,73 $). Sie steigt nur nicht mehr SPAET ein.

Blocker ist 'stretch' (_STRETCH_MAX 3,5) - der Kurs steht auf JEDER Zeitebene
weit ueber der EMA50 (M5 +5,18 / M15 +4,63 / M30 +4,36 / H1 +4,39 x ATR).

backtest_stretch_extrem.py (neu): traegt ein Einstieg JENSEITS des Gates?
60k Bars, M30 und M5, kanonischer Exit, Echtkosten, 2 Halbjahre, entkoppelt,
95-%-Bootstrap. Ergebnis: ALLE ACHT gesperrten Zellen negativ (PF 0,83-0,95),
Regel in keiner erfuellt -> Sperre bleibt.
Aufschlussreich: Trefferquote 57-60 % und trotzdem PF < 1 - die dokumentierte
Klein-Close-Signatur. Genau das heisst 'Spaet-Long'.
Ehrlich: nichts in der Tabelle ist positiv, auch die erlaubten Baender nicht -
auf der Ueberdehnungs-Achse ist nichts zu holen, das Gate entfernt nur das
schlechtere Ende.

News: 0 Treffer fuer 'news' in core/wave_rec.py, 0 News-Stimmen im Verdict -
geprueft, nicht vermutet. Score +0,42 liegt zudem unter der 0,5-Warnschwelle.
Messentscheidung vom 03.08. (stark-bullischer Bucket beidhaelftig null bis
negativ), kein Versehen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 13:17:13 +02:00
Axel HocksandClaude Opus 5 ff03ca2f43 Korrektur: die CRLF-"Reparatur" war eine erfundene Baustelle
Im Commit davor habe ich sechs Dateien von CRLF auf LF "zurueckgesetzt" und
das als Nebenbefund verbucht. Das war FALSCH.

core.autocrlf = true -> der Arbeitsbaum dieses Repos IST CRLF, git speichert
intern LF. Kontrolle an unberuehrten Dateien: core/trailing.py CR=756,
core/history.py CR=1436, server.py CR=521, tests/conftest.py CR=129 - alle
CRLF. Mein Schreib-Helfer hat also genau das erzeugt, was ein `git checkout`
erzeugt; meine "Reparatur" machte die sechs Dateien als EINZIGE inkonsistent
zum Rest. Zurueckgedreht. Kein Schaden in keiner Richtung, weil git ohnehin
normalisiert - aber es war Arbeit an einem Problem, das es nicht gab.

⚠ ZWEI ECHTE LEHREN BLEIBEN:
  (1) grep auf das Zeilenende-Zeichen meldete 0, obwohl 8.959 CR-Bytes
      drinstanden -> Zeilenenden nur ueber die BYTE-Zaehlung pruefen.
  (2) len(str) gegen os.path.getsize() zu halten vergleicht ZEICHEN mit BYTES -
      als Schrumpf-Sicherung taugt es, als Groessendifferenz nicht. Genau daran
      sah der Zuwachs zuerst nach +33 kB fuer einen 4,7-kB-Abschnitt aus.

⚠ Und ein dritter Treffer der dokumentierten Backslash-Falle: der Satz ueber
den grep-Fehlalarm enthielt ein ECHTES CR-Byte mitten im Fliesstext (CR=8975
gegen LF=8974). Gefunden nur, weil ich die beiden Zaehlungen gegeneinander
gehalten habe. Formulierung jetzt ohne Backslash.

Pipeline nach der Korrektur komplett gruen: check_nfalle, Stufe E, 97 Tests,
node --check.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 13:09:04 +02:00
Axel HocksandClaude Opus 5 0966caf1b8 G/V-Trennung geprueft: Adoptions-Sperre riss bei JEDEM Neustart auf
User: "ueberpruefe ob wirklich die G/V und G/V BRK Anzeigen stimmen, besonders
bei gleichzeitig laufenden Trades. Die Anzeige darf jeweils nur den eigenen
Slot anzeigen."

FRONTEND SAUBER: #hdr-pnl liest nur d.position, #hdr-pnl-brk nur
d.position_brk - keine Summe, kein Fallback. Aber das ist die falsche Stelle
zum Suchen: stehen im Backend beide Felder auf derselben Position, kann keine
Anzeige das mehr richten. Geprueft wurde deshalb die AUSWAHL in
TradeManager._refresh_locked.

⚠⚠ FUND 1 - die Sperrliste kannte nur zwei von DREI Quellen eines BRK-Tickets:
  trader_brk.ticket     nur im Speicher
  _pending_tickets      nur im Speicher
  _brk_restore          FEHLTE - und nur das ueberlebt den Neustart
Nach einem Neustart sind die ersten beiden leer, und die Reihenfolge im
_pos_loop besiegelt es: trader.refresh() laeuft DREI Zeilen vor _rebind_brk().
Slot 1 greift die BRK-Position also, bevor sie zurueckgebunden werden kann.
_rebind_brk erkennt das zwar und bricht ab - damit ist der Schaden aber nur
festgestellt, nicht behoben: die BRK-Position haengt am falschen Slot, ihr G/V
steht links statt rechts, und "G/V BRK" zeigt "—". Danach sieht alles normal
aus, was es besonders schwer sichtbar macht.
Behoben ueber getattr(..., None), also unabhaengig davon, WANN das Attribut
gesetzt wird - genau die Reihenfolge-Falle, die in zwei Tagen zweimal
zugeschlagen hat.

 FUND 2 - zwei verschiedene Rechnungen nebeneinander. Bei geschlossenem
Markt zeigt Slot 1 seit dem 01.08. eine HL-Schaetzung (pnl_hl), der BRK-Slot
bekam die nie und zeigte den EINGEFRORENEN Broker-Wert, ohne dass man es der
Anzeige ansieht. Neu pnl_hl_brk, mit ≈ markiert. Geprueft statt angenommen,
dass _tick_size/_tick_value am BRK-Slot gesetzt sind.

 day_pl.open summiert korrekt BEIDE Slots - die Summe gehoert dorthin, die
Trennung in die beiden G/V-Felder.

BELEG - tests/test_slot_gv.py, 6 Tests auf dem ECHTEN TradeManager (Broker
gestubbt): zwei Positionen gleichzeitig je im eigenen Slot · Slot 1 adoptiert
die BRK-Position nicht · Pending-Fill wird nicht weggeschnappt · der BRK-Slot
adoptiert nie · plus die Regressionsprobe, die den alten Zustand festhaelt.
NEUE PIPELINE-STUFE E (tools/check_slots.py): die Sperrliste muss alle drei
Namen erwaehnen. Mutationsprobe: Merker entfernt -> Exit 1.
⚠⚠ Ehrlich zur Arbeitsteilung: der pytest belegt den MECHANISMUS, baut die
Lambda aber selbst nach und bleibt bei der Mutation gruen. Erst die statische
Stufe belegt, dass die ENGINE sie richtig verdrahtet. Keine der beiden allein
haette gereicht.

⚠⚠ NEBENBEFUND, korrigiert: mein Schreib-Helfer hat SECHS Dateien still von
LF auf CRLF gedreht (io.open(...,"w") uebersetzt auf Windows). Mein erster
Check mit `grep -c $'\r$'` meldete faelschlich 0 - erst die BYTE-Zaehlung zeigte
8959 CR in CLAUDE.md. Alle sechs auf LF zurueckgesetzt. core.autocrlf=true
haette es im Repo normalisiert, im Arbeitsbaum aber nicht.

Live verifiziert: Slot 1 T=50396824 (+10,34), BRK flat, day_pl.open 10,34 -
kein gemeinsames Ticket. Deploy mit --feld pnl_hl_brk, alle 5 Schritte gruen.
⚠ Noch nicht beobachtet: ein Neustart MIT offener BRK-Position - der Fall, den
der Fix adressiert.

v=201.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 13:07:16 +02:00
Axel HocksandClaude Opus 5 3e275e7515 Slot-Close-Knoepfe groesser und in CLOSE-Farbe; grosser CLOSE-Knopf entfernt
User-Wunsch, drei Teile.

(1) GROESSER: font-size 0.72 -> 1rem, Polster 0.17/0.33 -> 0.39/0.61rem, fett.
(2) FARBE wie der bisherige CLOSE-Knopf: background #2d2000, color var(--accent),
    Rahmen #4a3600 - derselbe Bernstein-Ton, damit "schliessen" ueberall gleich
    aussieht.
(3) Grosser CLOSE-Knopf aus der Aktionsleiste ENTFERNT.

⚠⚠ DER HAKEN AN (3), geprueft bevor entfernt: der Knopf hatte ZWEI Aufgaben im
Render, nicht nur das Klicken - `disabled`, wenn keine Position offen ist, und
BLINKEN beim Close-Alarm (`closeBtn.classList.toggle("blink", closeAlert)`).
Haette ich ihn nur aus der HTML geloescht, waere der Alarm still geworden: nur
noch Ton, keine Sichtbarkeit. Beides ist mitgezogen:
  - `close-main` ist disabled, wenn Slot 1 leer ist; `close-brk`, wenn BRK leer
    ist (vorher gab es diese Unterscheidung gar nicht)
  - `.px-close.blink` nutzt dieselbe `blkClose`-Keyframe wie vorher, und weil
    die Farben identisch sind, sieht das Blinken exakt aus wie zuvor
⚠ Es blinkt NUR der Slot-1-Knopf: dort entstehen `sr_close_hint` und der
Flip-Alarm. Ein blinkender BRK-Knopf ohne Anlass waere ein Fehlsignal.

FUNKTIONAL GEPRUEFT (drei Zustaende gegen ein Minimal-DOM):
  hasPos=1 hasBrk=0 alarm=0 -> main aktiv,  brk gesperrt, kein Blinken
  hasPos=0 hasBrk=1 alarm=1 -> main gesperrt, brk aktiv,  Blinken
  hasPos=1 hasBrk=1 alarm=1 -> beide aktiv,               Blinken
0 verbliebene `data-side="close"`-Referenzen in JS und HTML.

⚠ `.btn.close` und `.btn.close.blink` bleiben in der CSS stehen - ungenutzt,
aber harmlos, und sie machen ein Zurueckholen des grossen Knopfs zu einer
Ein-Zeilen-Sache.

v=200 (HTML, JS, style.css und der Cache-Waechter `data-html-v` alle
gleichgezogen und am ausgelieferten Stand verifiziert).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:04:07 +02:00
Axel HocksandClaude Opus 5 54bcc9f81d Cache-Waechter: die Seite meldet selbst, wenn HTML und JS nicht zusammenpassen
User: "die buttons werden nicht angezeigt" (Close-Knoepfe an den G/V-Anzeigen).

DIAGNOSE: serverseitig war alles korrekt - HTML, CSS und JS werden mit v=199
ausgeliefert, der Knopf steht im gelieferten Markup, die CSS-Regel ist da, und
KEINE andere Regel versteckt ihn (globale button-Regeln gibt es nicht, .px setzt
nur Schrift). Der Server sendet no-store, und last-modified stimmt mit der
Platte ueberein. Es bleibt der Browser-Cache.

⚠⚠ URSACHE IST STRUKTURELL, nicht einmalig: `index.html` wird vom `?v=`-Bump
NICHT gebustet - nur app.js und style.css. Trifft neues JS auf eine alte,
gecachte HTML, fehlen die neuen Elemente. Das Auffang-`$` verhindert den
Absturz, aber die Anzeige ist STILL unvollstaendig. Real jetzt zum zweiten Mal:
19.08. (M5-/RSI-Zeile) und 20.08. (diese Knoepfe) - beide Male sah der Server
korrekt aus und der Browser zeigte Altes, und beide Male habe ich es von Hand
diagnostizieren muessen.

GEBAUT: `<body data-html-v="199">` plus eine Konstante `_JS_V` in app.js. Weichen
sie ab, blendet die Seite unten ein rotes Band ein ("Alte Seite im Cache, HTML
v198, JS v199 - hier tippen zum Neuladen"); ein Tipp darauf laedt mit frischem
Query-String neu.
⚠ Bewusst SICHTBAR statt nur Konsole - die sieht am Handy niemand.
⚠ Die Version wird beim `?v=`-Bump aus der HTML gelesen, muss also nicht getrennt
gepflegt werden.

BEIDE RICHTUNGEN VERIFIZIERT: HTML v198 gegen JS v199 -> Banner erscheint;
gleiche Version -> kein Banner.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 12:01:30 +02:00
Axel HocksandClaude Opus 5 d881636e1b Close-Knopf je Slot, direkt vor der jeweiligen G/V-Anzeige
User-Wunsch. Zwei Slots heissen zwei Close-Moeglichkeiten - bisher gab es nur
den grossen CLOSE-Knopf, und der schliesst seit heute BEIDE. Neu je ein kleines
✕ vor "G/V" (Slot 1) und vor "G/V · BRK", rechtsbuendig gespiegelt.

BACKEND: `engine.close(slot=None)` - None/"" = beide (Verhalten des grossen
Knopfs, unveraendert), "main" = nur Slot 1, "brk" = nur der Breakout-Autotrader.
`POST /api/order {"side":"close","slot":"brk"}` reicht ihn durch; ohne `slot`
ist das Verhalten bitgleich zu vorher.

⚠ Sicherheitsabfrage NUR im Minus - dieselbe Regel wie beim grossen Knopf: im
Plus direkt schliessen, im Minus nachfragen. Hartes Blockieren ist im Projekt
verworfen, aber ein versehentlicher Klick soll kein Geld kosten.

⚠⚠ EIGENER FEHLER auf dem Weg, gefunden bevor er live ging: mein erster Entwurf
las den P&L aus `_letzterSnap` - eine Variable, die es NICHT gab. Das ist exakt
der ReferenceError, der am 19.08. den halben Render abgeschossen hat, nur
diesmal im Klick-Pfad (er waere erst beim Druecken geknallt, also genau dann,
wenn man schliessen will). Behoben durch `letzterSnap`, das `_applySnapshot`
jetzt fuehrt - die Variable fehlte im Projekt tatsaechlich, Klick-Handler hatten
bisher keinen Zugriff auf den aktuellen Zustand.

Verifiziert: 2 Knoepfe im ausgelieferten HTML, span/div/button ausgeglichen,
keine doppelten IDs, node --check, Render-Probe, 91 Tests und die volle Pipeline
gruen. Deploy verifiziert (v=199).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 11:58:04 +02:00
Axel HocksandClaude Opus 5 14b3fd4f64 Vierter Slot-Durchgang: Chart-Marker deckte den BRK-Slot nicht ab
User-Auftrag (vierte Runde). Diesmal die Bereiche AUSSERHALB von engine.py
geprueft - core/trader.py, server.py, der MQL5-Export und die
Zustandspersistenz.

⑦ BEHOBEN - Trade-Marker im MT5-Chart (`TR;`-Zeilen) lasen nur
   `self.trader.snapshot()`. Eine offene BRK-Position blieb im Chart also
   UNMARKIERT: die hellgruene Umrandung der Einstiegskerze fehlte. Kosmetisch,
   aber dieselbe Klasse wie Deployment-Drift Fall 8 - nicht die Strategie
   driftet, sondern ihre Beobachtbarkeit. Wer den Chart ansieht, soll sehen,
   wo der Bot eingestiegen ist. Jetzt ueber beide Slots.

DREI ENTLASTUNGEN in diesem Durchgang (geprueft, NICHT vermutet):
  - core/trader.py hat als einzige Klassen-Variable `_STEUER_TTL_S` (eine
    Konstante); der Steuer-Cache liegt als `self._steuer_cache` INSTANZWEISE
    vor. Modul-Globale sind nur die zwei Logger. Die beiden TradeManager teilen
    also KEINEN veraenderlichen Zustand - zusammen mit dem Trailing-Befund aus
    Durchgang 3 ist damit beides sauber.
  - server.py routet ueber `eng.close` (deckt seit heute beide Slots),
    `eng.toggle_trail` (ebenfalls) und `eng.set_sltp`.
  - `emergency_state.json` ist per-Ticket und betrifft nur Slot 1 - die drei
    Notfall-Modi stehen ohnehin auf 0, und der Reichweiten-Waechter meldet es,
    falls einer eingeschaltet wird, waehrend BRK eine Position haelt.

⚠ WEITER OFFEN, unveraendert und bewusst: `set_sltp()` (nur Slot 1, braucht eine
UI-Entscheidung) und `_check_auto_m15`, das `_slot()` umgeht. Neu dazu:
`_check_close_alert` (Flip-Alarm) liest ebenfalls nur Slot 1 - das ist ein
Hinweis, keine Schutzhandlung, und der Flip-Close ist aus.

91 Tests gruen, Pipeline inkl. Stufe E gruen, Deploy verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:15:48 +02:00
Axel HocksandClaude Opus 5 fbc1e96b07 Trade-Leiste: alle Felder normal statt fett
User-Wunsch. `.tb-field input, .tb-field .tb-val` stand auf font-weight:700 -
das trifft ALLE Felder der Leiste auf einmal (Eingaben SL/TP/Gewinn-Close und
die Anzeige-Boxen Richtung/Lots/Einsatz/TP1/TP3). Auf 400 gesetzt, damit die
Leiste einheitlich bleibt.

⚠ Gegengeprueft, dass in der Leiste nichts anderes mehr fett ist: die acht dort
verwendeten Klassen (tb-row, tb-title, tb-dir, tb-field, tb-val, tb-runtime,
stop, gain) haben keine weitere font-weight:700-Regel, und es gibt keine <b>-
oder <strong>-Tags darin.

⚠ Der erste Versuch scheiterte am Anker: ich hatte die Zeile aus einer
sed-Ausgabe kopiert, die zwei Leerzeichen voranstellt. Nichts geschrieben
(Assertion vor dem Write) - danach ueber die Zeilennummer mit Inhaltspruefung.

Backup web/style.css.bak-2026-08-20-tbfett. Reine CSS-Aenderung (v=198), kein
Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:12:19 +02:00
Axel HocksandClaude Opus 5 d59d0eeaee TP-Anzeige entwirrt: doppelten Wert entfernt, Init-Formel ehrlich beschriftet
User-Frage "unterscheidet sich TP von TP1, TP2 oder TP3?" - sie deckte zwei
Fehler auf, beide von mir aus der vorigen Aenderung.

⚠ ZUERST DIE SACHE SELBST: der TP WIRD nachgezogen, aber nach DREI Formeln:
    Init   Entry ± 3,5xATR      fest, gibt dem Trade Luft
    Trail  Bestkurs ∓ 0,5xATR   zieht mit dem Hoch mit
    Lock   Bestkurs ∓ 0,3xATR   sehr eng am Hoch
    immer  mindestens Entry ± 0,5xATR (schliesst nie im Verlust)
Er springt beim Phasenwechsel also von WEIT VOR dem Kurs auf KNAPP HINTER das
Hoch - ab Phase Trail ist er faktisch ein zweiter, engerer Ausstieg ueber dem
Stop. 63 TP-Setzungen im Log bestaetigen das.

① BEHOBEN - "TP2 · Trailing" in der Trade-Leiste zeigte DENSELBEN Wert wie das
   Feld "TP" daneben. Eine Zahl doppelt. Entfernt; uebrig bleiben TP1 (Level)
   und TP3 (Kegel) als das, was sie sind: Orientierungsmarken, die der
   Broker-TP NICHT kennt. Das Feld "TP" bleibt editierbar.

② BEHOBEN - im M15-Setup-Block stand "TP2: ... (3,5xATR - das Trailing fuehrt
   ihn nach)". Das war irrefuehrend: 3,5xATR ist NUR die Init-Formel, und ab
   Phase Trail laeuft der TP nach einer anderen Regel. Jetzt: "Init-Ziel
   3,5xATR - ab Phase Trail zieht der TP an den Bestkurs heran, ∓0,5xATR".

Verifiziert: 0 verbliebene tb-tp2-Referenzen in JS und HTML, span/div
ausgeglichen, keine doppelten IDs, node --check und Render-Probe gruen.
Reine Frontend-Aenderung (v=197), kein Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:07:22 +02:00
Axel HocksandClaude Opus 5 6f1348adf3 G/V und G/V BRK in EINER Box: links Slot 1, rechts BRK
User-Wunsch. Statt zwei nebeneinanderliegender Header-Boxen jetzt eine geteilte:
linksbuendig "G/V" (Slot 1 - manuelle und M15-Trades), rechtsbuendig
"G/V · BRK" (Breakout-Autotrader, eigener Slot seit 19.08.).

⚠ Die WERTE bleiben getrennt, nur die Box ist eine. Die Slots gehoeren
verschiedenen Populationen (Mensch +1,56 gegen autonom -4,71 EUR/Lot); sie zu
ADDIEREN wuerde genau die Trennung verwischen, fuer die der zweite Slot gebaut
wurde. Die Summe steht weiterhin im TAG P/L (day_pl.open summiert beide seit
dem 19.08.).

Umgesetzt ueber flex mit `justify-content: space-between`; der Tooltip sitzt
jetzt an der Box statt zweimal an den Labels, damit die Erklaerung nicht
doppelt steht.

Verifiziert: div 89/89 ausgeglichen, keine doppelten IDs, beide Spans genau
einmal vorhanden, Render-Probe und Pipeline gruen. Reine Frontend-Aenderung
(v=196), kein Neustart - die Render-Logik (hdr-pnl / hdr-pnl-brk) ist
unveraendert, nur das Markup drumherum.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:01:57 +02:00
Axel HocksandClaude Opus 5 5925d9a527 Trade-Leiste: TP1/TP2/TP3 + Setup-Block "Entry Zone / SL / TP1-3" in der M15-Karte
User-Wunsch, mit einer Vorlage im Format "USOIL BUY SETUP: Entry Zone / Stop
Loss / Take Profit 1-3".

(1) TRADE-LEISTE — drei Anzeige-Boxen fuer die LAUFENDE Position:
    TP1 · Level     naechstes STEHENDES M30-Level in Trade-Richtung + P(haelt)
    TP2 · Trailing  der Broker-TP, den `core/trailing.py` dynamisch fuehrt
    TP3 · Kegel     Obergrenze des 80-%-Bandes auf 120 min (core/cone.py)
    Live gegengerechnet: 85.745 (67 % haelt) / 86.634 / 86.153 (trifft 75 %).

(2) M15-KARTE — Setup-Block im Format der Vorlage, direkt unter dem Banner:
    Richtung · Entry Zone (Level ± 0,15xATR) · Stop Loss (2,0xATR_M15) ·
    TP1 (Gegenlevel) · TP2 (3,5xATR) · TP3 (Kegel 120').
    Blendet sich aus, wenn kein Veto, keine Zone oder kein ATR vorliegt -
    aktuell ist genau das der Fall (M30 flach -> kein Veto -> keine erlaubte
    Richtung), und das ist korrektes Verhalten, kein Fehler.

⚠⚠ DREI LEITPLANKEN, damit daraus keine Prognose wird:
  - Die RICHTUNG kommt ausschliesslich aus dem VETO (erlaubte Richtung). Die
    Karte gibt weiterhin KEINE Richtungsprognose ab - die ist ueber 1.071
    Live-Episoden als Muenzwurf gemessen (48-51 %). Ohne Veto: kein Block.
  - Die drei TP sind ANZEIGE, nichts davon geht an den Broker. Ein FESTER TP am
    Gegenlevel ist der staerkste Gewinner-Kappen-Beleg des Projekts: er drehte
    den Squeeze von +0,102/+0,108 auf -0,066/-0,004 (backtest_trailing_sr.py).
    Deshalb steht an TP2 ausdruecklich, dass das Trailing ihn nachfuehrt.
  - NICHTS wird neu gerechnet - Zonen, ATR und Kegel stehen im Snapshot. Ein
    zweiter Rechenweg waere die Divergenz-Falle (dreimal zugeschlagen).
  - Neutral gerahmt, nicht gruen/rot: der Block sagt WO, nicht OB.

Die 0,15xATR der Entry Zone sind die im Projekt gemessene "Beruehrung"
(dieselbe Schwelle wie `at_level` im S/R-Hinweis), nicht geraten.

Reine Frontend-Aenderung (v=195), kein Neustart. node --check, Render-Probe und
die volle Pipeline gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 09:00:01 +02:00
Axel HocksandClaude Opus 5 5e476025d7 Dritter Slot-Durchgang: TRAIL-Knopf und Wiedereinstiegs-Sperre waren blind
User-Auftrag (dritte Runde). Diesmal die Bereiche ausserhalb der
`self.trader.`-Zugriffe geprueft. ZWEI neue Funde, beide behoben:

⑤ toggle_trail() schaltete NUR `self.trail`. Hielt allein der BRK-Slot eine
   Position, liess sich dessen Trailing per Dashboard weder ein- noch
   ausschalten. ⚠ Das ist keine Kosmetik: ohne `trail_brk` laeuft ein BRK-Trade
   in der gemessen DURCHGEFALLENEN SL-only-Variante (backtest_brk_slonly.py,
   alle zehn KI enthalten die Null, Trefferquote faellt 40 -> 21 %).
   Neu: haelt NUR BRK etwas, wird dessen Trailing geschaltet; sonst (auch bei
   zwei offenen Positionen) das von Slot 1 - die Position, die der Nutzer selbst
   geoeffnet hat.

⑥ Die Wiedereinstiegs-Sperre sah den BRK-Slot NICHT. `_check_auto_close` setzt
   `_pos_close_ts`/`_pos_close_dir` aus `self.trader.snapshot()`; schloss eine
   BRK-Position, blieb die Sperre unarmiert und der Squeeze durfte sofort in
   dieselbe Richtung neu eroeffnen. Genau die Open->Instant-Close-Kaskade, gegen
   die _SQUEEZE_REENTRY_COOLDOWN_S am 27.07. gebaut wurde.
   Neu `_check_brk_close_cooldown` im _pos_loop. ⚠ Bewusst DIESELBEN Felder wie
   Slot 1: die Sperre ist eine Aussage ueber den MARKT ("in diese Richtung
   gerade nicht"), nicht ueber einen Slot.

GEPRUEFT UND SAUBER in diesem Durchgang:
  - core/trailing.py hat KEINE Klassen-Variablen und keine veraenderlichen
    Modul-Globalen -> die zwei TrailingManager-Instanzen sind vollstaendig
    unabhaengig. Das war die groesste offene Sorge.
  - _check_close_notify arbeitet ueber history.trade_by_ticket, also DB-basiert
    und slot-unabhaengig.

⚠ WEITER OFFEN, bewusst nicht angefasst: `set_sltp()` wirkt nur auf Slot 1 (die
SL/TP-Felder koennen eine BRK-Position nicht anpassen) - das ist eine
UI-Entscheidung, welches Feld zu welchem Slot gehoert, und braucht eine Vorgabe
statt eines stillen Fixes. Ebenso `_check_auto_m15`, das `self.trader.open_long`
VOR dem `_open`-Aufruf bindet und damit `_slot()` umgeht (funktioniert derzeit
nur, weil beide dasselbe liefern).

91 Tests gruen, Pipeline inkl. der neuen Stufe E gruen, Deploy verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:54:20 +02:00
Axel HocksandClaude Opus 5 2b498fc20e Pipeline Stufe E: Slot-Trennung und Attribut-Reihenfolge (tools/check_slots.py)
User: "Uebernehme die Logikpruefung auf allen Slots in die Deployment pipeline" -
nach dem Ausfall, bei dem der Serverstart komplett abbrach und zwei Minuten lang
kein Close moeglich war.

ZWEI FEHLERKLASSEN, beide binnen zwei Tagen real aufgetreten, beide von KEINER
bestehenden Stufe gefangen (py_compile, ruff F821, ty, pytest: alle gruen):

(A) ATTRIBUT VOR SEINER ZUWEISUNG. `self.trader_brk.history = self.history`
    stand in `__init__` VOR `self.trader_brk = TradeManager(...)`.
    AttributeError im Konstruktor -> Serverstart brach ab -> "Netzwerkfehler" am
    Close-Knopf. Syntaktisch korrekt, und kein Test instanziiert die Engine (sie
    braucht MT5). Gefunden hat es erst deploy.py Schritt 2 - also NACH dem Kill
    des laufenden Servers. Derselbe Fehler am Vortag mit `_margin_brk` vor
    `_load_runtime_state()`, dort sogar still.
    Die Pruefung sammelt je `self.X` die ZEILE der ersten Zuweisung und meldet
    jede Benutzung davor.

(B) SLOT-VERWECHSLUNG. BRK-Pfade (_check_auto_squeeze, _manage_squeeze_pending,
    _check_pending_fill) duerfen den SLOT-ZUSTAND von `self.trader` nicht
    anfassen (close/snapshot/open_*/set_open_context/refresh). ⚠ Bewusst eine
    WEISSE Liste der Pfade - eine schwarze wuerde jede neue Funktion still
    durchlassen. `pending_orders`/`cancel_pending`/`place_stop` sind ausdruecklich
    ERLAUBT: magic-basierte Broker-Abfragen ohne Slot-Zustand (geprueft).
    Dazu die Invariante, dass `TradingEngine.close` beide Slots erwaehnen muss -
    sonst waere eine BRK-Position per Dashboard nicht schliessbar.

DREI RICHTUNGEN VERIFIZIERT: sauber -> gruen; Reihenfolge-Fehler zurueckgebaut ->
"self.trader_brk benutzt, aber erst in Zeile 270 zugewiesen"; Slot-Verwechslung
zurueckgebaut -> "self.trader.close im BRK-Pfad". Danach wieder gruen.

Statisch (AST), kein MT5, Millisekunden. Werkzeugfehler gilt NICHT als sauber.
Laeuft ueber check_nfalle.py im pre-commit-Hook mit.

⚠ Was diese Stufe NICHT kann: ein Startfehler AUSSERHALB von __init__. Dafuer
bliebe ein echter Rauchtest mit gestubbtem MT5 - der ist nicht gebaut.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:47:28 +02:00
Axel HocksandClaude Opus 5 a652223a05 Slot-Pruefung: close() traf nur Slot 1, squeeze_reverse den falschen
User: "ueberpruefe die Trade Logiken genau auf weitere Fehler oder Widersprueche,
besonders bezogen auf die 2 Slots". Systematisch alle `self.trader.`-Zugriffe in
engine.py durchgegangen (24 Stellen, nach Funktion gruppiert). VIER Widersprueche,
alle aus dem Umbau vom 19.08.:

① BEHOBEN - `engine.close()` schloss NUR Slot 1. Hielt der BRK-Slot eine Position
   und Slot 1 war leer, tat der CLOSE-Knopf im Dashboard NICHTS. Das ist die
   gefaehrlichste Variante der Luecke: nicht eine Zahl stimmt nicht, sondern eine
   SCHUTZHANDLUNG greift ins Leere. Jetzt ueber beide Slots, Slot 1 zuerst
   (wer CLOSE drueckt, meint meist die selbst geoeffnete Position), Fehler
   gesammelt gemeldet.

③ BEHOBEN - `squeeze_reverse` rief `self.trader.close()`, traf also die MANUELLE
   Position statt der BRK-Position, die der Reverse eigentlich drehen soll.
   Dormant (auto_squeeze_reverse=false), aber falsch verdrahtet.

② GEMELDET, NICHT geaendert - `set_sltp()` wirkt nur auf Slot 1. Die SL/TP-Felder
   der Trade-Leiste koennen eine BRK-Position nicht anpassen. Das ist eine
   UI-Frage (welches Feld gehoert zu welchem Slot?) und braucht eine Entscheidung,
   keinen stillen Fix.

④ GEMELDET - `_check_auto_m15` bindet `self.trader.open_long` VOR dem Aufruf von
   `_open`, umgeht also `_slot(source)`. Funktioniert derzeit nur, weil
   `_slot("auto_m15")` ohnehin `self.trader` liefert. Fragil: bekaeme M15 je
   einen eigenen Slot, waere es still falsch.

GEPRUEFT UND KORREKT: `_manage_squeeze_pending` (pending_orders/cancel_pending/
place_stop sind magic-basierte BROKER-Abfragen, kein Slot-Zustand),
`_broker_offset_s` (Zeitzone), `snapshot()` (position / position_brk getrennt),
Circuit-Breaker (summiert und schliesst beide).

⚠ Beim Bau eine Einrueckung zerschossen - Stufe A der Pipeline hat es sofort
gefangen (IndentationError + ty invalid-syntax + pytest). Genau dafuer ist sie da.

91 Tests gruen, Deploy verifiziert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:37:11 +02:00
Axel HocksandClaude Opus 5 c33227664c Trade-Leiste: Auto-Close-Feld entfernt (war doppelt)
User-Wunsch. Der Schalter existierte zweimal: in der Trade-Leiste und seit dem
19.08. als Knopf "S/R" in der Aktionsleiste. Die Aktionsleisten-Variante ist die
brauchbarere - die Trade-Leiste erscheint NUR bei offener Position, man konnte
den Auto-Close dort also gar nicht VOR einem Trade setzen. Genau deshalb war der
zweite Knopf am 19.08. dazugekommen.

Entfernt: das `<span class="tb-field">` mit `#srclose-btn`, der Render-Block, der
seinen Zustand schrieb, und der onclick-Handler. `srAuto` bleibt - es speist
weiter den Knopf `btn-sr` und die Hinweistexte.

⚠ Die beiden JS-Zugriffe haetten dank Auffang-`$` keinen Absturz erzeugt, aber
sie waeren toter Code gewesen, der je ID eine Konsolen-Warnung ausloest.
Deshalb mitentfernt statt liegengelassen: 0 Treffer in app.js UND index.html.

Backend, Endpoint /api/srclose und der Zustand `auto_sr_close` unveraendert.

Reine Frontend-Aenderung (v=193), kein Neustart. node --check und die
Render-Probe (Stufe B2) gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:33:49 +02:00
Axel HocksandClaude Opus 5 c081bdc734 SL/TP nicht mehr am S/R verankert + Squeeze-Market-Fallback auf den BRK-Slot
User: "SL/TP sollte nicht am S/R verankert werden sondern immer dynamisch
berechnet werden" - nach dem Fund, dass Trades wiederholt am Level schlossen.

(1) PIVOT-ANKER DES INITIAL-SL ENTFERNT (`_SL_PIVOT_ANKER = False`).
`_calc_sl_tp` legte den SL an den naechsten M15-Pivot (LONG: pivot_low − Puffer,
SHORT: pivot_high + Puffer) und klemmte ihn erst DANACH auf 1,8–2,2×ATR. Der
Stop lag damit fuer einen LONG direkt unter der UNTERSTUETZUNG. Ueber 69
geloggte Orders war der Pivot in 4 % massgeblich (59 % gekappt, 36 % geweitet) -
und in genau diesen Faellen stand der Stop auf dem Level, an dem der Markt
ohnehin am haeufigsten durchwickt.
⚠ Der TP erbte das INDIREKT: er ist `2,0 × SL-Distanz`, skalierte also mit dem
Pivot-Abstand. Beide sind jetzt rein ATR-dynamisch (Mitte des Bandes = 2,0×ATR).

VORHER GEMESSEN (`backtest_sl_pivot.py`, 60k M5, 2 Halbjahre, gleiche
Einstiege, NUR die SL-Methode variiert, kanonischer Exit, Echtkosten):
    PIVOT  H1 -0,054 / H2 -0,040   PF 0,93 / 0,95
    FIX    H1 -0,040 / H2 +0,004   PF 0,95 / 1,01
FIX ist in BEIDEN Haelften besser (+0,014 / +0,043 R), der Worst-Case wird nicht
groesser - die vorab fixierte Regel ist erfuellt.
⚠ EHRLICH: beide KI enthalten die Null, es ist KEIN belegter Ertragsgewinn. Der
Punkt ist, dass die Verankerung nichts nuetzt UND den Stop auf das Level legt.
Das bestaetigt `backtest_sl_method.py` ("gedeckelt sind alle Methoden
gleichwertig") auf dem heutigen Exit - dort war es nur nie als NACHTEIL sichtbar.
Zurueck: `_SL_PIVOT_ANKER = True`.

(2) LUECKE AUS DEM ZWEI-SLOT-UMBAU, vom Deploy-Schritt 5 aufgedeckt:
"Auto-Squeeze-Entry fehlgeschlagen: Position bereits offen!". `engine.open_long`
routete IMMER auf `self.trader` - der Market-Fallback des Squeeze lief also
weiter ueber Slot 1 und scheiterte, sobald ein manueller Trade lief. FLAT-Check
und Pending-Manager waren gestern umgehaengt, der BESTELLWEG nicht.
Neu `_slot(source)`: auto_squeeze -> trader_brk, alles andere -> trader. Auch
der Bot-Marker (`_bot_open_ticket`) holt das Ticket jetzt vom richtigen Slot.
⚠ Genau die Fehlerklasse von Deployment-Drift Fall 8 - ein Umbau, der den
Bestellweg aendert, muss ALLE Bestellwege mitnehmen.

91 Tests gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:32:21 +02:00
Axel HocksandClaude Opus 5 e01ecde3a3 Order-Knopf warnt sichtbar, wenn der Raum zum Ziel-Level fehlt
User: "und wieder am Widerstand geschlossen. Das ist kein Zufall mehr."

⚠⚠ ZUERST DER AUSSCHLUSS - im Exit gibt es KEINEN S/R-Anker:
  - S/R-Auto-Close ist seit 19.08. aus
  - `trail.set_sr(...)` uebergibt die Level zwar, aber `_sr_data` wird in
    core/trailing.py NIRGENDS benutzt (toter Parameter)
  - Trailing-Stop = Bestkurs ∓ 1,0xATR, TP = Entry ± 3,5xATR - beides reines ATR
Kein Codepfad kann an einem Level schliessen.

DIE URSACHE LIEGT AM EINSTIEG, und sie ist in der eigenen Telemetrie sichtbar
(ctx_dist_res_atr / ctx_dist_sup_atr, Abstand zum ZIEL-Level beim Eroeffnen):
   19.08 20:00 BUY  0,25xATR   -5,44
   19.08 20:05 BUY  0,29xATR   -4,20
   19.08 20:11 BUY  0,46xATR  -23,29
   19.08 20:59 SELL 0,52xATR   -4,47
   19.08 21:18 BUY -0,03xATR   -0,67   (Widerstand bereits ueberschritten)
FUENF von zwoelf Trades unter dem Gate 0,6, zusammen -38,07 EUR.
Der Kurs erreicht das Level nach wenigen Cent, dreht, und der Trail (1xATR
dahinter) nimmt mit. Der Exit SIEHT nach "am Widerstand" aus, weil der EINSTIEG
dort lag. Genau das misst entry_room_atr: OeR -0,119/-0,067 bei PF 0,42/0,66 -
79 % Trefferquote und trotzdem Verlust, weil der Gewinn am Level gedeckelt ist
und der Verlust bis zum Stop laeuft.

Warum es niemand sah: `entry_room` blockt nur die EMPFEHLUNG, manuelle Orders
laufen ungehindert (so gewollt, Uebersteuerungen liefen 68 % WR). Seit dem
Entfernen des Entry-Dialogs (11.08.) fehlte die Zahl im Moment des Klicks; sie
stand nur in Gate ③b - und das ist seit gestern im zugeklappten Akkordeon.

GEBAUT: der Order-Knopf selbst wird markiert (Umriss in Akzentfarbe, gedaempfte
Flaeche, Raum-Zahl fett), sobald `frei === false`. Live gegengeprueft: bei Raum
0,04 / 0,28 xATR sind beide Knoepfe gewarnt.
⚠ KEIN Block, KEINE Abfrage - sichtbar machen, nicht bevormunden.
⚠ Die Zahl wird NICHT neu gerechnet; `rm` liegt bereits vor. Ein zweiter
Rechenweg waere die Divergenz-Falle, die im Projekt dreimal zugeschlagen hat.
⚠ Der Knopf hat keine id, sondern data-side - deshalb ueber `closest()` statt
ueber eine ID (erster Versuch griff ins Leere).

Reine Frontend-Aenderung (v=192), kein Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:25:33 +02:00
Axel HocksandClaude Opus 5 834bd0bba3 Header: eigene G/V-Box fuer den BRK-Slot, rechts neben dem ersten
User-Wunsch. Seit dem Zwei-Slot-Umbau vom 19.08. kann der Breakout-Autotrader
parallel zu manuellen und M15-Trades eine eigene Position halten - im Header war
davon nichts zu sehen. Neue Box "G/V · BRK" (#hdr-pnl-brk) direkt neben "G/V",
mit Ticket, Lots, Einstieg und Trailing-Zustand im Tooltip. Zeigt "—", wenn BRK
nichts haelt.

⚠ BEWUSST ZWEI BOXEN statt einer Summe: die Slots gehoeren verschiedenen
Populationen (Mensch +1,56 gegen autonom -4,71 EUR/Lot), und sie in EINEM Feld
zusammenzurechnen wuerde genau die Trennung verwischen, fuer die der zweite Slot
ueberhaupt gebaut wurde.

Die SUMME steht dort, wo der User sie angefragt hat: im TAG P/L. Geprueft statt
angenommen - `day_pl["open"]` summiert seit dem 19.08. bereits beide Slots
(engine.py:4537), es war also nichts nachzuruesten. Live gegengerechnet:
Slot 1 +4,18 / BRK leer / day_pl.open 4,18.

Die WHT-Behandlung ist identisch zur ersten Box (Abzug nur auf Gewinne) - eine
zweite Rechenart im selben Header waere eine Divergenz, die niemand erwartet.

Reine Frontend-Aenderung (v=191), kein Neustart. div 87/87 ausgeglichen, keine
doppelten IDs, node --check und die Render-Probe gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:14:26 +02:00
Axel HocksandClaude Opus 5 d87bda1461 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>
2026-08-20 08:12:15 +02:00
Axel HocksandClaude Opus 5 4ebc55c49b Trailing: ATR fest auf M5 (Drift behoben) + trail_start 0,3 -> 1,3
User: "ueberpruefe die trailing logik und passe ggf an", nach drei Trades in
Folge, die per nachgezogenem Stop schlossen. Beide Aenderungen auf Zustimmung.

(1) DEPLOYMENT-DRIFT: der Trail-ATR kam aus der WELLEN-Zeitebene, und die
    wechselt. Gemessen an 90 echten Aktivierungen im Log:
        M5   Ø ATR 0,1877  n=51   -> 1,00x wie validiert
        M15  Ø ATR 0,2586  n= 9   -> 1,38x
        M30  Ø ATR 0,4751  n=30   -> 2,53x
    In 43 % der Faelle lief der Trail also mit einem Abstand, der NIE gemessen
    wurde. `backtest_trailmult.py` misst mult=1,0 auf M5-Bars mit M5-ATR; auf
    M30 entspricht das effektiv ~2,5 in M5-Einheiten, und 2,5 ist dort KLAR
    schlechter gemessen (H1 ΣR -1174 gegen -73 bei 1,0).
    ⚠⚠ Am 31.07. wurde `_MULT_BY_TF` GENAU gegen diese Fehlerklasse auf
    durchgehend 1,0 geglaettet. Der Multiplikator war aber nie die Ursache - es
    ist der ATR. Die Variabilitaet kam durch die Hintertuer zurueck.
    `_atr_tf_override` bleibt unberuehrt: den setzt engine bewusst, das ist eine
    explizite Vorgabe und kein Automatismus. Zurueck: vier auskommentierte
    Zeilen in `_pick_tf` wieder aktivieren.

(2) trail_start 0,3 -> 1,3. `backtest_trail_start.py` (14.08.) zaehlt den Anteil
    "war im Plus, schloss im Minus": 0,3 -> 47,6 % / 38,2 %, bei 1,3 -> 0,0 % /
    0,5 %. ⚠ Der ERTRAG unterscheidet sich gepaart NICHT messbar - alle zwoelf
    KI enthalten die Null. Es ist also eine KOMFORT-Entscheidung, und sie ist
    gemessen gratis. Mechanik: der Trail sitzt mult×ATR (=1,0) hinter dem
    Bestkurs und erreicht den Einstand erst bei 1,0×ATR Gewinn; mit Start bei
    0,3 lag der Stop im Band dazwischen zwangslaeufig auf der VERLUSTSEITE.

⚠⚠ FOLGE FUER DIE BACKTESTS, ausdruecklich benannt: `LIVE` ist die GETEILTE
Quelle. Alle Skripte, die sie nutzen, rechnen ab jetzt mit trail_start 1,3 -
ihre dokumentierten Zahlen wurden mit 0,3 erzeugt und reproduzieren daher NICHT
mehr. Wer eine alte Zahl nachrechnen will, muss `LIVE.with_(trail_start=0.3)`
pinnen. Das ist der Preis der geteilten Quelle und zugleich ihr Zweck: Live und
Messung bewegen sich gemeinsam. Der veraltete Kommentar "start 0,3" in
exit_model.py wurde mitgezogen, damit die Begruendung nicht gegen die
Einstellung steht.

⚠ Am Verlust-Trade von heute frueh (-22,36) haette KEINE der beiden etwas
geaendert: er war nie im Plus und traf den regulaeren Initial-SL. Dort ist die
Schraube die Positionsgroesse, nicht der Exit.

91 Tests gruen, Deploy ueber tools/deploy.py --feld position_brk.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 08:01:20 +02:00
Axel HocksandClaude Opus 5 d3d613068c M15-Karte: Pruefkette als Akkordeon in drei Abschnitten
User-Wunsch. Die Karte war auf zehn Zeilen gewachsen und dominierte das
Dashboard; jetzt sind sie in drei aufklappbare Gruppen sortiert:

  ① - ④  Pruefkette                        (offen)   Bias · Kosten · Zone · Reichweite
  ⑤      Kontext - Motor · M5 · RSI        (zu)      Motor/Raum · M5-Zustand · RSI
  ⑥ - ⑦  Selbstmessung · Ausfuehrung · Veto (zu)      Track · Exec · Veto

Das Status-Banner bleibt IMMER sichtbar - es ist die eine Zeile, die eine
Handlungsaussage traegt, und es bestaetigt ausdruecklich auch das Nicht-Handeln.

⚠⚠ NATIVES <details>/<summary>, kein JS fuer das Klappen. Entscheidend ist, dass
die Elemente IM DOM bleiben: der Render schreibt weiter in alle zehn IDs, auch
wenn ein Abschnitt zugeklappt ist. Ein Container, der die Elemente ENTFERNT,
haette den Render abbrechen lassen - genau der Ausfall von gestern Abend, als
ein ReferenceError in renderM15 das halbe Dashboard auf "—" stehen liess.

JS macht nur EINES: den Auf-/Zu-Zustand in localStorage merken. Ohne das waere
jeder Reload ein Rueckschritt - und die Seite wird bei jedem ?v=-Bump neu
geladen. Faellt localStorage aus (privater Modus), greift der Default.

Verifiziert: 10 m15-Items unveraendert vorhanden, keine doppelten IDs,
div 86/86 und details 3/3 ausgeglichen, node --check gruen, Render-Probe
(Stufe B2) gruen. Reine Frontend-Aenderung (v=190), kein Neustart.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 00:11:17 +02:00
Axel HocksandClaude Opus 5 5684589878 FIX: SL/TP-Feld rundete auf 2 Nachkommastellen - Stop verschob sich beim Speichern
User: "SL war auf 84,86 laut Dashboard" (nach dem Close von T=50360258).

ZWEI BEFUNDE, und der zweite ist der eigentliche:

(1) Die 84,86 gehoerten zum NAECHSTEN Trade. Der geschlossene T=50360258 hatte
    SL 84,776; 26 s spaeter lief bereits T=50360505 mit SL 84,863. Kein Fehler,
    nur Verwechslung durch die schnelle Folge.

(2) ABER dabei faellt ein echter Anzeigefehler auf: das SL/TP-Feld der
    Trade-Leiste formatierte mit `fmt(x, 2)`. WTI notiert DREISTELLIG - aus dem
    echten Stop 84,776 wurde die Anzeige 84,78.
    ⚠⚠ Das ist nicht kosmetisch: das Feld ist BESCHREIBBAR, und ein Enter darauf
    schickt den gerundeten Wert per /api/sltp an den Broker. Der Stop verschiebt
    sich also still um bis zu 0,5 Cent - bei einem Trail von 11 Cent (ATR_M5
    0,1104 in dieser Nacht) sind das 5 % der Distanz. Zusaetzlich schaltet
    /api/sltp das Trailing ab, der Nutzer wuerde also einen leicht falschen Stop
    festschreiben und die Nachfuehrung verlieren.

Behoben auf 3 Stellen. Gegengeprueft, dass es kein weiteres Preisfeld mit
`, 2)` gibt.

Reine Frontend-Aenderung (v=189), kein Neustart. node --check und die neue
Render-Probe (Stufe B2) gruen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 00:04:20 +02:00
Axel HocksandClaude Opus 5 f02fd43b39 Telegram: ALLE Trade-Opens und -Closes + Reichweiten-Waechter fuer den 2. Slot
(1) User-Vorgabe: "Alle Trade Closes und Opens sollen per Telegram gemeldet
werden".
 - close_notify_min_eur 50 -> 0, also jeder Close ohne Schwelle
   (Backup oil_widget_config.ini.bak-2026-08-19-tgopen)
 - neuer _check_open_notify: meldet jede Eroeffnung, ueber BEIDE Slots. Der
   BRK-Slot ist ausdruecklich dabei - ein autonomer Entry soll nicht unbemerkt
   bleiben, genau dafuer wurde der zweite Slot gebaut; die Meldung nennt den
   Slot mit.
 - _TG_ERLAUBT um "Trade eroeffnet" erweitert (das Gate ist EINE Filterstelle,
   nicht 17 Einzeleingriffe).
 ⚠ 1x je Ticket ueber _open_notify_gemeldet - ohne den Merker feuerte es im
   1-s-Takt weiter, solange die Position offen ist.
 ⚠ In der Startup-Schonfrist wird nur GEMERKT, nicht gemeldet: nach einem
   Neustart erkennt der Trader eine BESTEHENDE Position wieder, und das ist
   keine Eroeffnung.

(2) Reichweiten-Waechter (_check_slot_reichweite). Gemessener Befund: von den
Schutz-Checks ist NUR _check_circuit_breaker slot-faehig. _check_auto_close
(Notfall-Stop, haengt an 4 Ticket-Variablen), _check_sr_close, _check_adverse15
und _check_flip_close kennen nur Slot 1. Heute folgenlos, weil alle vier AUS
sind - aber wird einer eingeschaltet, waehrend eine BRK-Position laeuft, gilt er
stillschweigend nur fuer Slot 1, und im Dashboard saehe alles normal aus.
Dieselbe Klasse wie Deployment-Drift Fall 8: nicht die Strategie driftet,
sondern ihre REICHWEITE. Der Waechter macht das Loch LAUT (Log-Warnung 1x je
Ticket + Snapshot-Feld `slot_luecke`), bis die vier slot-faehig sind.

⚠ Die volle Parametrisierung der vier Checks steht AUS. _check_auto_close allein
haengt an vier Ticket-Variablen und ist der Notfall-Stop - das gehoert in eine
eigene Sitzung mit Tests, nicht ans Ende einer langen.

⚠ EIGENER FEHLER auf dem Weg: der erste Bauversuch lief per Heredoc und riss das
Telegram-Format-Literal an einem \n auseinander (SyntaxError). Das ist exakt die
im Projekt dokumentierte \n-Falle - "mehrzeilige Strings mit \n NIE per Heredoc
schreiben, den Edit-Weg nehmen". Ich habe die eigene Regel verletzt; engine.py
wurde per git checkout zurueckgesetzt und sauber ueber Edit neu gebaut.

Deploy ueber tools/deploy.py --feld position_brk, alle 5 Schritte.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:23:01 +02:00
Axel HocksandClaude Opus 5 0fe51dea48 Pipeline: zwei neue Pruefstufen vor dem Commit (Typaritaet + JS-Render)
User: "baue alle und integriere in die pipeline vor dem commit". Beide Stufen
schliessen Luecken, die HEUTE real zugeschlagen haben.

A3) TYPPRUEFUNG (ty 0.0.73, Konfiguration in ty.toml)
Anlass: `paarweise(d)` wurde mit 1 von 2 Pflichtargumenten gerufen. py_compile
sah nichts (Syntax ok), ruff F821 auch nicht (der Name IST definiert), kein Test
deckte den Pfad ab - der Fehler schlug erst zur Laufzeit zu.
⚠ BEWUSST ENGES REGELSET: der volle ty-Lauf meldet 172 Befunde, davon 97
`unresolved-attribute` aus fehlenden MetaTrader5-Stubs. Eine Stufe mit
Dauer-Treffern wird ignoriert, und mit ihr die eine echte Meldung (die Lehre vom
07.08.). Aktiv sind nur die Aritaets-Regeln. `call-non-callable` und
`not-iterable` sind AUS - beide melden hier ausschliesslich Falsch-Positive aus
heterogenen dicts (`c["have"]()`, `"up" in c`); geprueft, nicht angenommen.
⚠ Der dokumentierte Einwand "Pruefumgebung != Laufumgebung" greift NICHT: ein
Typchecker fuehrt nichts aus, er kann also nicht divergieren. Er braucht auch
kein MT5.
⚠ Nebenbefund: die CLAUDE.md-Begruendung gegen mypy ("kaum Annotationen
vorhanden") ist veraltet - gemessen sind 305 von 443 Funktionen annotiert (69 %).

B2) RENDER-PROBE (tools/render_check.mjs gegen tests/fixtures/snapshot.json)
Anlass: `node --check` prueft nur SYNTAX. Der ReferenceError von heute Abend
(RSI-Zeile griff in renderM15(s) auf d.market zu) war syntaktisch einwandfrei
und brach im Browser den GESAMTEN Render ab - sechs leere Zeilen und eine leere
Breakout-Karte. Fuer Python gibt es ruff F821, fuer JS gab es nichts.
⚠ Laeuft gegen einen GESPEICHERTEN Snapshot, nicht gegen den laufenden Server -
der Hook darf nicht davon abhaengen, ob gerade ein Server laeuft.
⚠ KEIN ESLint: das braeuchte npm und node_modules, gegen die dokumentierte
Entscheidung ("kein npm, keine package.json").

BEIDE RICHTUNGEN VERIFIZIERT, je Stufe:
  A3  Aritaetsfehler eingebaut -> "FEHLER too-many-positional-arguments",
      1 Befund; zurueck -> gruen
  B2  d.market zurueckgebaut   -> " EXCEPTION: d is not defined",
      1 Befund; zurueck -> gruen
Beide haengen an tools/check_nfalle.py und laufen damit im pre-commit-Hook mit.
Fehlt das Werkzeug (ty nicht installiert, node nicht im PATH, Fixture fehlt),
wird die Stufe uebersprungen statt zu blockieren - eine frische Maschine darf am
Hook nicht haengenbleiben. Ein WERKZEUGFEHLER (Exit != 0/1) gilt dagegen
ausdruecklich NICHT als sauber.

ty in requirements-dev.txt gepinnt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:14:43 +02:00
Axel HocksandClaude Opus 5 95b22e2add FIX: Render brach ab - RSI-Zeile griff im falschen Scope zu (Dashboard kaputt)
User-Screenshot: sechs leere "—"-Zeilen in der M15-Karte unter Gate ④ und eine
komplett leere Breakout-Karte.

URSACHE, mein Fehler von heute Abend: `renderM15(s)` bekommt NUR `m15_setup`.
Meine RSI-Zeile griff aber auf `d.market.rsi_m15` zu - `d` existiert in diesem
Scope nicht. ReferenceError mitten im Render: alles ab der Fehlerstelle blieb
auf dem Initialwert "—", und die danach gerufenen Renderer (u.a. renderBrk)
liefen gar nicht mehr. Genau die Signatur im Screenshot.

⚠⚠ WARUM DIE PIPELINE ES DURCHGELASSEN HAT: `node --check` prueft nur SYNTAX.
Ein ReferenceError ist syntaktisch einwandfrei. Python hat dafuer ruff F821 -
fuer JS gab es nichts Vergleichbares. Das ist die Luecke, nicht ein
Einzelversehen: es ist der ZWEITE Fall derselben Klasse heute (vorhin `d5.m5`
statt `s.m5`, den hatte ich beim Bauen selbst bemerkt).

BEHOBEN: renderM15(s, snap) bekommt den vollen Snapshot mit, Aufrufer angepasst,
Zugriff auf ((snap||{}).market||{}).rsi_m15. Ein Kommentar an der Signatur haelt
fest, warum `d.` dort verboten ist.

NEU: tools/render_check.mjs - laesst renderM15 und renderBrk gegen ein
Minimal-DOM mit einem ECHTEN Snapshot laufen und meldet jede Exception.
Mutationsprobe bestanden: Fehler zurueckgebaut -> " d is not defined",
zurueck -> gruen. Alle vier Zeilen rendern wieder korrekt (RSI, M5-Kontext,
Gate ③b, BRK-Position).

v=188, damit der Browser das Update sicher zieht.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:07:52 +02:00
Axel HocksandClaude Opus 5 621c82bab8 Walk-Forward auf dem Live-Trail: 1,0 gegen 1,5 stabil, gegen 0,8 unentschieden
Zweite der drei benannten offenen Messungen. Der Trail betrifft JEDEN Trade -
nach dem Walk-Forward-Befund vom selben Tag (Squeeze nur 4 von 8 Bloecken
positiv, obwohl "beidhaelftig positiv") war offen, ob LIVE.mult = 1,0 ueber die
Zeitachse haelt oder nur ueber zwei Haelften.

GEPAART gerechnet: alle Multiplikatoren auf DENSELBEN Einstiegen, verglichen
wird die Differenz je Trade. Der sequentielle Vergleich waere ungueltig - ein
anderer Exit laesst ANDERE Trades in den einen Slot, das ist ein Selektions-
und kein Exit-Effekt (die Falle vom 14.08. beim trail_start-Sweep).

ERGEBNIS ueber 8 Bloecke (~35 Tage je Block):
  1,5 gegen 1,0   Vorzeichen  - - + + - - - -    nur 2 von 8 fuer 1,5
  0,8 gegen 1,0   Vorzeichen  - + + + + - + -    5 von 8 fuer 0,8

 Gegen den WEITEREN Trail ist 1,0 stabil bestaetigt: 6 von 8 Bloecken, und die
beiden Gegenbloecke liegen beieinander (3 und 4). Die Entscheidung vom 31.07.
haelt also nicht nur ueber zwei Haelften, sondern ueber die Zeitachse.

⚠ Gegen den ENGEREN Trail ist es unentschieden - 5:3 fuer 0,8, aber das
Vorzeichen kippt dreimal, und ALLE Deltas liegen zwischen -0,026 und +0,097 R.
Damit ist die dokumentierte Aussage "enger ist monoton besser"
(backtest_trailmult.py) als Blocksicht NICHT bestaetigt: sie beschreibt zwei
Regime, keine Stabilitaet. Eine Umstellung auf 0,8 waere nicht gedeckt.

⚠ Effektgroesse: typisch ±0,03 R je Trade. Der Trail ist damit keine
Stellschraube mit Hebel, sondern eine, die man richtig stehen lassen sollte.
Keine Aenderung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 23:00:53 +02:00
Axel HocksandClaude Opus 5 e3e8a6b9fd RSI als Filter auf dem GEGATETEN Signal - die neue Achse traegt auch nicht
User: "neue achse" -> "messe". Das war die einzige nie gepruefte RSI-Population:
alle bisherigen Laeufe massen RSI als EIGENSTAENDIGEN Einstieg
(backtest_rsi_v2.py heute) oder als Konfluenz-Beitrag auf dem UNGEGATETEN
_build-Signal mit altem Exit (backtest_confluence.py). Hier laeuft er auf den
Signalen, die den VOLLEN Live-Gate-Stack passieren - 1344/2038 statt ~1700/2500.

AUFBAU: echte Gate-Pipeline aus backtest_entryroom_level.sammle (kein Nachbau,
inkl. set_entry_room - die Lehre vom 05.08.), RSI-Serie gegen calc_rsi
verifiziert, kanonischer Exit, Echtkosten, 2 Halbjahre, 95-%-KI, beide
Ausfuehrungen, 3 Schwellen als Nachbar-Robustheit.

ERGEBNIS: KEINE der 12 Zellen erfuellt die vorab fixierte Regel. Die Effekte
sind winzig - alle Deltas gegen die Basis liegen bei ±0,06 R, ausser in den
Extrem-Baendern, und die haben n=10 bis 50 (Rauschen).

⚠ Die Projekt-Hypothese "RSI GEGEN die Richtung = doppelter Edge" reproduziert
NICHT: am Markt +0,040 in H2 aber -0,021 in H1, an der Order genau umgekehrt
(+0,010 / -0,041). Vorzeichen kippt in beiden Ausfuehrungen. Der Pullback-Effekt
existiert, aber der RSI ist nicht das Werkzeug, ihn zu greifen - im Bot laeuft er
ueber die EMA-Distanz.

 EIN robuster Befund bleibt, und er ist die Bestaetigung einer vorhandenen
Regel: MIT RSI>70 an der ruhenden Order ist in H2 OeR -0,683 mit KI
[-1,041 .. -0,310], also signifikant NEGATIV. In eine Richtung einzusteigen,
waehrend der RSI dort schon extrem steht, ist messbar schaedlich - genau das,
was die Anti-Ueberdehnung (_STRETCH_MAX 3,5) bereits abfaengt. Kein neuer Filter
noetig, die Wirkung ist schon da.

30. verworfener Signal-Eingriff. RSI bleibt reine Anzeige.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 21:05:11 +02:00
Axel HocksandClaude Opus 5 3839fd5dc0 RSI-Zeile im Dashboard - reine Anzeige, bewusst ohne Ampel
User-Wunsch nach der Messung. `market.rsi_m15` stand bereits im Snapshot
(core/mt5data.py:246 ruft calc_rsi), es ist also eine reine Frontend-Aenderung
(v=187), kein Neustart, die offene Position unberuehrt.

⚠⚠ BEWUSST NEUTRAL und OHNE gruen/rot: die Lehrbuch-Lesart ist am selben Tag
gemessen und durchgefallen (backtest_rsi_v2.py: 24 Zellen ueber 80k M5-Bars und
2 Halbjahre, KEINE besteht, vier sind signifikant negativ; auch die Umkehrung
traegt standalone nicht). Eine Ampel wuerde hier systematisch falsch stupsen -
dieselbe Korrektur wie bei der Kerzen-Anatomie (Lehrbuch-Lesart invertiert) und
bei der Ueberdehnungs-Anzeige, die aus genau diesem Grund "Ueberdehnung" heisst
und nicht "Bounce".

Die Zeile NENNT die Zone (hoch / mittleres Band / tief), bewertet sie aber
nicht. Der Tooltip traegt die Messung samt Skriptnamen und den Hinweis, dass der
WIRKSAME Teil - der Pullback-Effekt - im Bot bereits ueber die EMA-Distanz
laeuft (Konfidenz-Bonus "tiefer Pullback" +15) und ueber die Ueberdehnung. RSI
waere dort eine zweite Verpackung derselben Aussage.

Kein Verdict-Gewicht, kein Trade-Trigger.

Verifiziert: div ausgeglichen, keine doppelten IDs, node --check gruen, v=187
ausgeliefert, Live-Wert 38,2 -> "mittleres Band".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 21:02:46 +02:00
Axel HocksandClaude Opus 5 de801e5f40 S/R-Auto-Close aus: ini nachgezogen und Waechter-Anker gedreht
User hat SR ueber das Dashboard abgeschaltet. Snapshot und runtime_state standen
danach auf false, die INI aber noch auf true - verhalten korrekt (runtime
gewinnt beim Start), aber genau die latente Inkonsistenz, durch die
auto_squeeze am 11.08. unbemerkt aus und auto_m15 am 19.08. unbemerkt AN war.
Ein geloeschtes runtime_state.json haette SR zurueckgeholt. Jetzt alle drei
konsistent false (Backup oil_widget_config.ini.bak-2026-08-19-srclose-aus).

Zusaetzlich der Config-Waechter-Anker gedreht: auto_sr_close validiert jetzt
gegen false statt true. Begruendung ist der Inversions-Befund vom selben Tag -
solange P(break) live rueckwaerts rankt (AUC 0,452, Klassen monoton invertiert),
ist der gegatete S/R-Close faktisch ein pauschaler, und der ist 2x gemessen und
verworfen. Ein Wiedereinschalten ist damit eine Abweichung von der Messung und
soll auffallen.

⚠ Die P(break)-Anzeigen (Chart-Linien, #pos-srhint, stop_approach,
Copilot-Kontext) bleiben aktiv und tragen dieselbe Inversion - sie sind Kontext,
kein Urteil. Das Live-Tracking laeuft weiter, damit ein Neubau eine Messgrundlage
hat.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:58:05 +02:00
Axel HocksandClaude Opus 5 a7a024aa20 BEFUND: P(break) ist live INVERTIERT - und steuert per S/R-Auto-Close echtes Geld
Die faellige Messung ist entscheidbar geworden (n=530 entkoppelt gegen Latte 350).

AUC live 0,452, 95-%-KI [0,405 .. 0,504]. Die Messlatte aus dem Nachtrainieren
vom 31.07. war 0,654 - sie liegt weit ausserhalb des Intervalls.

Die Klassentabelle zeigt eine MONOTONE UMKEHRUNG: die Klasse 0-19 (Modell sagt
8,3 % Bruch) bricht real zu 45,2 %, die Klasse 65-100 (sagt 72,5 %) nur zu
37,9 %. Das ist kein Kalibrierungsfehler mehr - das Modell rankt rueckwaerts.

OPERATIV BRISANT: die Entwarnung in CLAUDE.md ("kein Notfall, auto_sr_close ist
aus seit 06.08.") ist STALE - er wurde am 11.08. wieder eingeschaltet. Das Gate
feuert bei p_break < 0,35 ("Level haelt, Gewinn mitnehmen"), und genau diese
Klassen haben die HOECHSTE reale Bruchrate. Damit ist der S/R-Auto-Close
faktisch ungegatet, und der pauschale S/R-Close ist 2x gemessen und verworfen.

Die Live-Bilanz (13 sr_close seit 11.08., +226,71 EUR) ist KEIN Gegenbeleg:
_check_sr_close schliesst konstruktiv nur im Plus, die Zahl ist per Bauart
positiv.

Ein dritter Fit waere nicht die Loesung: am 07.08. wurde die Niveau-Hypothese
gemessen und widerlegt (Roll-Achse faellt live durch, Regime-Merkmal ebenso).
Eine Inversion laesst sich durch Niveau-Verschiebung nicht beheben.

Nichts geschaltet - das ist eine User-Entscheidung.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:56:09 +02:00
Axel HocksandClaude Opus 5 d7dc997eee RSI zum vierten Mal gemessen - faellt in allen 24 Zellen durch
User: "messe ihn nochmal". Kein blosses Wiederholen: die drei alten RSI-Laeufe
stiegen alle am Bar-Close zum MARKTPREIS ein. Genau diese Annahme hat am
05./06.08. Squeeze und Auto-Signal von negativ auf positiv gedreht (+0,32 bzw.
+0,61 R - mehr als alle Signal-Ideen zusammen). Fuer RSI war die
Ausfuehrungs-Achse nie geprueft.

AUFBAU: 80k M5, 2 Halbjahre, kanonischer Exit, Echtkosten, 95-%-Bootstrap.
2 Lesarten (Lehrbuch-Reversion und die Umkehrung) x 3 Schwellenpaare
(70/30, 75/25, 80/20) x 2 Ausfuehrungen (Markt / ruhende Order am Extrem mit
Fill bei Beruehrung) = 24 Zellen.

⚠ KEIN NACHBAU des Indikators: `calc_rsi` ist ein Wilder-RSI mit Rekursion ueber
die GANZE Reihe, ein Slice waere also nicht dasselbe. Die Serie wird inkrementell
gerechnet und an 200 Zufallsstichproben gegen die echte Funktion verifiziert;
bei Abweichung bricht das Skript ab. Groesste gemessene Abweichung: unter 1e-6.

ERGEBNIS: KEINE einzige Zelle erfuellt die vorab fixierte Regel (beidhaelftig
OeR > 0 UND PF > 1 UND KI ohne die Null UND Nachbarn gleichgerichtet). Vier
Zellen sind sogar beidseitig SIGNIFIKANT NEGATIV (KI komplett unter null):
REV 70/30 am Markt und MOM 75/25 an der Order.

⚠⚠ DIE AUSFUEHRUNGS-ACHSE HILFT HIER NICHT - und das war vorab so vorhergesagt.
Bei REV 75/25 hebt die ruhende Order zwar von -0,107/-0,014 auf +0,006/+0,075,
aber beide Intervalle enthalten weiter die Null, und die Nachbarn kippen
(80/20: H1 -0,181). Das bestaetigt den Mechanismus aus
`backtest_candle_fade2.py`: eine ruhende Order hilft bei MOMENTUM-Entries und
schadet bei REVERSIONS-Entries, weil eine Limit-Order am Extrem nur fuellt, wenn
sich die Bewegung weiter ausdehnt - also genau dann, wenn man falsch liegt.

⚠ Auch die im Projekt dokumentierte Umkehrung ("RSI gegen die Richtung =
doppelter Edge") traegt STANDALONE nicht: die MOM-Zeilen sind ueberwiegend
schlechter als die REV-Zeilen. Der Pullback-Effekt existiert, aber als
Konfidenz-Beitrag im gegateten Signal, nicht als eigenstaendiger Einstieg.

29. verworfener Signal-Eingriff. RSI bleibt draussen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:52:37 +02:00
Axel HocksandClaude Opus 5 33cc451e52 Globales Einsatz-Feld zurueck - es steuert die MANUELLEN Trades
User: "der einsatz wird immer noch nicht uebernommen, siehe aktueller trade",
danach Wahl von Variante A.

DIAGNOSE - kein Defekt, sondern eine Luecke, die ich selbst gerissen habe. Der
laufende Trade war setup=WAVE, also MANUELL; Slot 2 leer; und die Logzeile
"Einsatz fuer <pfad>" existierte kein einziges Mal. Die Pfad-Felder wirken
ausschliesslich auf die beiden AUTONOMEN Pfade - M15 ist aus, BRK hat seit dem
Einbau nicht gefeuert (Circuit-Breaker hat heute dreimal ausgeloest). Das Feld
hatte also nie eine Gelegenheit zu greifen.

Manuelle Trades laufen bewusst auf dem GLOBALEN Wert (der Mensch ist die
gemessen bessere Population, +1,56 gegen -4,71 EUR/Lot - seine Groesse gehoert
ihm). Nur: das globale Feld war am 19.08. auf Wunsch entfernt worden, und
danach kamen die Pfad-Felder dazu. Damit hatte ausgerechnet die Schraube, die
die eigenen Eroeffnungen steuert, keine UI mehr - erreichbar nur noch ueber die
ini plus Neustart. Das habe ich beim Bau der Pfad-Felder nicht mitgedacht.

Behoben: Feld "Einsatz global %" als drittes in derselben Zeile. Endpoint
/api/marginpct, set_margin_pct und die Persistenz existierten bereits - reine
Frontend-Aenderung (v=186), kein Neustart, die offene Position unberuehrt.

⚠ Semantik bewusst ANDERS als bei den Pfad-Feldern: dort heisst leer/0
ausdruecklich "globaler Wert", hier gibt es kein "aus" - ein Einsatz MUSS
gelten. Deshalb echte Untergrenze 1 statt der 0-Semantik.

Verifiziert: 45 gesetzt -> Snapshot -> persistiert -> zurueck auf 40; span
51/51 ausgeglichen, keine doppelten IDs, node --check gruen, v=186 ausgeliefert.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 20:15:21 +02:00
Axel HocksandClaude Opus 5 5593f270cc Dashboard-Zeile fuer Slot 2 + Doku des Zwei-Slot-Umbaus
Die vom Breakout-Trader gehaltene Position ist jetzt sichtbar (#brk-pos in der
Breakout-Karte): Richtung, Lots, Einstieg, P&L - und vor allem der
Trailing-Zustand.

⚠ Der Trailing-Hinweis ist der wichtigste Teil der Zeile: steht er auf
"⚠ TRAILING AUS - nur Broker-SL!", laeuft der Trade in der gemessen
DURCHGEFALLENEN SL-only-Variante (backtest_brk_slonly.py: alle zehn
Konfidenzintervalle enthalten die Null, Trefferquote faellt 40 -> 21 %). Ohne
diese Anzeige waere das im Betrieb nicht bemerkbar - genau Deployment-Drift
Fall 8 (nicht die Strategie driftet, sondern ihre Beobachtbarkeit).

Richtung wird aus SL/TP abgeleitet statt ein weiteres Snapshot-Feld zu bauen -
place_stop setzt immer einen SL. Damit bleibt es eine reine Frontend-Aenderung
(v=185), kein Neustart noetig, die offene Position unberuehrt.

Verifiziert: v=185 wird ausgeliefert, div 85/85 ausgeglichen, keine doppelten
IDs, keine verwaisten JS-Referenzen, node --check gruen.

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