0966caf1b87d15b4ea5caad0ddec79c387d76eda
323
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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> |
||
|
|
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>
|
||
|
|
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>
|
||
|
|
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> |
||
|
|
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> |
||
|
|
a9a6c487d2 |
Circuit-Breaker und Tages-P&L summieren jetzt BEIDE Positions-Slots
Letzte offene Luecke des Zwei-Slot-Umbaus (User: "ja"). WARUM ES ZWINGEND IST: nach dem Umbau kann BRK parallel zu einer manuellen oder M15-Position laufen. Haette der Tages-P&L weiter nur den ersten Slot gesehen, waere eine offene BRK-Position unsichtbar geblieben - der Breaker griffe also genau dann zu spaet, wenn zwei Positionen gleichzeitig laufen und das Risiko doppelt ist. Bei 40 % Einsatz je Position sind 80 % der Margin gebunden. GEAENDERT: - snapshot(): day_pl["open"] summiert beide Slots - _check_circuit_breaker(): dieselbe Summe als Ausloeser - und der Breaker schliesst jetzt BEIDE Positionen - eine Notbremse, die nur die Haelfte schliesst, ist keine. Fehlschlag am zweiten Slot wird geloggt, nicht verschluckt. 91 Tests gruen, Deploy ueber tools/deploy.py --feld position_brk. ⚠ NEBENBEFUND beim Verifizieren, NICHT von dieser Aenderung verursacht: der Circuit-Breaker steht auf 8 % (runtime_state cb_limit_pct = 8.0) und hat heute dreimal ausgeloest (19:17, 20:03, 20:07). Der Tages-P&L liegt bei -178,89 EUR gegen ein Limit von -55,89 EUR. Damit sind fuer heute KEINE autonomen Trades mehr moeglich - auch BRK nicht. Manuelle Orders bleiben frei (so gebaut). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
f04ae4d9d9 |
Fix: Einsatz je Pfad ueberlebte keinen Neustart (Reihenfolge-Fehler)
User: "Einsatz BRK % / Einsatz M15 % hat keine Auswirkung, die Eingabe bleibt wirkungslos, in den Feldern erscheint 'global'". URSACHE - mein Fehler beim Bau: die Default-Initialisierung (self._margin_brk = 0.0) stand in Zeile 631, `_load_runtime_state()` laeuft aber in Zeile 553. Der geladene Wert wurde also unmittelbar danach mit 0 ueberschrieben. Die Eingabe WIRKTE (POST kam an, Wert stand im Snapshot, wurde auf Platte geschrieben) - sie war nach dem naechsten Neustart weg, und das Feld zeigte wieder den Platzhalter "global". Real am 19.08.: BRK 10 / M15 85 gesetzt, nach dem Deploy beide 0. Behoben: Defaults stehen jetzt VOR dem Laden. Reihenfolge ist immer Default setzen -> runtime_state laedt darueber. ⚠ EIGENER FEHLALARM beim Verifizieren, dokumentiert weil er lehrreich ist: mein Persistenz-Test setzte 55/30, und nach dem Neustart standen 85/10 - ich habe das als "VERLOREN" und sogar als Vertauschung gelesen. Die Logzeitstempel zeigen etwas anderes: um 20:06:04 und 20:06:06 hat der Browser des Users zwei weitere POSTs geschickt (85/30, dann 85/10), waehrend mein Test lief. Persistiert wurde also korrekt der ZULETZT gesetzte Wert. Lehre: bei einer Live-Verifikation gegen ein System, das der Nutzer gleichzeitig bedient, gehoert die Logspur mitgelesen - sonst hält man fremde Eingaben fuer einen Defekt. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9b5b20e713 |
BRK bekommt einen EIGENEN Positions-Slot - unabhaengig von manuell und M15
User-Vorgabe: "der brk trade soll komplett unabhaengig von m15 oder manuellen
trades laufen". Entwurf: docs/brk-eigener-slot.md
DER BEFUND, DER DEN UMBAU KLEIN MACHT: TrailingManager.__init__ nimmt bereits
SEINEN Trader entgegen und liest ausschliesslich ueber dessen snapshot() - es
haengt also nicht an einer globalen Position. Damit entfaellt der
29-Stellen-Umbau in engine.py. Stattdessen:
engine.trader - TradeManager() - trail - manuell + M15
engine.trader_brk - TradeManager(nur_ticket=True) - trail_brk - nur BRK
Der validierte Pfad bleibt damit vollstaendig unangetastet - kein
Regressionsrisiko auf der gemessen besseren Population (+1,56 gegen -4,71/Lot).
DIE ZWEI KRITISCHEN STELLEN, beide gebaut:
(1) ADOPTION. TradeManager.refresh() greift per Default jede Position auf dem
Symbol (gewollt: ein von Hand eroeffneter Trade bekommt so den Schutz-Stack).
Mit zwei Managern wuerden sich BEIDE dieselbe Position schnappen. Neu:
`nur_ticket=True` sucht sich nichts, und der adoptierende Manager bekommt
ueber `fremde_tickets` eine Sperrliste (BRK-Ticket + liegende Pendings).
(2) DER FILL. Eine ruhende Order fuellt IM BROKER; der ticket-gebundene Slot
kann sie nicht finden. Neu `TradeManager.bind(ticket, sym)`, aufgerufen aus
_check_pending_fill - es sieht direkt am Broker nach, welches der liegenden
Tickets zu einer Position geworden ist.
WEITER GEAENDERT: _check_auto_squeeze und _manage_squeeze_pending lesen den
EIGENEN Slot (eine manuelle oder M15-Position storniert die Pendings nicht mehr
- real am 19.08. waren es 5 Fenster mit zusammen ~2 min am Markt, 3 davon vom
M15-Trader); trail_brk wird in _price_loop mit Preisen versorgt (ohne das liefe
BRK in der gemessen DURCHGEFALLENEN SL-only-Variante); Snapshot-Feld
`position_brk` macht den zweiten Slot sichtbar - ohne das waere es
Deployment-Drift Fall 8 in neuer Form (nicht die Strategie driftet, sondern
ihre Beobachtbarkeit).
TESTS: 91 gruen. tests/test_pending_fill.py auf den BRK-Slot umgestellt - die
Aussagen bleiben unveraendert (fremde Quelle wird NICHT getaggt, derselbe Fill
zaehlt nur einmal), nur der Slot ist ein anderer. Die Tests wurden NICHT
abgeschwaecht; sie sichern weiter Deployment-Drift Fall 8.
LIVE VERIFIZIERT: Slot 1 fuehrt die offene Position (T=50349215) unveraendert
weiter, Slot 2 ist leer und wartet auf einen Squeeze. Deploy ueber
tools/deploy.py --feld position_brk, alle 5 Schritte.
⚠ OFFEN und bewusst NICHT in diesem Zug: Circuit-Breaker und Tages-P&L summieren
noch nicht BEIDE Slots, und die Dashboard-Zeile fuer den zweiten Slot fehlt. Mit
zwei Positionen sind bei 40 % je Position 80 % der Margin gebunden - der Breaker
(aktuell AUS) waere dann keine Kuer mehr.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
815b6a77b8 |
Entwurf: BRK mit eigenem Positions-Slot (docs/brk-eigener-slot.md)
User: "der brk trade soll komplett unabhaengig von m15 oder manuellen trades laufen". Der Entwurf ist am echten Code verifiziert, aber NICHT gebaut - Umsetzung gehoert in eine eigene Sitzung mit flachem Konto. DER ENTSCHEIDENDE BEFUND macht den Umbau viel kleiner als gedacht: TrailingManager.__init__ nimmt BEREITS einen Trader entgegen (trailing.py:146) und liest ausschliesslich ueber self.trader.snapshot(). Es haengt also nicht an einer globalen Position, sondern an SEINEM Trader. Damit ist die Loesung ein ZWEITER, ticket-gebundener TradeManager fuer BRK samt eigenem Trailing - statt 29 Stellen in engine.py umzubauen. Der validierte Pfad (manuell + M15) bleibt dabei vollstaendig unangetastet, also kein Regressionsrisiko auf der gemessen besseren Population. DER KRITISCHE PUNKT ist die Adoption: TradeManager.refresh() greift heute jede Position auf dem Symbol (positions_get(symbol=sym) mit Fallback auf alle). Mit zwei Managern wuerden sich beide dieselbe Position schnappen. Der BRK-Manager muss deshalb STRIKT ticket-gebunden sein - das ist die eine Aenderung, an der der ganze Entwurf haengt. Dokumentiert sind ausserdem die sieben Bauschritte in Reihenfolge, vier Vorbedingungen (flaches Konto, RETAIL_HEDGING bestaetigt, doppeltes Risiko und damit die Breaker-Frage, Margin-Semantik des Feldes "Einsatz je Pfad") und die Erfolgskontrolle. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
5f4d66bcaf |
Doku: auto_m15 aus, und die Messung die den kleinen Umbau ausschliesst
Zwei Eintraege. (1) Warum kein BRK-Trade zustande kam: fuenf Pending-Fenster, zusammen rund 2 Minuten am Markt, drei davon vom M15-Trader storniert - einmal in derselben Sekunde. (2) Die Messung, ob BRK ohne Trailing laufen koennte (backtest_brk_slonly.py): keine der fuenf Varianten erfuellt die vorab fixierte Regel, alle zehn KI enthalten die Null. Festgehalten sind ausdruecklich auch die beiden Grenzen: die Kontrolle reproduziert NICHT (Absolutwerte unbrauchbar, nur der interne Vergleich zaehlt), und das scheinbar bessere SL-only ist ein Varianz-Befund (WR 40 -> 21 %, KI-Breite vervierfacht). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
3e4a181c00 |
Messung: was bleibt vom BRK-Edge ohne Trailing? Ergebnis: kleiner Umbau faellt aus
User-Wunsch "BRK soll auch eroeffnen wenn M15 aktiv ist" + Entscheidung fuer
Variante 1+3 (erst messen, dann grosser Umbau in eigener Sitzung).
WARUM DIESE MESSUNG DIE BAUWEISE ENTSCHEIDET. Der KLEINE Umbau (Pendings nicht
mehr stornieren, open_* nicht mehr bei self.ticket abweisen) waere an einem
Abend gemacht - aber der zweite Trade haette dann nur den Broker-SL. `trader`
haelt EIN Ticket, und Trailing, Breakeven, Time-Stop, Notfall-Stop und
S/R-Close haengen alle daran (29 Stellen in engine.py). Die dokumentierten
Squeeze-Zahlen sind MIT dem kanonischen Exit gemessen; SL-only ist eine andere,
nie gemessene Konfiguration - Deployment-Drift per Konstruktion.
AUFBAU. Echte core.squeeze_scan-Regel, LIVE-Parameter (⚠ ATR-Floor 0,06, nicht
der Modul-Default 0,12), ruhende Stop-Order mit Fill bei BERUEHRUNG, Echtkosten,
80k M5, 2 Halbjahre, 95-%-Bootstrap, feste GETEILTE Einstiegsliste (alle
Varianten auf DENSELBEN Trades - sonst vergleicht man Populationen statt Exits).
⚠ KEINE Exit-Kopie: SL-only entsteht aus LIVE.with_(trail_start=999, be=999) -
der Trade bleibt in Phase "Init" und verlaesst sie nur ueber SL oder max_hold.
Es laeuft derselbe kanonische Code. Eine eigene Schleife waere das fuenfte
Exit-Modell gewesen.
ERGEBNIS (H1 / H2, OeR):
A) kanonisch (heute) -0,145 / +0,036 PF 0,76 / 1,07 WR 40 / 44 %
B) SL only -0,132 / +0,464 PF 0,92 / 1,27 WR 21 / 19 %
C) SL + Time-Stop -0,157 / +0,138 PF 0,87 / 1,12
D) SL + TP -0,188 / +0,073 PF 0,86 / 1,06
E) SL + Time + TP -0,212 / +0,064 PF 0,81 / 1,06
KEINE Variante erfuellt die vorab fixierte Regel (beidhaelftig OeR > 0 UND
PF > 1 UND 95-%-KI ohne die Null). H1 ist durchgehend negativ, und ALLE zehn
Intervalle enthalten die Null. Die vorab fixierte Antwort lautet damit:
GROSSER Umbau, nicht kleiner. Das deckt sich mit der Entscheidung des Users.
⚠⚠ GRENZE, die nicht ueberspielt werden darf: die KONTROLLE reproduziert NICHT.
Variante A liefert -0,145/+0,036, dokumentiert sind +0,124/+0,292
(backtest_squeeze_touchfill.py), und meine Einstiegszahl ist 362/559 gegen
1092/1807. Meine Auswahl ist also deutlich strenger. Damit sind die
ABSOLUTWERTE unbrauchbar; belastbar ist allein der INTERNE Vergleich, weil alle
Varianten auf derselben Entry-Liste laufen und sich nur im Exit unterscheiden.
Derselbe Vorbehalt wie am 13.08. bei backtest_squeeze_srclose2.py.
⚠⚠ UND DER INTERNE VERGLEICH IST KONTRAINTUITIV: SL-only sieht im OeR NICHT
schlechter aus (H1 -0,132 gegen -0,145, H2 +0,464 gegen +0,036). Das ist aber
kein Argument fuer den kleinen Umbau, sondern ein Varianz-Befund:
- Trefferquote faellt 40 -> 21 % bzw. 44 -> 19 %. Vier von fuenf Trades laufen
in den vollen -2R-Stop.
- Die KI-Breite explodiert: [-0,108 .. +1,115] gegen [-0,081 .. +0,148] beim
kanonischen Exit - rund das Vierfache.
Der Ertrag haengt an wenigen sehr langen Laeufern (max_hold 200 Bars = 16,7 h
ohne jede Absicherung). Unter 40-%-Margin-Sizing ist "81 % der Trades verlieren
volle 2R" eine ganz andere Risikoklasse als die gemessene - und statistisch
nicht von null zu unterscheiden.
FAZIT: nichts gebaut, nichts umgeschaltet. Der grosse Umbau (Trailing je Ticket)
bleibt der Weg, und er gehoert in eine eigene Sitzung mit FLACHEM Konto - ein
halb fertiger Ticket-Umbau laesst den Schutz-Stack an der falschen der beiden
Positionen haengen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
a07ad942c1 |
Gesamtpruefung: drei echte Fehler behoben, alle drei aus meinem eigenen Code
Dritter vollstaendiger Durchlauf nach docs/review-prompt.md (nach 02.08. und
11.08.). Bemerkenswert: alle drei Funde stammen aus Aenderungen der letzten zwei
Tage, und alle drei sind DIESELBE Klasse - ein vorhandenes Muster nicht kopiert,
sondern ein eigenes erfunden.
FUND 1 (kritisch) - DER CONFIG-WAECHTER WAR TOT.
Mein CONFIG_DEPS-Eintrag fuer auto_m15 vom 19.08. trug das Feld "soll", die
anderen 15 Eintraege tragen "validated". config_drift() lief in einen KeyError
und warf - damit meldeten ALLE 16 Anker nichts mehr, seit gestern. Der Waechter,
der die auto_m15-Abweichung haette melden sollen, war durch genau diesen
Eintrag erledigt.
Behoben: Feldname angeglichen UND config_drift gehaertet - ein defekter Eintrag
wird jetzt uebersprungen und als eigener Befund GEMELDET statt den ganzen
Waechter zu toeten. Ein Waechter, der still stirbt, ist schlimmer als keiner
(dieselbe Klasse wie der ruff-Exit-2-Fall vom 07.08.).
Der Waechter meldet seitdem wieder: margin_buffer_pct 40 gegen 95,
auto_m15 true gegen false, auto_squeeze true gegen false - alle drei sind
dokumentierte User-Entscheidungen, aber sie waren unsichtbar geworden.
FUND 2 (Geld) - DER EINSATZ JE PFAD WAR FUER BRK WIRKUNGSLOS.
engine._open setzt den Einsatz je Pfad - aber _manage_squeeze_pending legt
ruhende Stop-Orders ueber trader.place_stop -> calc_lots, also NICHT ueber
_open. Gemessen fuellen 7 von 8 BRK-Trades per ruhender Order (seit dem
Pending-Umbau 05.08.). Das Feld haette also genau an der Stelle nicht gegriffen,
fuer die es gebaut wurde - und das faellt im Betrieb nur auf, wenn jemand die
Lots nachrechnet.
FUND 3 (Geld, Race) - GLOBALE MUTATION UEBER EINE LOCK-GRENZE.
Der erste Entwurf setzte config.MARGIN_BUFFER temporaer. Der Global wirkt
prozessweit, und zwischen dem Setzen in _open und dem mt5_lock in trader._send
liegt ein Fenster von bis zu 15 s (Lock-Timeout). Eine gleichzeitige MANUELLE
Order haette darin mit dem Prozentsatz des AUTONOMEN Pfads gesized.
FUND 2 und 3 gemeinsam behoben: calc_lots bekommt einen EXPLIZITEN Parameter
buffer_pct (Default None = global), durchgereicht ueber _send/_send_locked/
open_long/open_short/place_stop. Keine Mutation mehr, und beide Bestellwege
tragen denselben Wert.
TESTS - und eine Luecke in meinem eigenen Test, die erst die Mutationsprobe zeigte:
tests/test_buffer_pct.py, 6 Tests. Die erste Fassung bildete die Regel NACH
(_buf) statt die echte Funktion zu pruefen - die Mutation "calc_lots ignoriert
den Parameter wieder" lief damit GRUEN durch. Das ist die dokumentierte
Nachbau-Falle, diesmal in einem TEST. Ergaenzt um eine AST-Pruefung, dass
calc_lots den Parameter im Rumpf wirklich benutzt. Beide Mutationen werden jetzt
gefangen (Parameter aus place_stop entfernt -> rot; calc_lots ignoriert ihn ->
rot).
OHNE BEFUND (geprueft, sauber): check_nfalle, ruff F821, 91 Tests, node --check;
100 JS-Zugriffe gegen 124 HTML-IDs -> 0 fehlend (die 4 gemeldeten waren
Falsch-Positive meiner Regex: zwei stehen in Kommentaren, raum-* wird dynamisch
als $("raum-" + st) gebaut, tb-dur ueber getElementById); 2 Config-Schluessel
ohne Leser (beide [zones], dokumentiert schlafend); 14 Snapshot-Felder ohne
app.js-Leser (dokumentiert als Diagnose-Oberflaeche, deploy.py --feld braucht
sie); Snapshot-Median 15,7 ms bei p90 25,7 ms - unveraendert zum 11.08. und weit
unter dem 1-s-Budget, keine Massnahme.
TELEMETRIE-PULS: alle 7 Logger schreiben. rec_outcomes steht bei 72 Zeilen -
beim Review am 11.08. stand es auf "hat NIE geschrieben", der Fix vom 12.08. hat
also gewirkt.
DIVERGENZ-WAECHTER: A) WARTEN +16,6 Pp ueber der Erwartung (bekannt, wird von
den Live-only-Gates getragen); D) mom3 -0,55 Sigma - knapp ueber der bewusst
tiefen 0,5-Sigma-Schwelle, beobachten.
⚠ NICHT ANGEFASST (User-Entscheidungen, nur berichtet): auto_m15 laeuft live
ueber runtime_state.json gegen die ini; Circuit Breaker aus (cb_limit_pct 0
gegen ini 8); BRK an trotz gefallener B5-Regel.
Deploy ueber tools/deploy.py --feld margin_brk, alle 5 Schritte gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
027267063d |
Einsatz-je-Pfad-Feld war nicht bedienbar - auf das bewaehrte Muster umgebaut
User: "Einsatz je Pfad kann ich nichts eingeben".
URSACHE - mein erster Entwurf hat ein EIGENES Markup erfunden, statt das zu
nehmen, das im Projekt nachweislich funktioniert. Zwei Fehler darin:
(1) KEIN `inputmode`. Alle funktionierenden Felder des Projekts (SL, TP,
Gewinn-Close, Notfall-Close) tragen `inputmode="decimal"` - am Handy
erscheint sonst keine brauchbare Zahlentastatur. Das allein macht ein Feld
praktisch unbedienbar, obwohl es sichtbar und technisch "aktiv" ist.
(2) Die Inputs steckten in einem <b> innerhalb einer `.kv`-Zeile. `.kv` ist
`display:flex; align-items:baseline` und fuer das Muster
<span>Label</span><b>Wert</b> gebaut - also fuer TEXT, nicht fuer
Formularelemente.
BEHOBEN: identisches Markup wie die Trade-Leiste (`.tb-row` > `.tb-field` mit
<label> ueber <input>), plus `inputmode="decimal"` und `placeholder="global"`
statt "BRK"/"M15" - das macht zugleich sichtbar, was LEER bedeutet.
Zusaetzlich den Render gehaertet, damit der 1-s-Snapshot die Eingabe nicht
fressen kann: Feld mit Fokus wird gar nicht angefasst, und geschrieben wird nur
bei tatsaechlicher Aenderung (eine Zuweisung setzt sonst auch bei identischem
Text die Cursorposition zurueck).
⚠ LEHRE, die ueber diesen Fall hinausgeht: es gab in derselben Datei vier
funktionierende Vorbilder, und ich habe keines davon angesehen, bevor ich ein
neues Muster erfunden habe. Beim Hinzufuegen eines Bedienelements gehoert das
vorhandene Muster kopiert - dieselbe Klasse wie die dokumentierte Regel, beim
Wiederverwenden eines Backtest-Kerns die Live-KONFIGURATION mitzukopieren.
Reine Frontend-Aenderung (HTML/CSS/JS + v=184) - kein Neustart noetig, statische
Dateien werden je Request frisch von der Platte gelesen. Verifiziert: Tags
ausgeglichen (div 84/84, span 49/49), keine doppelten IDs, node --check gruen,
beide Felder mit inputmode im ausgelieferten HTML, v=184 wird ausgeliefert.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
8bbc58f336 | Doku: M5-Kontextzeile und die vorab fixierte Bedingung, die sie ersetzt hat | ||
|
|
7915e171d0 |
M5-Kontextzeile in der M15-Karte statt einer eigenen M5-Setup-Karte
User fragte nach einer M1- oder M5-Setup-Karte und hat der hier gebauten
Variante zugestimmt: eine reine ZUSTANDS-Zeile, ohne Richtung und ohne Banner.
WARUM KEINE ZWEITE KARTE - und diesmal entscheidet eine frische Messung, nicht
eine Meinung. Die entkoppelte Selbstmessung der BESTEHENDEN Karte steht bei
n=342 (gruen + gerichtet, ab dem Hysterese-Stichtag 12.08.):
30 min 53,5 % KI [48,2 .. 58,8] -> enthaelt 50 %
60 min 49,3 % KI [44,0 .. 54,5] -> enthaelt 50 %, liegt DARUNTER
Am 12.08. war die Bedingung fuer ein Ja VORAB fixiert worden: ">=350 Faelle,
Trefferquote ueber 50 %, KI ohne die 50". Die Stichprobe ist jetzt da, die
Bedingung ist NICHT erfuellt. Das ist kein "noch zu wenig Daten" mehr.
Dazu die Messung vom 13.08.: als Handelsregel faellt die Karte durch
(backtest_m15_auto.py, OeR -0,162/-0,094, beide KI ohne Null, schlechter als
die HTF-Richtung UND schlechter als ihr eigenes Gegenteil).
M1 scheitert zusaetzlich an der Arithmetik: Spread/ATR Median 0,319 gegen 0,193
(M5) und 0,104 (M15). Feiner aufloesen macht die EINZIGE gemessene Staerke der
M15-Karte - die Kosten - monoton schlechter. Um 01:00 ist der Spread
1,051xATR_M1, also groesser als die mittlere Kerze; und die M1-Historie ist bei
80 Tagen gedeckelt, zwei Stichproben laegen im selben Regime.
GEBAUT ist deshalb Zustand ohne Urteil: Squeeze-Lage (armiert/Ausbruch/keine
Kompression + Box), Kosten in xATR_M5 mit den Schwellen aus
backtest_realcosts.py (Median 0,193, ab 0,32 Kostenfalle) und der ATR.
Der M5-RAUM wird bewusst NICHT wiederholt - Gate 3b rechnet ohnehin auf M5.
⚠ NUR ZUSAMMENGESETZT, nichts neu gerechnet: wave.squeeze und bid/ask/ATR_M5
stehen im Snapshot ohnehin. Ein zweiter Rechenweg war der Fehler des
Konsens-Pfeils (komplettes zweites _verdict im 5-s-Takt) und ist die Quelle
jeder Divergenz zwischen Karte und Chart.
⚠ Kein Verdict-Gewicht, kein Trade-Trigger, keine Farbampel - dieselbe
Zurueckhaltung wie bei der Kerzen-Anatomie und der Ueberdehnungs-Anzeige.
Live verifiziert: "M5 · keine Kompression (Box 3.52xATR) · Kosten 0.15xATR_M5
guenstig · ATR 0.165". Deploy ueber tools/deploy.py --feld m15_setup.m5
(Punktpfad), alle 5 Schritte gruen.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
618f3a4bee |
Doku: Einsatz je Pfad, MQL5 v1.44 und drei neue Fehlerklassen
Pflege-Regel. Festgehalten sind neben den beiden Features vor allem drei Fallen, die heute real zugeschlagen haben: 1. Ein fehlgeschlagener MQL5-Compile LOESCHT die .ex5 - und der Default-Log des Terminals wird dabei nicht ueberschrieben. Ich habe daraufhin "0 errors" aus einem stale Log gemeldet, waehrend der Chart gar keinen Indikator hatte. Regel: eigener Logpfad je Compile, Pruefung auf "Result: N errors" PLUS .ex5-Zeitstempel. 2. Backticks in einer Bash-Commit-Nachricht werden als Kommando ausgefuehrt. 3. "git commit --amend -F <fehlende Datei>" nimmt eine stale COMMIT_EDITMSG, also die Nachricht eines fremden Commits. Asset-Version auf v=182 nachgezogen (stand noch auf 169). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
0a465f9258 |
Einsatz-Prozentsatz je autonomem Pfad (BRK / M15) + Dashboard-Feld
User: "Baue ein Eingabefeld im Dashboard ein in welchem ich das Margin Verhaeltnis von M15 / BRK manuell setzen kann". ⚠⚠ EHRLICHE EINORDNUNG, weil die Umsetzung NICHT ist, wonach es klingt: eine GLEICHZEITIGE Aufteilung (z.B. 40 % manuell / 50 % reserviert fuer BRK) ist heute nicht baubar. Der Bot haelt EINE Position - _check_auto_squeeze feuert "nur FLAT", und Trailing, Notfall-Stop, S/R-Close, Time-Stop und Breaker verwalten je EINE Position (42 Einzel-Positions-Annahmen in engine.py, 25 in trader.py). Mit zwei Positionen auf demselben Symbol haengt der GESAMTE Schutz-Stack an einer davon, die andere liefe ungeschuetzt. Das ist kein Aufwands-, sondern ein Sicherheitsargument. GEBAUT ist deshalb das, was heute wirkt und dieselbe Frage beantwortet: je Pfad ein eigener Einsatz-Prozentsatz. 0 = globaler Wert (bisheriges Verhalten). Quellen-abhaengig verdrahtet wie die SL-Zeitebene seit 05.08.: _open() setzt config.MARGIN_BUFFER fuer die Dauer des einen Aufrufs und stellt ihn im finally-Zweig zurueck. Manuelle Trades bleiben beim globalen Wert (der Mensch ist die gemessen bessere Population, +1,56 gegen -4,71 EUR/Lot). ⚠ Direkt gesetzt statt ueber set_margin_buffer(): das loggt je Trade eine Zeile UND wuerde den globalen Wert dauerhaft ueberschreiben. ⚠⚠ ZWEI ECHTE FEHLER VOM LINTER GEFANGEN, die py_compile durchgewinkt hat: "config" war in engine.py gar nicht importiert (nur Einzelnamen via "from core.config import ..."), und in server.py hiess die Engine "eng" statt "app.state.engine". Beide sassen in Pfaden, die erst beim ERSTEN autonomen Trade bzw. beim ersten Klick gefeuert haetten - also genau die Klasse, fuer die ruff F821 am 07.08. eingebaut wurde. ⚠ Frontend: $streng statt $, weil LEER hier ausdruecklich 0 = "global" bedeutet und nicht "unveraendert"; mit dem Auffang-Element waere .value undefined -> NaN -> null. Der Render ueberschreibt das Feld nicht, solange es den Fokus hat (sonst frisst der 1-s-Snapshot die laufende Eingabe). ⚠ Beim Committen selbst zweimal danebengegriffen, beides dokumentiert weil es Fehlerklassen sind: (a) Backticks in einer Bash-Commit-Nachricht werden als Kommando-Substitution ausgefuehrt und loeschen die eingeklammerten Namen aus dem Text; (b) ein Bash-Pfad (/c/Users/...) an Python uebergeben schlaegt fehl, und "git commit --amend -F <fehlende Datei>" nahm daraufhin eine STALE COMMIT_EDITMSG - die Nachricht eines fremden Commits. Der Code war davon nie betroffen (Arbeitsbaum sauber, Remote synchron), nur die Beschriftung. Ende-zu-Ende geprueft: 50/25 gesetzt -> Snapshot -> persistiert; 150 abgelehnt; 0/0 zurueck. Deploy ueber tools/deploy.py --feld margin_brk, alle 5 Schritte. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
8e7223f6ce |
MQL5 v1.44: Zeilenhoehe der Meldungen MESSEN statt schaetzen
User: 'die zeilenabstaende sind immer noch zu gering' (nach v1.43).
ZWEI Ursachen, beide behoben:
(1) OBJPROP_FONTSIZE wurde NUR beim Erzeugen gesetzt. Ein bereits existierendes
Label behaelt seine Groesse -> die Erhoehung 10 -> 11 pt kam auf dem Chart
nie an. Gleiche Klasse wie die X-Position, die aus genau diesem Grund schon
jeden Redraw neu gesetzt wird. Jetzt auch die Schriftgroesse.
(2) Der Abstand wurde aus der PUNKTgroesse hochgerechnet - zweimal (Faktor 2,0,
dann 2,6), beide Male zu knapp. Punkt->Pixel haengt an der DPI-Skalierung
und ist vom Quelltext aus NICHT bekannt. Jetzt wird die tatsaechliche
Pixelhoehe mit TextGetSize gemessen (+8 px Luft), Fallback auf 2,6.
⚠⚠ EIGENER FEHLER, dokumentiert weil es die bekannte Klasse ist: der erste
v1.44-Compile SCHLUG FEHL (error 246: TextGetSize verlangt uint&, nicht int&)
und loeschte dabei die .ex5 - der Chart hatte kurzzeitig GAR KEINEN Indikator.
Ich habe trotzdem '0 errors' gemeldet, weil ich einen STALE Logfile gelesen
habe (erkennbar an identischen 894 ms). Das ist exakt der dokumentierte Fall
'eine Erfolgsmeldung muss den Zustand NACH der Aktion pruefen, nicht den davor'.
Aufgefallen nur, weil die .ex5-Zeitstempelpruefung danebenstand.
Jetzt: eigener Logpfad je Compile + Pruefung auf 'Result: N errors' + .ex5-Alter.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
1b5bdf98e4 |
MQL5 v1.43: Meldungen groesser (10->11 pt) und Zeilenabstand 2.0 -> 2.6
User: 'die meldungen sind eine schriftgroesse zu klein und ueberlagern sich im MT5'. Zwei Aenderungen an derselben Stelle, weil beide Symptome dieselbe Ursache haben: OBJPROP_FONTSIZE ist in PUNKT, nicht Pixel. 11 pt rendern je nach DPI 18-24 px hoch - mit Faktor 2.0 (=22 px) beruehren sich zwei Zeilen bereits. Faktor 2.6 (=28 px bei 11 pt) traegt auch 125 % DPI. ⚠ Die Schriftgroesse zu erhoehen OHNE den Abstand mitzuziehen haette die Ueberlagerung VERSCHLIMMERT - der Abstand haengt am Faktor, nicht am Absolutwert. Kompiliert ins RICHTIGE Terminal (D0E8209F.., das mit sr_levels.csv - der dokumentierte Fallstrick): 0 errors, 0 warnings. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
444ed27ade |
Nachtrag: die drei falschen M15-Trades liefen alle ueber den alten Code
Zeitachse: 18:03:25 / 18:11:04 / 18:13:18 alle SHORT, Engine erst 18:13:31 neu
gestartet. Beweis ist das Log-Format der 18:13:17-Zeile ('Lesart ab, Level ...'
statt des neuen 'erlaubt, verboten=...'). Der Neustart kam 14 Sekunden zu spaet.
Zwei Fehler, beide meine: (1) der erste Bau nahm die Lesart statt des Vetos;
(2) ich habe den Schalter testbereit stehen lassen, waehrend der Fix noch nicht
deployt war -- der User schaltete ein und der alte Code feuerte sofort. Regel:
ein autonomer Pfad mit bekanntem Defekt gehoert hart aus, nicht nur 'nicht
eingeschaltet'.
Noch nicht live belegt: dass die neue Richtung korrekt eroeffnet. Der erste
echte Entry ist die Verifikation -- die Logzeile muss 'erlaubt, verboten=...'
enthalten.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
c5190e77fd |
M15-Auto-Entry: Richtung aus dem Veto + Abbruchregel verankert
(1) Der Auto-Entry nimmt die Richtung jetzt aus bias.verboten (= die ERLAUBTE Richtung), also genau das, was die Karte anzeigt (app.js:504 nimmt erl). Kein Veto -> kein Entry, weil die Karte dort ausdruecklich keine Richtung gibt. Gegenprobe an der Live-Lage: verboten=SHORT, lesart=ab -> alt SHORT (die verbotene!), neu LONG = identisch zur Anzeige. Damit entspricht der Pfad der gemessenen Kontrolle C (-0,085/-0,030), der am wenigsten schlechten Variante -- aber weiterhin negativ. Die Korrektur behebt den Widerspruch, nicht den fehlenden Edge. (2) measurement_reminder.py: neue Messung m15_abbruch (>=20 AUTOM15_*-Trades, Latte Verhaeltnis < 1,0 ODER PF < 1) und Config-Anker auto_m15 (validiert false), dazu der Helfer _zaehle_setup(). Der Zaehler zaehlt nur geschlossene Trades. Damit kann die vorab fixierte Regel nicht mehr unbemerkt verfallen -- genau das war bei B5 wochenlang der Fall. Aktivierung steht aus: Backend-Aenderung, braucht einen Neustart. auto_m15 ist aus, also keine Eile -- der Neustart wartet, bis das Konto flat ist. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
412aab706d |
M15-Auto-Entry handelte die VERBOTENE Richtung -- abgeschaltet
User: 'der auto trader hat short eroeffnet obwohl long angezeigt wurde'. Bestaetigt. auto_m15 = false, auch in runtime_state. Ein Trade betroffen (18:03:24, SHORT 0,39 Lot @ 86,266). Widerspruch: die Anzeige (app.js:504) nimmt bias.verboten -> die ERLAUBTE Richtung (LONG), mein _check_auto_m15 nahm die P(break)-lesart (SHORT). Damit hat der Bot die VERBOTENE Richtung eroeffnet -- und das Veto ist die einzige beidhaelftig robuste Aussage der Karte (-6,60 EUR/Lot gegen das Signal). Ursache: ich habe die Richtung gegen backtest_m15_auto.py geprueft und damit dessen Variante A gebaut. Uebersehen: derselbe Backtest hat eine Variante B (Lesart + veto-konform, -0,104/-0,051), und die Karte zeigt B. A gebaut, B angezeigt. Geprueft hatte ich nur gegen den Backtest, nicht gegen die Anzeige. Lehre: bei einem Auto-Entry auf eine ANGEZEIGTE Empfehlung ist die Anzeige die zu pruefende Referenz. Position laeuft auf User-Entscheidung weiter (Trailing an). Offen: ob der Trader auf die angezeigte Richtung (Variante B) umgebaut wird. Zweiter offener Punkt: die vorab fixierte M15-Abbruchregel ist noch nicht in measurement_reminder.py verankert. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
bd65bdaad0 |
M15-Auto-Entry gebaut (Default AUS) -- gegen die Messung, auf User-Wunsch
User wollte den Auto-Trade testen, nach vollstaendiger Information ueber die
Beleglage. backtest_m15_auto.py (13.08.): die gehandelte Lesart ist in BEIDEN
Halbjahren negativ (OeR -0,162/-0,094, PF 0,72/0,84), beide KI schliessen die
Null aus, Nachbarn monoton schlechter, und sie ist schlechter als die
HTF-Richtung UND als ihr eigenes Gegenteil. Live entkoppelt 46,8 % Treffer.
_check_auto_m15 im _pos_loop: Ausloeser gruen + gerichtet, Richtung exakt wie im
Backtest (auf->LONG, ab->SHORT), Dedup 1x je Episode ueber (Richtung, Level),
nur FLAT, Setup-Tag AUTOM15_*. Erbt die VOLLE Guard-Kette ueber
_auto_guard('m15') -- der Parameter war laut Docstring genau dafuer vorgesehen,
nachgebaut wurde nichts.
Abweichung ausdruecklich benannt: gemessen wurde der Einstieg AM Level mit Fill
bei Beruehrung, gebaut ist der Markt-Einstieg. Der ist hier mehrfach als der
schlechtere gemessen -- die Live-Zahlen sind eher noch unter -0,16/-0,09 zu
erwarten.
Abbruchregel VORAB fixiert: nach >=20 AUTOM15_*-Trades Verhaeltnis < 1,0 ODER
PF < 1 -> auto_m15 = false. Dieselbe Latte wie B5, damit sie nicht nachtraeglich
wandert.
Verifiziert: Toggle, Snapshot-Felder, Deploy mit --feld auto_m15, ruff F821
(neuer Code sitzt in einem except -- der dokumentierte blinde Fleck), 85 Tests.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
cc3a710752 |
Praezisierung: der Squeeze-Backtest unterstellt keinen Flat-Entry
User bat um Ueberpruefung der Aussage 'Reverse nie validiert -- der Squeeze-Backtest unterstellt Flat-Entry'. Die Sache stimmt, die Begruendung war ungenau. squeeze_scan.scan hat ueberhaupt keinen Positions-Zustand: nach jedem Ausbruch springt i = j + cooldown (3 Bars), nicht bis zum Exit. Jeder Ausbruch ist ein isolierter Trade, Trades duerfen sich ueberlappen. Der Backtest unterstellt also nicht Flatness -- die Lage 'Gegen-Position offen, wird gedreht' kann darin schlicht nicht vorkommen. Gegengeprueft: kein einziger backtest_squeeze*.py enthaelt das Wort 'reverse'; gemessen wurde nur die Exit-only-Halbvariante (3x, alle negativ). Zweite Folge, wichtiger: weil kein Slot modelliert wird, unterstellen die dokumentierten Squeeze-Zahlen, dass man jeden Ausbruch nehmen kann -- live gibt es EINEN Slot (die Sim ueberhandelt um das 2,4-fache, Befund vom 11.08.). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |