Commit Graph
53 Commits
Author SHA1 Message Date
Axel HocksandClaude Opus 5 59f5cf2586 CB in das Feld TAG P/L, Farben invertiert (v=213)
User-Vorgabe. Zwei Aenderungen.

(1) Der CB-Knopf sitzt jetzt im Feld TAG P/L, rechts neben dem Wert. AT und TR
bleiben im Balance-Feld. VERSCHOBEN, nicht kopiert.
Passt inhaltlich: der Circuit Breaker haengt am TAGES-Verlust, und genau der
steht in diesem Feld - der Knopf sitzt jetzt neben der Zahl, die ihn ausloest.

(2) FARBEN INVERTIERT: jetzt GRUEN = aktiv (scharf), ROT = inaktiv (aus).
⚠ Damit lesen sich alle drei Knoepfe gleich - gruen heisst ueberall "an". Die
gegenlaeufige Zuordnung von heute Vormittag ist damit zurueckgedreht; der
Warnhinweis "CB ist bewusst invers" ist aus Markup, CSS und JS entfernt, sonst
haette er kuenftige Leser in die falsche Richtung geschickt.
⚠ Die Tooltips nennen die Farbe jetzt ausdruecklich ("AN (gruen)" / "AUS
(rot)"), damit der Zustand auch ohne Farbwahrnehmung eindeutig ist.

Am ausgelieferten HTML/CSS geprueft: TAG P/L enthaelt btn-cb, Balance enthaelt
btn-at und btn-trail und NICHT btn-cb, 0 doppelte IDs, .cb-dot.aktiv ist gruen.
Pipeline A-G gruen, 97 Tests, 14 render*-Funktionen, deployt.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 10:58:26 +02:00
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 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 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 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 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 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 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 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 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 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>
2026-08-19 19:22:56 +02:00
Axel HocksandClaude Opus 5 d9ff48b5be Knopf 'STOPP' in 'CIRCUIT BREAKER' umbenannt (v=179)
Nur Beschriftung: Button-Label, Toast-Text und die beiden Tooltip-Varianten.
Funktion, Endpunkt und Persistenz unveraendert. Dazu eine CSS-Zeile, damit das
laengere Label auf schmalen Displays umbricht statt ueberzulaufen -- sechs
Knoepfe teilen sich die Leistenbreite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 17:07:49 +02:00
Axel HocksandClaude Opus 5 af5190cf9e Raum je Richtung auf die Order-Knoepfe (v=175)
Gemessen auf 27 eigenen manuellen Trades: Raum < 0,6xATR zum naechsten Level in
Trade-Richtung = 79 % Trefferquote und trotzdem -7,57 bzw. -11,51 EUR/Lot. Das
ist die Klein-Close-Falle (Gewinn am Level gedeckelt, Verlust laeuft bis zum
Stop), ueber 80k Bars als PF 0,42/0,66 belegt.

Die Zahl stand nur in Gate 3b der M15-Karte -- seit dem Entfernen des
Entry-Dialogs am 11.08. war sie im Moment des Klicks unsichtbar. Jetzt als
zweite Zeile auf dem LONG-/SHORT-Knopf, bernstein unter dem Gate.

REINE ANZEIGE: kein Block, keine Sperre, kein Dialog -- Uebersteuerungen laufen
gemessen 68 % WR.

Kein Backend, kein Neustart: die Daten lagen bereits im Snapshot
(m15_setup.motor.raum) und werden NICHT neu gerechnet. Bewusst kein eigener
Layout-Block, weil #actions ein flex ohne wrap ist.

Verifiziert: node --check als Modul, check_nfalle sauber, beide IDs im
ausgelieferten HTML, live LONG 0,07xATR (unter Gate) / SHORT 1,49xATR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 13:08:31 +02:00
Axel HocksandClaude Opus 5 5b01610634 Einsatz-Feld: feste Breiten durch mitwachsende ersetzt (v=174)
User: das Einsatz-Feld ist nicht breit genug.

Die Trade-Leiste hatte width:88px fest, die Order-Leiste 74px. Der Einsatz zeigt
Betraege wie '712.84 EUR' -- bei fett und 0,94rem passt das in 88px nicht (das
sind ~9,7 Zeichen Platz bei 10 benoetigten).

Jetzt in ch statt px: 1ch ist die Breite einer Ziffer und haengt damit an der
Schriftgroesse -- skaliert also mit der fluiden Wurzel mit, was ein px-Wert
nicht tut. Anzeige-Werte bekommen width:auto + min-width:7.5ch und duerfen bei
laengeren Betraegen darueber hinaus wachsen statt abzuschneiden; Eingabefelder
bleiben bei 8ch als feste, aber mitskalierende Basis. Order-Leiste 74px -> 7ch.

Das war dieselbe Klasse wie die px-Abstaende von heute frueh: eine feste
Pixelzahl in einem Layout, dessen Schrift skaliert.

Verifiziert: min-width:7.5ch im ausgelieferten CSS, HTML zieht v=174.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 00:44:44 +02:00
Axel HocksandClaude Opus 5 3b5706c6bb Picos Formular-Hoehe zurueckgenommen (v=172)
User: die Textfelder des laufenden Trades sind viel zu hoch.

ZWEI Pico-Regeln waren schuld:
 (1) input{height:calc(1rem*line-height + spacing-vertical*2 + border*2)} --
     mit --pico-form-element-spacing-vertical:0.75rem sind das ~3rem = 48px.
     Unsere .tb-field-Regel setzt nur padding, KEINE Hoehe -- also gewann Pico.
 (2) input{margin-bottom:var(--pico-spacing)} -- nochmal 0,7rem darunter.

height:auto laesst wieder das eigene Padding die Hoehe bestimmen; margin-bottom:0
entfernt den Formular-Abstand. Checkbox/Radio/Range ausgenommen (eigene
Groessenlogik).

Rechnerisch am Handy (Wurzel 16px): vorher ~50px, jetzt ~30px.

Das ist die erste Stelle, an der Pico sichtbar durchgeschlagen hat -- genau der
Fall, den ich beim Einbau angekuendigt habe. Die Bruecke im Kopf von style.css
ist der Ort fuer weitere solche Ruecknahmen.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 00:41:48 +02:00
Axel HocksandClaude Opus 5 572c6c0253 PicoCSS v2.1.1 als Basisschicht eingebunden (v=171)
User-Wunsch "schreibe auf pico css um".

⚠ EHRLICH ZUM UMFANG: Pico ist KLASSENLOS -- es stylt semantisches HTML
(button, input, article, nav), nicht die ~60 Trading-Klassen (.card, .tb-field,
.m15-item, .px ...). Ein echtes "Umschreiben" ist damit gar nicht moeglich; was
geht, ist eine SCHICHT: Pico liefert Typografie, Formulare, Buttons und
Fokus-Ringe, style.css steht DANACH und gewinnt bei Konflikten.

LOKAL eingebunden (83 KB), kein CDN: die PWA laeuft ueber WireGuard und muss
offline funktionieren; ein CDN-Link waere zudem CSP-blockiert.

Damit Pico das Dashboard nicht in sein Standard-Blau umfaerbt, sind seine
Variablen auf die BESTEHENDE Palette gemappt (--pico-* -> --bg/--card/--accent
...). Zwei Pico-Defaults bewusst ausgeschaltet:
 - --pico-font-size: 100% -- Picos eigene fluide Schrift wuerde sich mit
   html{font-size:clamp(...)} vom 13.08. MULTIPLIZIEREN.
 - Block-Abstaende auf 0,7rem gezaehmt; die Karten bringen ihre eigenen mit.
Dazu drei Ruecknahmen, wo Picos Container-Regeln mit dem Grid kollidieren.

Verifiziert am laufenden Server: pico.min.css HTTP 200 (83.319 Bytes),
style.css 200, data-theme=dark im ausgelieferten HTML, und die Reihenfolge
stimmt (Pico Zeile 14, style.css Zeile 15).

Nebenbefund: das CDN antwortete sofort -- das Netz ist in Ordnung, nur Gitea
ist weiterhin nicht erreichbar.

Backups: index.html.bak-2026-08-19-pico, style.css.bak-2026-08-19

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 00:36:11 +02:00
Axel HocksandClaude Opus 5 d03d6a1a50 Dashboard wirklich responsive: Hauptgitter selbstregelnd, Abstaende in rem (v=170)
User: am Handy passen sich die Groessen nicht an.

HAUPTBEFUND: main hatte FESTE 2 Spalten und brach erst bei <=360px um --
moderne Handys haben 390-430 CSS-Pixel. Auf dem Geraet standen also zwei
Spalten a ~190px nebeneinander. Der Breakpoint war schlicht zu schmal geraten.

Jetzt selbstregelnd, ohne geratenen Breakpoint:
  main{grid-template-columns:repeat(auto-fit,minmax(320px,1fr))}
  360/390/430px -> 1 Spalte · 768 -> 2 · 1024 -> 3 · 1440 -> 4

ZWEITER BEFUND: 138 Abstaende in px, 0 in rem -- die Schrift skalierte seit dem
13.08., die Polster nicht. Damit sass der Text am Handy eng und auf dem Desktop
verloren. Jetzt 122 von 138 auf rem umgestellt (Basis 18px, passend zur fluiden
Wurzel); die verbleibenden 29 sind Werte < 4px, wo Rundung mehr schadet als
nuetzt. Rahmen, Radien und Punktgroessen bleiben BEWUSST px -- die sollen nicht
mitwachsen.

Auch .trades (5 feste Spalten, sprengte 390px) auf auto-fit umgestellt.

Ausgeliefert verifiziert: auto-fit im CSS, 122 rem-Abstaende, HTML zieht v=170.
Backup web/style.css.bak-2026-08-19.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-19 00:32:07 +02:00
Axel HocksandClaude Opus 5 95521d041c Schrift eine Stufe kleiner: -2px an der fluiden Wurzel (v=168)
User: "verkleinere alle Schriftarten um 1em".

Woertlich waere 1em = 100 % der Schriftgroesse, also null. Gemeint ist eine
Stufe -- genommen wurden -2px, exakt der Schritt, in dem die Groesse am 24.07.
zweimal HOCHgesetzt wurde. Das Handy landet damit auf dem Zwischenstand von
damals (~16px statt ~18px).

  html { font-size: clamp(15px, 14px + 0.5vw, 22px); }   (war 17/16/24)

  Fenster    v=167     v=168
   390px    17,95px   15,95px
   768px    19,84px   17,84px
  1440px    23,20px   21,20px
  ab 1600   24,00px   22,00px

Das war eine EINZIGE Zeile. Die 96 rem-Werte bleiben unberuehrt, alle
Groessenverhaeltnisse untereinander auch -- genau dafuer wurde heute frueh
umgestellt. Der Bump am 24.07. musste noch 96 Einzelwerte anfassen und
uebersah dabei drei Shorthands.

Ausgeliefert verifiziert: Wurzel = clamp(15px, 14px + 0.5vw, 22px),
93 rem-Werte, 0 px-Schriftgroessen, HTML zieht v=168, Klammern ausgeglichen.

Zurueck auf die 18er-Basis: clamp(17px, 16px + 0.5vw, 24px) -- eine Stufe
entspricht 2px in Minimum und Steigungs-Basis, der Deckel wandert mit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 11:20:18 +02:00
Axel HocksandClaude Opus 5 01916134be Schrift skaliert mit dem Fenster: 96 px-Werte -> rem + fluide Wurzel (v=167)
User-Wunsch: "Schriftarten im Dashboard auf em einstellen, damit auf jedem
Geraet oder je nach Fenstergroesse die Schriftgroesse automatisch angepasst
wird."

Umgesetzt mit rem + fluider Wurzel, NICHT mit em. Der Wunsch war richtig,
die genannte Einheit nicht: `em` ist relativ zum ELTERNelement und reagiert
auf die Fenstergroesse gar nicht -- verschachtelt multipliziert es sich sogar
(h2 mit 1,2em in einer Karte mit 1,1em landet bei 1,32x).

  html { font-size: clamp(17px, 16px + 0.5vw, 24px); }

  390px Handy -> 17,95px  (bisher 18,00 -- bewusst kein Rueckschritt)
  768px       -> 19,84px
  1440px      -> 23,20px
  ab 1600px   -> 24,00px (Deckel)

Der Anker ist so gesetzt, dass am Handy NICHTS kleiner wird -- der User hat
die Groesse am 24.07. zweimal von Hand hochgesetzt; eine Responsive-Umstellung,
die sie wieder eindampft, waere eine stille Ruecknahme seiner Entscheidung.

Verifiziert statt behauptet:
  - alle 96 Deklarationen gegen die 18px-Referenz zurueckgerechnet,
    groesster Fehler 0,0008 px
  - 93 font-size + 3 font:<weight> Npx/...-Shorthand (.ms-chip/.ms-bos-lbl/
    .sqm-badge -- die waren beim Bump am 24.07. zuerst uebersehen worden)
  - ausgeliefert: 0 px-Schriftgroessen, fluide Wurzel da, HTML zieht v=167

Zwei Vorbedingungen geprueft, nicht angenommen:
  - viewport-Meta ist gesetzt (sonst wuerde vw am Handy ~980px messen)
  - beide Media-Queries stehen in px, verschieben sich also nicht mit der
    Schrift (die klassische em-Falle bei Breakpoints)

Abstaende bleiben in px -- sie mitzuskalieren waere ein weit groesserer
Eingriff mit Layout-Risiko; die Anfrage betraf die Schrift.

Groesse global aendern = jetzt EINE Zeile statt 96 Einzelwerten.
Zurueck: web/style.css.bak-2026-08-13

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-13 11:12:13 +02:00
Axel HocksandClaude Opus 5 44955bf70a M15-Karte "Setup-Bereitschaft" gebaut - Ersatz der Gesamtempfehlung (v=153)
Nach drei negativen M15-Messungen (Squeeze-Einstieg, VWAP-Baender, Exit-ATR)
steht fest: auf M15 traegt keine Richtungsquelle. Gebaut ist deshalb bewusst
KEINE Empfehlung, sondern eine sequenzielle Gate-Kette:

  [1 HTF-BIAS M30/H1] -> [2 KOSTEN Spread/ATR_M15] -> [3 LEVEL & KEGEL]
  -> Order AM LEVEL

Der Unterschied zur alten Karte ist grundsaetzlich: dort wurden Stimmen zu einem
Bias VERRECHNET (gemessen 48-51 % Treffer), hier muss jedes Gate EINZELN
passieren. Ein gefallenes Gate laesst sich nicht durch ein anderes ausgleichen.

Nur belegte Bausteine: HTF-Trend (einziger robuster Filter, Edge x2), Kosten
(M15 gemessen 0,104 gegen M5 0,193), naechstes stehendes Level + P(break),
Kegel (out-of-sample kalibriert, 80-%-Band trifft 77 %), Veto (-6,60 EUR/Lot).

Status-Banner: SETUP BEREIT / WARTEN AUF LEVEL / KEIN TRADE. Es bestaetigt
ausdruecklich auch das NICHT-Handeln - die gemessene Kern-Leckage sind
diskretionaere Abweichungen.

Die Order-Buttons werden BEWUSST NICHT gesperrt (gegen den Vorschlag
"ausgrauen"): hartes Blockieren wurde im Projekt verworfen, und
User-Uebersteuerungen liefen gemessen 68 % WR.

Umsetzung: engine._m15_setup() setzt nur zusammen, was der Snapshot ohnehin
erzeugt. Neu gerechnet wird allein das M15-Kosten-Verhaeltnis und P(break) fuer
das naechste Level. Dafuer veroeffentlicht wave_rec jetzt tf_atr (ADDITIV) - der
ATR je Zeitebene wurde im Turn-Fetch laengst berechnet, war aber nirgends
abrufbar.

P(break)-Merkmale bleiben auf M5 (Modell ist darauf trainiert, Fix 2026-07-13).

Mit 5 Szenarien getestet (alles passt, Bias uneinig, Kosten teuer, Level zu
weit, Kaltstart ohne ATR_M15 -> kein Absturz), live verifiziert ueber
deploy.py --feld m15_setup.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 15:18:29 +02:00
Axel HocksandClaude Opus 5 30c8616280 Gesamtempfehlung entfernt (User-Entscheidung 2026-08-08)
"Funktioniert so leider nicht, entferne es komplett - wir bauen etwas Neues."

Entfernt: Headline, Konfidenz-Ring, Bias-Nadel, Modul-Chips, Konsens-Zeile,
Block-Gruende. Dazu renderVerdict(), die zugehoerigen 24 CSS-Regeln,
docs/gesamtempfehlung.md und die Snapshot-Felder `verdict` + `block_mix`.

Die Aggregation war reine ANZEIGE - vor dem Loeschen belegt: die Order-Logik
haengt an `wave_signal` bzw. `checklist`, nicht am Verdict (Blinken app.js:821,
Order-Dialog 1312/1366/1391). Orders, Alarme und das gemessene Veto
(-6,60 EUR/Lot) sind unberuehrt.

BEHALTEN (sassen nur in derselben Karte, je eigene Beleglage, User-Entscheidung):
  Zeitebenen-Ampel  #wave-turns  - war aus der Welle-Karte dorthin verschoben
  Erwartete Spanne  #kx-cone     - out-of-sample kalibriert, trifft real ~77 %
  Selbstkalibrierung #kx-selfcal - misst das Wellen-Signal, das bleibt
  HL-Kontext        #hl-note     - lief in renderVerdict mit, schreibt aber in
                                   die Meldungen-Karte
Sie stehen jetzt in der neuen, schlanken Karte "Marktkontext" (#card-kontext).
IDs von vd- auf kx- umbenannt, damit keine tote Nomenklatur zurueckbleibt.

verdict_votes wird WEITER geloggt (User-Entscheidung): `_verdict()` bleibt
bestehen und laeuft 1x/min fuer die Telemetrie sowie fuer den optionalen
MQL5-Konsens-Pfeil. Aus dem 1-s-Snapshot ist es raus - dort waere es Arbeit fuer
eine Anzeige, die es nicht mehr gibt.

Verifiziert: node --check gruen, 34 Tests gruen, 0 verwaiste $("id")-Zugriffe
(die zwei Treffer 'neu'/'x' stehen in Kommentaren), CSS-Klammern ausgeglichen
(287/287), @media und @keyframes intakt. Zeile 1572 (_SQM_VERDICT[d.verdict])
ist der SQUEEZE-MONITOR-Verdict und bleibt.

Asset-Version v=152.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-08 14:12:27 +02:00
Axel HocksandClaude Opus 5 59e9498237 G/V-Lag: 1-s-Fallback + ehrlicher Verbindungspunkt (v=151)
Zuerst gemessen, dann gedreht - und das Backend war NICHT das Problem:
  /api/snapshot   75 Abrufe in 20 s -> 21 verschiedene ts = ~1/s
  WebSocket-Push  direkt am Socket gemessen: Median 1,04 s (min 1,00 max 1,06)
  G/V-Aenderungen Ø 1,44 s - das ist der Markt, keine Verzoegerung

Die ganze Server-Kette liefert bereits 1 s. Der Lag entsteht erst am Handy:
bricht der WebSocket STILL weg (WireGuard-Aussetzer, App-Wechsel), traegt nur
noch der REST-Poll - und der stand auf 4 s.

POLL_MS 4000 -> 1000, aber mit Sperre: solange der WS liefert (lastWsMs,
Fenster WS_FRISCH_MS=2200 ms), ueberspringt der Poll den Abruf. Kein
zusaetzlicher Verkehr im Normalfall.

Denkfehler, den erst die Simulation zeigte: der erste Entwurf las die
WS-Frische aus lastRecvMs (jede Quelle) - damit drosselte sich der Poll SELBST
und kam bei totem WS nur auf 2,9 s statt 1 s. Jetzt zwei getrennte Uhren.

Simuliert: WS gesund -> 0 Zusatz-Abrufe, max. Alter 0,9 s. WS tot -> 1/s, max.
Alter 0,9 s. WS traege (5 s) -> max. 2,9 s. Vorher bei totem WS: 4,0 s.

Der Verbindungspunkt log: er wurde nur bei sock.onclose auf "off" gesetzt, aber
genau der Fall, der den Lag erzeugt, feuert KEIN onclose - der Socket haengt
still, der Punkt blieb gruen. Neu .dot.stale (bernstein, pulsierend) ab 3,5 s
ohne frischen Snapshot: gemessen wird, was ANKOMMT, nicht was der Socket ueber
sich behauptet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 14:20:42 +02:00
Axel HocksandClaude Opus 5 caa937f87d Gesamtempfehlung: nur noch Module mit Stimmrecht · Tooltips ueberall (v=147)
· Modul-Chips: neues `used`-Flag in _verdict.add(). used=False = dauerhaft
  entmachtet (Elliott, Orderbuch — beide heute gemessen ohne Inhalt), das
  Frontend filtert sie aus. ⚠ Sie bleiben im Snapshot und in verdict_votes:
  log_verdict_votes speist daraus die Telemetrie und die 25.000-Verdict-Messung
  braucht die Reihe weiter. Ausgeblendet wird die Anzeige, nicht die Messung.
  Module mit weight=0 aus SITUATIVER Stille (Welle bei WARTEN, Squeeze ohne
  Ausbruch) bleiben sichtbar.
· #vd-note (Muenzwurf-Hinweistext) entfernt, samt CSS. Die Aussage steht
  weiter im Karten-Tooltip.
· Tooltips auf allen Dashboard-Anzeigen (59 title-Attribute): Karten,
  Header-Boxen, Trade-Leiste, Anzeige-Elemente. Wo eine Messung existiert,
  steht sie drin. Gesetzt ueber set_tooltips.py — idempotent, ergaenzt nur
  fehlende title=.

Verifiziert: keine Anzeige mehr ohne Tooltip, keine doppelten IDs, Tag-Balance
ok, v=147 ausgeliefert, Elliott/Orderbuch used=False, eine Instanz auf 8000.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 23:46:31 +02:00
Axel HocksandClaude Opus 5 2cdd1ba0e8 Hyperliquid geprueft: Orderbuch-Stimme raus, Funding gemessen (traegt nicht),
Kontext in die Meldungen (v=145)

Direkt gegen die HL-API geprueft statt aus dem Code geschlossen.

ANGEBOT: 4 Oel-Maerkte (2 liquide: xyz:CL OI 3,07 Mio, xyz:BRENTOIL 2,25 Mio),
je Markt mark/oracle/funding/open_interest/day_volume + l2Book (20 Level je
Seite). Historie: fundingHistory 5.095 Stundenwerte ueber 7 Monate inkl.
premium. Open Interest hat KEINE Historie -> waere sammelpflichtig.

Netz-Frage geklaert: config sagt testnet (leeres Buch, 0 Bids/0 Asks), aber es
sind zwei Schalter — [hyperliquid] network steuert das Handeln (aus),
[sim] price_network die Daten (mainnet, live bestaetigt).

(1) Mehr Orderbuch-Daten: NEIN. Zweimal unabhaengig gemessen — bookflow_report
    0,2-1,0 bp gegen eine ~3-bp-Schwelle und KIPPT; Lead-Lag: Pepperstone
    fuehrt, HL trifft nach 6 s zu 51 %.
(2) Modul "Orderbuch" Gewicht 0,5 -> 0. Ueber 2.688 Episoden beidhaelftig
    negativ (-0,054/-0,066, 49 % Treffer). Chip bleibt.
(3) analyze_hl_funding.py: Funding/Premium gegen den CFD, 2 Haelften.
    ⚠ Der erste Lauf meldete mehrere "robuste" Buckets und war FALSCH —
    ueberlappende Forward-Fenster (aus n=506 werden ~21 unabhaengige Faelle)
    und global gebildete Quintile (Bucket mit der Zeit konfundiert). Dass
    Funding- und Premium-Tabelle fast identisch waren, war der dritte Hinweis:
    HL rechnet das Funding aus dem Premium. Entueberlappt haelt kein Bucket.
(4) hl_ctx in den Meldungen (#hl-note) als reine Anzeige.
    ⚠ Zwei Bau-Fallen behoben: der Aufruf erbte den 2-s-Timeout der Waende und
    lief still ins Leere (braucht real 7,2 s), und er haette den Trend-Loop
    blockiert -> Daemon-Thread wie beim Wirtschaftskalender.

Live verifiziert: hl_ctx befuellt, Orderbuch weight=0 bei erhaltenem Chip,
v=145 ausgeliefert, eine Instanz auf Port 8000.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 23:38:01 +02:00
Axel HocksandClaude Opus 5 874ee16e00 Gesamtempfehlung: Selbst-Kalibrierung, voller Ausrichtungs-Split, Block-Gruende,
Elliott entmachtet (v=144)

Vier Verbesserungen, alle aus dem Gemessenen abgeleitet — kein neues Signal.
Ausgangspunkt: die Karte hat genau eine belegte Funktion, das Veto; als Prognose
ist sie ein Muenzwurf (48-51 % ueber 1.071 Episoden).

(1) SELBST-KALIBRIERUNG. Neue Tabelle rec_outcomes: eine Zeile je EPISODE
    (Richtungswechsel, nicht je Minute), Auswertung ~alle 5 min gegen candles_m1
    nach 30/60 min, Snapshot rec_track, Zeile #vd-selfcal. Gegen 50 % zu lesen.
    Warum der groesste Hebel: die Qualitaet war bis heute unsichtbar und musste
    auf Nachfrage rueckwirkend gemessen werden. Dasselbe Muster
    (pbreak_predictions) hat den Ausfall des P(break)-Modells LIVE aufgedeckt.
    Mit 4 Szenarien getestet (tests_rec_outcomes.py). Zwei Fehlschlaege dabei
    waren Testfehler, keine Code-Fehler — dokumentiert.

(2) alignment_stats auf die VOLLE Historie (1.216 statt 40 Trades) und
    zusaetzlich je Lot. Absolute Euro-Vergleiche sind bei wechselnder
    Positionsgroesse ungueltig (Lehre 04.08.). Damit steht die einzige
    beidhaelftig robuste Aussage der Karte auf ihrer vollen Stichprobe.

(3) Block-Gruende sichtbar (block_mix -> #vd-blocks): "heute X % ohne Block ·
    entry_room … · min_conf …". Bisher nur per DB-Abfrage zu beantworten.

(4) ELLIOTT: Verdict-Gewicht 1,0 -> 0. Gemessen ueber 15.544 Zeilen hatte es mit
    1.384 Episoden die groesste Stichprobe der Tabelle und ist darin flach
    (-0,075/+0,032, 50 % Treffer) — bei 25,9 % Einfluss auf die Nadel, weil es
    in nur 1 % der Zeilen schweigt. Chip bleibt, Stimme entfaellt.
    ⚠ Folge: die Nadel schlaegt staerker aus (real +0,33 -> +1,00).

⚠ Namenskollision beim Bau gefunden und behoben: die neue Klasse hiess zuerst
.vd-track — so heisst bereits die Schiene der Bias-Nadel; sie waere
ueberschrieben worden. Jetzt .vd-selfcal.

Live verifiziert: alignment je Lot, block_mix (93 von 1381 ohne Block),
rec_outcomes angelegt, Elliott weight=0 bei erhaltenem Chip, v=144 ausgeliefert,
eine Instanz auf Port 8000.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 23:21:52 +02:00
Axel HocksandClaude Opus 5 45bfc87153 Squeeze auf 9 Instrumenten · Momentum neu gemessen · Fill-Annahme korrigiert · UI
Drei Messungen und eine UI-Aenderung, ausgeloest von der Frage, ob das Konzept
zu ueberdenken ist.

1) SQUEEZE AUF ANDEREN INSTRUMENTEN (backtest_squeeze_multi.py): 7 von 9 halten
   alle vier Bedingungen, alle nachbar-robust. Die zwei Durchfaller (Gasoline,
   USDX) sind exakt die mit Spread >= ATR — der Test scheitert, wo er muss.
   ⚠ 7 sind nicht 7 unabhaengige Tests (Crude/Brent, Gold/Silber, NAS/GER40
   korrelieren), und die Kompression traegt weniger als der Ausbruch selbst
   (Kontrolle "beliebige Box" ist ueberall positiv).

2) MOMENTUM (backtest_momentum_v2.py): bleibt verworfen. Mit Level-Order sah es
   nach +0,4 aus — das war Look-ahead. Eine liegende Order fuellt bei der ersten
   BERUEHRUNG, nicht erst wenn der Bar jenseits des Levels SCHLIESST. Ehrlich
   gerechnet: -0,04..-0,09 in H1. Struktureller Grund: das Momentum-Level wandert
   jede Bar mit C[i-N] und ist damit kein Ort, an dem eine Order liegen bleibt.

3) FILL-ANNAHME (backtest_squeeze_touchfill.py): dieselbe Frage fuer den Squeeze.
   Er haelt (+0,124/+0,292, PF 1,24/1,64) und die Umstellung auf ruhende Orders
   bleibt richtig (Market -0,158/-0,006). ABER die heute zitierten +0,456/+0,611
   sind als Live-Erwartung ~0,32 R zu hoch. Die Beruehrungs-Variante trifft fast
   genau das original validierte Band +0,14..+0,23.
   ⚠ OFFEN: derselbe Test fehlt fuer den SIG-Pending-Pfad, der seit 05.08. live
   ist — und dort ist ein schlechteres Ergebnis zu erwarten, weil das _pend-Level
   wandert statt stillzustehen.

4) UI (v=143): fester Vorbehalt unter der Headline und "Score" statt nackter
   Prozentzahl am Ring. Statisches Markup, kein JS.

Eigener Fehler dokumentiert: der erste Momentum-Entwurf pruefte nicht, ob das
Level als Stop-Order auf der richtigen Marktseite liegt, und lieferte ØR +2,2 —
unmoeglich, und genau daran erkennbar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-06 22:14:02 +02:00
Axel HocksandClaude Opus 5 a1a5d560b9 Charts-Tab komplett entfernt (User-Vorgabe)
Entfernt: Tab-Button, #view-charts, der gesamte app.js-Chart-Block
(Kartenaufbau, renderChart, loadCharts, 20-s-Refresh, Resize-Handler), die
Chart-CSS-Regeln, die vendorte Bibliothek
web/lightweight-charts.standalone.production.js (164 KB) samt script-Tag - und
die Backend-Kette dahinter: /api/bars und engine.get_bars (60 Zeilen). Beide
existierten ausschliesslich fuer dieses Tab; geprueft, dass es keinen anderen
Aufrufer gibt.

Nicht betroffen (sahen nur aehnlich aus): die Chartmuster-Karte (Verdict-Gewicht
0,25, im Tab "SIG Live"), der MQL5-Indikator samt sr_levels.csv-Export (eigener
Pfad ueber _write_levels_file) und die Analyse-Module structure/patterns/cone -
die speisen den Snapshot, nicht das Chart. Der MT5-Chart bleibt voll bedient.

Ein veralteter Kommentar in trader.py, der auf engine.get_bars verwies, wurde
auf core/gaps.py umgehaengt.

Verifiziert am laufenden Server: /api/bars -> 404, Bibliothek -> 404,
data-view="charts" und id="view-charts" nicht mehr im ausgelieferten HTML,
6 Tabs zu 6 Views paarig, keine verwaisten JS-Referenzen, Klammern-Balance ok,
keine Fehler im Log. v=142.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 23:27:24 +02:00
Axel HocksandClaude Opus 5 a13adb891b Zwei neue Tabs: "SIG Live" und "SIG Anzeige", Module nach WIRKUNG sortiert
User-Vorgabe. Sortiert wird nicht nach Thema, sondern danach, ob ein Modul die
Empfehlung bewegt - und das ist am Code pruefbar: engine._verdict ruft
add(name, vote, gewicht, ...); Gewicht > 0 heisst Einfluss auf die Bias-Nadel.

  SIG Live    <- KI-Copilot (Gewicht 1,0) · Chartmuster (_PAT_W = 0,25)
  SIG Anzeige <- Marktstruktur · Kerzen-Anatomie (gemessen ohne Einfluss)

Chartmuster landet damit bewusst in "Live", obwohl die Klasse als Signal
verworfen wurde - seit 01.08. hat sie 5 % Stimmanteil. "Gewicht" heisst nicht
"belegt"; genau deshalb ist die Trennung nach Wirkung sinnvoll: sie zeigt, was
die Empfehlung TATSAECHLICH bewegt, unabhaengig von der Beleglage.

Auf dem Dashboard bleiben Trade-Leiste, Gesamtempfehlung, Meldungen und
Statistik (live). Die Meldungen-Karte enthaelt zwar einflussreiche Teile
(Squeeze-Stimme, S/R-Close-Hinweis, Flip-Close), ist aber der Live-Meldungsstrom
zum laufenden Trade und gehoert dorthin, wo gehandelt wird.

Reiner Markup-Umzug: showView bildet data-view="siglive" auf #view-siglive ab,
keine JS-Aenderung noetig. CSS-Regel analog zum Statistik-Tab, weil beide Views
ausserhalb des <main>-Grids liegen. Die verschobenen Bloecke wurden aus git
zurueckgeholt statt nachgetippt.

Verifiziert am ausgelieferten HTML: 7 Tabs, 7 Views, keine doppelten IDs, keine
verwaisten JS-Referenzen, section-Tags balanciert. v=141.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 13:27:07 +02:00
Axel HocksandClaude Opus 5 e55b866f29 Kachel "Erwartete Spanne" entfernt, Kernwerte komprimiert in die Gesamtempfehlung
User-Vorgabe. #card-cone/#cone-list raus; neu die einzeilige #vd-cone unter der
Bias-Nadel: "erwartete Spanne · 30' 75,99-76,77 · 60' ... · trifft 77 %".
Gezeigt wird nur noch das 80-%-Band je Horizont; das enge 50-%-Band und der
Erklaer-Absatz stecken im title.

Platzierung und Farbe sind Absicht: die Zeile steht UNTER der Nadel und ist
neutral/randlos - sie zeigt Streuung, nicht Richtung, und darf optisch nicht mit
dem Bias konkurrieren. Beschriftet bleibt sie mit der REAL gemessenen Abdeckung
(~77 %), nicht mit dem Nennwert 80 %.

Backend unveraendert aktiv (core/cone.py, Snapshot cone, MT5-Export CN;...).
Verifiziert am ausgelieferten HTML: card-cone weg, vd-cone da, keine verwaisten
JS-Referenzen, Klammern-Balance ok. v=140.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 13:17:18 +02:00
Axel HocksandClaude Opus 5 43b7756df3 Manuelle Trades, Letzte Trades und Kurslueken in den Statistik-Tab verschoben
User-Vorgabe: die drei sind Rueckschau, das Dashboard soll das
Handlungsrelevante zeigen. Reiner Umzug im Markup - keine Logik beruehrt.
Die Karten werden weiterhin von render() aus dem Snapshot gefuettert und
haengen NICHT an loadStats(); ein ausgeblendeter View ist nur display:none,
die Elemente bleiben im DOM.

Noetig war eine CSS-Regel: #view-stats > .card{margin:11px 10px}. Das
Dashboard ist ein <main>-GRID mit eigenem Padding, #view-stats eine schlichte
<section> - ohne die Regel klebten die Karten randlos aneinander und
.card.wide{grid-column:1/-1} liefe ins Leere.

Verifiziert am ausgelieferten HTML (alle drei nach id="view-stats",
card-stats-live bleibt im Dashboard), keine doppelten IDs, Tag-Balance
geprueft. v=138.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 09:10:25 +02:00
Axel HocksandClaude Opus 5 cc4f1a0863 Provider-Failover bei hartem Fehlschlag + Einsatz-Prozentfeld im Dashboard
1) LLM-Failover (core/agent.py): ein hart gescheiterter Provider wird zeitweise
uebersprungen, analyze() nimmt den naechsten aus der Kette. Hart = 401/402/403/
404 (Key/Guthaben/Modell) -> 30 min, nicht erreichbar -> 5 min. Timeout/429/5xx
loesen BEWUSST keinen Wechsel aus (voruebergehend; sonst kostet jede Lastspitze
die volle Timeout-Summe aller Anbieter). Neu im Snapshot: agent.provider_dead
mit Restminuten - der DeepSeek-Ausfall stand vorher nur im Log und blieb
deshalb 18 h unbemerkt. 9 Szenarien getestet.

2) Einsatz-Prozentfeld (web, v=137): margin_buffer_pct hatte bisher keine UI.
Neues Feld "Einsatz %" neben "Einsatz EUR", POST /api/marginpct ->
engine.set_margin_pct -> config.set_margin_buffer, Snapshot margin_pct,
neustart-fest. Der feste EUR-Betrag hat Vorrang; das Prozentfeld wird dann
ausgegraut, damit nicht unklar bleibt was gilt. Auf 1-99 % geklemmt.
Ende-zu-Ende getestet (50, 150->99, 0 und -5 abgelehnt, 95, persistiert).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-05 08:38:17 +02:00
Axel HocksandClaude Opus 5 6af4c868bc Feste Einsatz-Margin (UI-Feld) + lokale Sprachausgabe via Piper
EINSATZ-FELD (User-Wunsch): Laufzeitwert MANUAL_MARGIN in core/config.py
(set/get_manual_margin, Muster wie set_margin_buffer). 0 = automatisch wie bisher
(margin_buffer_pct % der freien Margin), > 0 = Position wird auf genau diesen
Margin-Einsatz gerechnet.
- calc_lots setzt es um und DECKELT auf freie Margin x Buffer; ein zu hoher
  Wunschwert wird begrenzt und geloggt statt an den Broker durchgereicht. Reicht
  der Betrag nicht fuers Mindestlot -> 0.0 + Warnung, Trade sauber abgelehnt.
- Vorrang vor dem Risiko-Modus in trader._send_locked: eine ausdrueckliche
  Groessenvorgabe schlaegt die Rechenregel.
- Wirkt auf ALLE neuen Positionen, auch die autonomen.
- UI-Feld "Einsatz" in der ORDER-Leiste (nicht in der Trade-Leiste: die ist nur
  bei offener Position sichtbar, der Einsatz muss vorher einstellbar sein),
  bernstein umrandet solange gesetzt. Enter blurrt nur, change sendet einmal.
- POST /api/manualmargin, Snapshot manual_margin, neustart-fest ueber
  runtime_state.json. Ende-zu-Ende getestet (250 -> Snapshot -> 0 -> persistiert).
- Lot-Logik isoliert geprueft: 200 EUR -> 0,58 Lots; 5000 EUR -> gedeckelt.

SPRACHAUSGABE: Piper lokal (tools/speak.py). Windows-TTS funktioniert zwar, aber
es ist KEINE deutsche Stimme installiert - weder SAPI5 noch OneCore (nur
David/Zira/Mark, en-US); deutscher Text kaeme mit englischer Aussprache.
Add-WindowsCapability scheitert ohne Adminrechte.
Piper gewaehlt: laeuft lokal (passt zum Rest - WireGuard-only, Secrets in der
ini, keine Cloud), kostet nichts, aus PowerShell/Python aufrufbar. Stimme
thorsten-medium (de_DE), Real-Time-Faktor 0,08 (4,3 s Audio in 0,36 s).

Das ZIP entpackt eine Ebene tiefer als erwartet (tools/piper/piper/piper.exe) -
speak.py SUCHT Binary und Modell statt Pfade fest zu verdrahten. Der erste
Entwurf scheiterte daran; der Fail-safe meldete die Pfade sauber statt stumm zu
bleiben. Drei Modi getestet (Argument, Pipe, --wav).

tools/piper/ ist gitignored (Binaries + 60-MB-Modell), speak.py versioniert.
v=136.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 17:31:58 +02:00
Axel HocksandClaude Opus 5 da7d8f5b90 Stufe 1: voller Entscheidungskontext beim Einstieg + Karte "Manuelle Trades"
Frage: kann der Bot aus den manuellen Trades lernen? Vorpruefung: noch NICHT.
1) Die entscheidenden Merkmale wurden nie gespeichert - beim Einstieg nur 5
   Felder, davon ai_sentiment in 1,4 % und news_score in 34 % befuellt.
2) Das naive Lernziel ("wann steigt er ein") braucht unbeschriftete Negative;
   brauchbar ist nur "welche Einstiege liefen gut" (Labels ueber P&L).
3) Die scheinbaren Muster sind Einzeltage: Stunde 13:00 zeigt +478 EUR ueber
   n=69, davon +382 EUR (80 %) aus den fuenf Trades des 04.08.

Gebaut wurde Stufe 1 - reine Telemetrie, kein Verhalten:
- trades um 16 ctx_*-Spalten erweitert (DB-Backup .bak-2026-08-04, 1.148 Zeilen
  unveraendert): p_break_target/-stop, dist_res_atr/dist_sup_atr, structure,
  squeeze, htf_trend/h1_trend, spread_atr, session, block_reason, conf_pct,
  atr_m5, bias, cone_pos, hour
- log_trade_open haengt die Spalten dynamisch an und ignoriert unbekannte
  Schluessel -> aeltere DB ohne Migration laeuft weiter (fail-open)
- Kette: engine._run_analysis -> trader.set_open_context(ctx=) -> log_trade_open

Fallstrick beim Bau: wave_snap existiert in _run_analysis NICHT (nur in
snapshot()). Der erste Entwurf haette einen NameError erzeugt, den das umgebende
except still geschluckt haette - der Kontext waere dauerhaft leer geblieben ohne
dass es auffaellt. Jetzt self.wave.snapshot(); vd zusaetzlich per locals()-Guard.

Verifiziert auf einer DB-KOPIE: alle 16 Spalten korrekt geschrieben, unbekannter
Schluessel ignoriert, Basisfelder unberuehrt. Snapshot liefert manual_stats.

Dashboard-Karte "Manuelle Trades" (#card-manual, v=134): heute / 30 Tage /
gesamt / Bot-Vergleich plus Split mit vs ohne Signal-Deckung. Backend
history.manual_stats(30) mit ~120-s-Cache wie _alignment_cached. Bewusst neutral
gefaerbt und deskriptiv; eine Reifegrad-Zeile nennt die ctx-Abdeckung (heute
0 %), damit die Karte nicht ueberschaetzt wird.

Stufe 2 NICHT gebaut: erst bei ausreichender ctx-Abdeckung messen, was Gewinner
von Verlierern unterscheidet (Fit H1, validiert H2, AUC + Kalibrierung). Ergebnis
waere ein Hinweis im Order-Dialog, ausdruecklich KEIN Auto-Entry.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 16:34:26 +02:00
Axel HocksandClaude Opus 5 7427c36922 Hyperliquid-Kurs neben dem Broker-Kurs + G/V-Schaetzung bei geschlossenem Markt
User: "wenn Pepperstone closed ist trotzdem Kurs und Liquiditaet von
Hyperliquid einbinden" -> nachgeschaerft zu "blende den HL-Kurs NEBEN den
Pepperstone-Kurs ein" (ehrlicher als ein stiller Tausch) -> plus "bei
geschlossenem Markt auch den G/V mit HL berechnen".

Snapshot: hl_live {mid_mt5, hl_mid, basis, age_s, bid/ask, bid_sz/ask_sz,
imb5, trend, slope_per_h, vs_mt5} - IMMER befuellt. mid_mt5 = HL-Mid +
gemessene Basis, also direkt mit dem Broker-Kurs vergleichbar. Dazu
market_closed, tick_age_s, pnl_hl.
core/hl_walls.py liefert jetzt zusaetzlich hl_mid/mid_mt5/age_s.

Dashboard v=129: eigene Header-Box "HL" neben KURS mit Tooltip (Rohkurs,
Basis, Alter, Abweichung). Bei geschlossenem Markt: Label "KURS · ZU",
Session-Zeile "MARKT ZU", und das G/V wechselt auf die HL-Schaetzung, mit
"≈" markiert.

MT5 v1.34: HL;<mt5_aequiv>;<alter>;<bid>;<ask>;<U|D|-> -> bernsteinfarbenes
Label unter Kurs und G/V (InpShowHL/InpHLColor).

DREI SACKGASSEN dokumentiert, damit sie niemand wiederholt:
1) tick_local_ts ist die ABHOLZEIT, nicht das Tick-Alter.
2) tick_server_ts minus _broker_offset_s() ist ZIRKULAER - die
   Offset-Funktion leitet den Versatz selbst aus dem letzten Tick ab und
   misst bei geschlossenem Markt die Veraltung (-7,41 h statt +3 h); das
   Alter hebt sich auf (-347 s).
3) pnl / Kursbewegung als EUR-je-Punkt ergab 155 statt ~86, weil
   trader.pnl den Wochenend-Swap enthaelt.

Verwendet wird stattdessen: Markt zu = der Kurs hat sich seit 180 s nicht
BEWEGT (_last_bid/_last_bid_move_ts). Und der G/V nutzt die vorhandene,
korrekte trader.live_pnl(bid, ask) mit dem HL-Kurs +- halbem Spread.

Live verifiziert: market_closed=True nach 198 s, Broker 86.333 eingefroren,
HL 86.349 (7 s alt), Broker-P&L -15,02 -> HL-Schaetzung -14,37 EUR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-01 09:31:01 +02:00
Axel HocksandClaude Opus 5 d9cb54a52c C: Wahrscheinlichkeits-Kegel (kalibriert) + Config-Waechter im Reminder
C - core/cone.py + Kachel #card-cone + MT5 v1.31 (CN;<min>;<lo>;<hi>):
"Erwartete Spanne" statt "Kursvorhersage". Der User wollte eingezeichnete
Verlaufspfade; bewusst NICHT gebaut - sie suggerieren eine Praezision, die
es nicht gibt (Lehre aus analyze_verdict_calibration.py). Der Kegel sagt
wie WEIT der Kurs in 30/60/120 min plausibel laeuft, nicht wohin.

analyze_cone.py: r(h)=(C[i+h]-C[i])/ATR[i], Fit auf H1, Abdeckung gemessen
auf H2 (echtes out-of-sample):
  80%-Band -> 76,7 / 76,6 / 75,3 %
  90%-Band -> 87,5 / 87,2 / 86,5 %
Konsistent ~3-5 Pp ZU ENG. Das wird NICHT weggefittet - Kachel und Tooltip
nennen die REAL gemessene Abdeckung, nicht den Nennwert. Damit nach dem
P(break)-Modell die zweite kalibriert geprueft Komponente im Projekt.

Zentriert auf den aktuellen Kurs, KEINE Drift addiert (Median +-0,0..0,16
xATR = klein gegen die Bandbreite; eine Drift-Korrektur waere eine
Richtungsaussage und die ist nicht belegt). Farbe neutral grau, kein
gruen/rot. Kein Signal, kein Verdict-Gewicht.

MQL5 v1.31: zwei sich oeffnende gepunktete Pfade, verkettet 30->60->120.
Startpunkt aus der PX-Zeile - die setzt g_conePx jetzt auch, wenn
InpShowPrice aus ist (sonst verliert der Faecher seinen Anker).

Config-Waechter in measurement_reminder.py (Antwort auf "sollten wir alle
verworfenen Backtests woechentlich neu rechnen?"): NEIN - eine Woche sind
~2000 Bars, und 18 Ideen x 52 Wochen = 936 Tests/Jahr erzeugen bei 5 %
Fehlalarmquote ~47 falsche "funktioniert jetzt!" pro Jahr. Stattdessen
EREIGNIS-gesteuert: CONFIG_DEPS verankert 8 config-abhaengige Messungen an
den Wert, gegen den sie validiert wurden (entry_room_atr 0,6 /
sr_close_pbreak 0,55 / breakout_k 0,3 / risk_pct 0 / margin_buffer_pct 95 /
adverse_15min_atr 0,5 / auto_signal_min_conf 75 / dead_hours leer). Weicht
einer ab, meldet der Timer welche Messung veraltet ist. Numerischer
Vergleich, damit 0.60 == 0.6. Mit 5 synthetischen Szenarien getestet.

Erledigt ausgetragen: Chartmuster-Kontrolltest (30.07., Muster schlagen die
Kontrolle in beiden Haelften +0,022/+0,108).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 08:25:29 +02:00
Axel HocksandClaude Opus 5 03be3b8f5f D+A: Klimax-Fade verworfen, Kerzen-Anatomie-Kachel gebaut (reine Anzeige, v=123)
D - backtest_candle_fade.py: der Lead aus backtest_candles.py (Fade der
volumenstarken Klimax-Kerze) faellt im echten Trade-Sim durch. Live-Exit
(SL 2,0/Trail 1,5/BE 1,3/Time-Stop 120') + Echtkosten, mit KONTROLLGRUPPE
"Fade ohne Volumen-Filter" (die Lehre aus backtest_patterns.py).

  Kontrolle   -0,080 / -0,046
  Vol >= 2,0  -0,059 / +0,103
  Vol >= 2,5  +0,144 / -0,080
  Vol >= 3,0  +0,113 / -0,064

Benachbarte Schwellen exakt gegenlaeufig = Rauschmuster. Die einzige
beidseitig positive Zelle (Vol>=2,0 + Marubozu, +0,036/+0,043) hat n=91/118
bei 7 Varianten = Mehrfachvergleich-Artefakt. 18. verworfener Eingriff.

Wichtigste Lehre: Informations-Ueberschuss != handelbarer Edge. Dieselbe
2,0-Schwelle liefert im Forward-Fenster +0,12/+0,20 beim Fade, im echten
Trade -0,059/+0,103 - die Gegenbewegung ist diffus, der 2xATR-Stop wird
unterwegs getroffen (WR nur 35-40 %). Der Weg zum Ziel zaehlt.

A - core/candles.py + Kachel #card-candles (M5, ~20 s, unter mt5_lock):
Marubozu, Langer Koerper, Langer Docht oben/unten, Spinning Top, Doji,
Engulfing. Schwellen identisch zum Backtest.

Bewusste UI-Entscheidung: die Kachel ist NEUTRAL gefaerbt (keine gruen/rot-
Ampel) und nennt die GEMESSENE Lesart ("Klimax-Kerze - der Kurs laeuft
danach eher GEGEN die Kerze"), nicht die Lehrbuch-Lesart. Eine
Richtungsampel wuerde hier systematisch falsch stupsen - gleiche Korrektur
wie bei der Bounce-Anzeige. Kein Verdict-Gewicht, kein Trigger.

Beim Bau gefunden: mt5_lock ist ein CONTEXT-MANAGER, kein Lock-Objekt -
.acquire()/.release() wirft. Jetzt "with mt5_lock(3.0) as got".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-31 08:15:46 +02:00
Axel HocksandClaude Opus 4.8 7e0d2a4563 Verdict: Chartmuster + Orderbuch + Liquiditaets-Trend als Stimmen (v=121)
User-Vorgaben: "beruecksichtige die chartmuster mit in der gesamtempfehlung sobald
eins erkannt wird" + "auch der liquiditaetstrend und das orderbuch".

MUSTER (Gewicht 1,0 bestaetigt / 0,5 bildet sich) -- vorher den faelligen
KONTROLLTEST nachgeholt (stand seit heute im measurement_reminder):
  Muster    H1 +0.206 (Ziel 23%)  H2 +0.328 (Ziel 26%)
  Kontrolle H1 +0.184 (Ziel 19%)  H2 +0.220 (Ziel 18%)   <- beliebiger Swing-Bruch
  Delta     H1 +0.022             H2 +0.108
Die Muster schlagen die Kontrolle in BEIDEN Haelften, aber der Loewenanteil des
Ertrags kommt vom Breakout+Trailing. Deshalb Gewicht 1,0 (wie Elliott/KI), nicht
2,0 (Squeeze). Ziel-Trefferquote bleibt niedrig -> die Stimme sagt Richtungs-
tendenz, kein Kursziel.

ORDERBUCH-Imbalance + LIQ-TREND (Gewicht je 0,5 = kleinstes im Verdict):
⚠ BEIDE UNGEMESSEN. Die Uebertragbarkeit HL->CFD wird gerade erst erhoben
(analyze_bookflow.py, ~3% der Daten). Der Lead-Lag-Test zeigt sogar, dass
PEPPERSTONE fuehrt (r=0.525 bei k=-1) und HL folgt -- HL ist Oracle-basierter
HIP-3-Perp, strukturell Follower. Daher das kleinste Gewicht.
Imbalance-Schwelle _OB_IMB_MIN=0.30, darunter keine Stimme.

MITLOGGING: verdict_votes um pattern/pattern_w/orderbook/orderbook_w/liqtrend/
liqtrend_w erweitert (DB migriert, Backup angelegt). Nur so ist in ein paar Wochen
datenbasiert entscheidbar, ob die Stimmen bleiben, mehr Gewicht bekommen oder
rausfliegen (wie TU 2026-07-06).

Frontend: Chips rendern dynamisch (keine Aenderung noetig); NEU wird das GEWICHT
im Chip angezeigt und stumme Module (w=0) ausgegraut -- so ist sichtbar, dass
Orderbuch/Liq-Trend schwaecher zaehlen als Welle (3,0) oder Squeeze (2,0).

Verifiziert live: alle 9 Stimmen korrekt, Bias-Rechnung geprueft (1.5/5.5=0.273),
Logging schreibt die neuen Spalten.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 21:12:40 +02:00
Axel HocksandClaude Opus 4.8 2996eddd7e Auto-Signal-Entry + 15-Min-Regel (User-Wunsch, gegen die Messung, mit besten Params)
User will Auto-Eroeffnung bei Empfehlung trotz negativem Backtest -> gebaut,
Default AUS, mit den GEMESSEN besten Parametern statt geratenen:

Entry (_check_auto_signal, [trading] auto_signal=false):
- min_conf=75 + Nacht-Sperre = beste Kombi (H1 -0.053 mildester Verlust,
  H2 +0.141 bestes Netto). NICHT weil "mehr Konfidenz besser" -- conf_pct ist
  unkalibriert, 75 ist empirisch.
- Nur FLAT, 1x je Signal-Episode (Dedup, re-armt bei WARTEN/Flip), kein Nachkauf,
  kein Drehen einer Gegen-Position; erbt Circuit-Breaker + beide Cooldowns.
- Setup-Tag AUTOSIG_<dir> -> in der DB separierbar fuer B4-Monitor.
- Toggle POST /api/autosignal, Button "SIG" (bernstein = gemessen nicht tragfaehig),
  neustart-fest via runtime_state.json.

15-Min-Regel (_check_adverse15, adverse_15min_atr=0.5):
- Schwelle GEMESSEN kalibriert: "sobald im Minus" ist die SCHLECHTESTE Variante
  (WR 39->31%, Netto -0.067 vs +0.026 ohne); 0.5xATR ist die beste (H1 -0.111
  -> -0.079). Netto bringt die Regel ~nichts = Regime-Schutz.
- Nur BOT-eroeffnete Trades (_bot_open_ticket) -- manuelle Diskretion bleibt.
- 1x je Ticket geprueft, Startup-Grace respektiert, closed_by=adverse15.

Verifiziert: 18 synthetische Szenarien (9 Entry + 9 Adverse) alle korrekt;
Live-Neustart ohne Loop-Fehler, Toggle + Persistenz geprueft. v=119.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 14:01:14 +02:00
Axel HocksandClaude Opus 4.8 919ed7c3ee Trade-Leiste: Laufzeit-Uhr des offenen Trades (v=118)
- trader: open_time (echte Epoch, Broker-Offset korrigiert) aus position.time,
  im Snapshot; nur 1x je Position berechnet, beim Close auf 0.
- _broker_offset_s(sym=None): Symbol explizit uebergebbar -- beim Adoptieren ist
  self.symbol noch nicht gesetzt (war Offset 0 -> Zeit 3h in der Zukunft);
  zusaetzlich Selbstheilung bei Zukunftswerten.
- app.js/index.html/style.css: Feld #tb-dur + Titel-Uhr #tb-runtime, eigener
  1-s-Ticker (flüssig zwischen Snapshots), ab 2h bernstein (Time-Stop-Naehe).
- Verifiziert: Live-Trade 48898382 open_time == Log-Zeile 13:22:48.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-30 13:40:41 +02:00
Axel HocksandClaude Opus 4.8 ae6bbb2f35 Chartmuster grafisch: SVG-Skizze in Karte + Trigger/Ziel-Linien im PWA-Chart
- patterns.py: nur AKTIVE, kursnahe Muster (abgearbeitete/Ziel erreicht raus,
  _MAX_DIST_ATR=5.0 Distanz-Filter)
- get_bars liefert bei M30 die Muster (patterns.snapshot) fürs Chart-Overlay
- app.js: _patternSvg-Skizze je Muster-Karte + 2 stärkste Muster als
  Trigger-/Ziel-Preislinien im M30-Chart; Gitternetz dezenter (#10151c)
- style.css: .pt-svg; index.html v=116->117; CLAUDE.md aktualisiert

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 19:13:47 +02:00
Axel HocksandClaude Opus 4.8 e5589da08b Neues Modul: Visuelle Chartmuster-Erkennung (core/patterns.py) — reine Anzeige
Erkennt aus M30-Swing-Pivots: Doppeltop/-boden, Kopf-Schulter/inverse SKS,
Tasse+Henkel/invers, auf-/absteigendes+symmetrisches Dreieck. Je Muster Richtung,
Trigger/Nackenlinie, Measured-Move-Ziel, Status (bildet sich/bestätigt/ungültig),
Güte. Dashboard-Karte #card-patterns + Disclaimer (v=116). KEIN Signal, kein
Verdict-Gewicht — Signal-Einfluss erst nach Backtest (Muster-Klasse 2x verworfen,
hohe Beweislast). Live getestet: findet bestätigten Doppeltop.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 18:49:40 +02:00
Axel HocksandClaude Opus 4.8 cd8ee5b01b Circuit Breaker: Tagesverlust-Stopp (daily_loss_limit_pct=8) — Überlebens-Basis
User-Ziel autonomes Handeln → Notbremse im Code (vorher abgelehnt, reaktiviert).
Erreicht der Tages-P&L (realisiert+offen) -8% der Balance, schließt der Bot die
Position und sperrt neue Auto-Trades bis zum naechsten Tag. _check_circuit_breaker
im _pos_loop (Startup-Grace, ~30s realized-cache, Berlin-Datum-Reset), blockt
Auto-Squeeze, Snapshot + roter Frontend-Banner (v=115). 80%-Margin bleibt (User).
Mit 5 Szenarien getestet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-27 17:39:55 +02:00
Axel HocksandClaude Opus 4.8 d61c4a3634 Gesamtempfehlung-Paket: 2 Rollouts, 3 Anzeige-Features, 2 Messungen (v=114)
- Entry-Raum-Gate 0,6→1,0 (Messung lag vor: beide Hälften besser)
- Konfidenz-Kalibrierung gemessen (analyze_verdict_calibration.py): conf
  INVERTIERT zwischen Regimen → keine P(Erfolg)-Aufwertung, kein Konf-Sizing
- verdict_votes-Logging (1×/min) für spätere Copilot/Elliott-Entscheidung
- Order-Dialog zeigt eigenen Ausrichtungs-Split (36/40 Trades ohne Signal: −423€)
- Live-Kosten-Chip (Spread/ATR) im Verdict
- P(break)×Entry-Raum-Freigabe gemessen VERWORFEN (Flip in jeder Schwelle,
  backtest_entryroom_pbreak.py) — 13. verworfener Signal-Eingriff
- News-Konflikt-Chip + recommendations.news_score wieder befüllt

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 20:57:56 +02:00
Axel HocksandClaude Opus 4.8 bfe3c4206c G/V im Header extra-fett (weight 800, analog Gesamtempfehlung, v=113)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 18:46:39 +02:00
Axel HocksandClaude Opus 4.8 4bc7679ba3 Übersehene font:-Shorthands mitvergrößert (v=112)
Die drei `font:<weight> Npx/…`-Shorthands (.ms-chip/.ms-bos-lbl/.sqm-badge) waren
bei den beiden +2px-Runden ausgelassen worden (Skript erfasste nur `font-size`);
jetzt +4px nachgezogen → wirklich ALLE Schriftgrößen einheitlich +4px.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:50:24 +02:00
Axel HocksandClaude Opus 4.8 25a0c6c826 Schriftgrößen nochmal +2px (v=111, gesamt +4px)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-24 17:47:47 +02:00