From caa937f87d618780e624f58059a072f346a2285d Mon Sep 17 00:00:00 2001 From: Axel Hocks Date: Thu, 6 Aug 2026 23:46:31 +0200 Subject: [PATCH] =?UTF-8?q?Gesamtempfehlung:=20nur=20noch=20Module=20mit?= =?UTF-8?q?=20Stimmrecht=20=C2=B7=20Tooltips=20ueberall=20(v=3D147)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit · 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 --- CLAUDE.md | 20 ++++++- core/engine.py | 18 +++++-- tools/set_tooltips.py | 95 +++++++++++++++++++++++++++++++++ web/app.js | 9 +++- web/index.html | 121 +++++++++++++++++++----------------------- web/style.css | 6 --- 6 files changed, 189 insertions(+), 80 deletions(-) create mode 100644 tools/set_tooltips.py diff --git a/CLAUDE.md b/CLAUDE.md index 7313734..384995e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -3744,7 +3744,25 @@ dort bereits nachvalidiert, ØR +0,305.) **Eine** Oberfläche: machte daraus ein wortloses `None`. Danach hätte er den **Trend-Loop 7 s blockiert** → läuft jetzt im **Daemon-Thread**, wie der Wirtschaftskalender und aus demselben Grund. -- Asset-Version aktuell **v=145** (in `web/index.html` hochzählen, siehe Workflows). +- **Gesamtempfehlung aufgeräumt + Tooltips überall (User-Vorgabe 2026-08-06, + v=147):** + · **Nur noch Module MIT Stimmrecht als Chip.** `_verdict.add()` hat ein + **`used`**-Flag; `used=False` heisst *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 — die sprechen wieder. + · **`#vd-note` entfernt** (der Münzwurf-Hinweistext) samt CSS. Die Aussage steht + weiter im Tooltip der Karte und in dieser Datei. + · **Tooltips auf allen Dashboard-Anzeigen** (59 `title`-Attribute): Karten- + Überschriften, Header-Boxen, Trade-Leiste und die Anzeige-Elemente. Wo eine + Messung existiert, steht sie im Tooltip (z. B. Kerzen-Anatomie: „Lehrbuch-Lesart + gemessen INVERTIERT"; Bounce: „~50 % Trefferquote, KEIN Signal"). Gesetzt über + `set_tooltips.py` — **idempotent**, ergänzt nur fehlende `title=`, damit ein + erneuter Lauf nichts überschreibt. +- Asset-Version aktuell **v=147** (in `web/index.html` hochzählen, siehe Workflows). Schriftgrößen 2026-07-24 global **+4px** (2× je +2px auf User-Wunsch; Body-Basis 14→18px). ⚠ Betrifft in `style.css` sowohl `font-size:Npx` (71×) ALS AUCH die `font: Npx/…`-**Shorthand** (3×: `.ms-chip`/`.ms-bos-lbl`/`.sqm-badge` — diff --git a/core/engine.py b/core/engine.py index 8b86c69..7ccdcf5 100644 --- a/core/engine.py +++ b/core/engine.py @@ -2835,9 +2835,17 @@ class TradingEngine: bid = (market or {}).get("bid") votes = [] - def add(name, vote, weight, detail): - votes.append({"name": name, "vote": int(vote), - "weight": weight, "detail": detail}) + def add(name, vote, weight, detail, used=True): + """`used=False` = das Modul hat DAUERHAFT kein Stimmrecht (gemessen + ohne Inhalt) und wird im Dashboard NICHT mehr als Chip gezeigt. + ⚠ Es bleibt trotzdem in `votes` — `log_verdict_votes` speist daraus + die Telemetrie, und die 25.000-Verdict-Messung braucht die Reihe + weiter. Ausgeblendet wird nur die Anzeige, nicht die Messung. + Nicht zu verwechseln mit `weight=0` aus SITUATIVER Stille (Welle bei + WARTEN, Squeeze ohne Ausbruch): die sprechen zeitweise und bleiben + sichtbar.""" + votes.append({"name": name, "vote": int(vote), "weight": weight, + "detail": detail, "used": bool(used)}) # 1) Welle — primär (validierter Edge). ⚠ Bei WARTEN hat sie KEINE Aussage # → Gewicht 0 (Fix 2026-07-30). Vorher stand w=3,0 permanent im Nenner und @@ -2910,7 +2918,7 @@ class TradingEngine: # ⚠ Reine ANZEIGE-Änderung: die Order steuert die Welle über die # Headline, nicht der Konsens. Zurück: `ew = 1.0 if ev != 0 else 0.0`. ew = 0.0 - add("Elliott", ev, ew, edet) + add("Elliott", ev, ew, edet, used=False) # 7) Squeeze-Breakout — Event-Signal: stimmt NUR bei `active` mit (dann 2,0, # gemessen 2-Stichproben-positiv, unter der Welle=3,0). armed/keine → Gewicht 0 @@ -3012,7 +3020,7 @@ class TradingEngine: ldet = f"{tr['dir']} {tr.get('slope_per_h', 0):+.2f}$/h" except Exception: pass - add("Orderbuch", ov, ow, odet) + add("Orderbuch", ov, ow, odet, used=False) add("Liq-Trend", lv, lw, ldet) # Bias nur über stimmberechtigte Module (weight>0); agree/total = wie viele diff --git a/tools/set_tooltips.py b/tools/set_tooltips.py new file mode 100644 index 0000000..0ea90de --- /dev/null +++ b/tools/set_tooltips.py @@ -0,0 +1,95 @@ +"""Setzt Tooltips (title=) auf alle Dashboard-Anzeigen. Idempotent.""" +import pathlib +import re + +P = pathlib.Path(r"c:\Users\ah\Downloads\tradingrobot\web\index.html") +t = P.read_text(encoding="utf-8") + +KARTEN = { + "trade-bar": "Der aktuell offene Trade. SL, TP und die Close-Schwellen sind hier direkt editierbar — Enter oder Verlassen des Feldes sendet.", + "card-verdict": "Aggregation aller Module zu einer Empfehlung. Die HEADLINE (Welle) steuert die Order, alles darunter ist Konsens-Anzeige. Gemessen an 1.071 Live-Episoden trifft die Richtung zu 48–51 % — die Karte taugt als Veto (gegen das Signal zu handeln kostet gemessen 6,60 € je Lot), nicht als Prognose.", + "card-pos": "Live-Meldungen zum laufenden Trade und zur Marktlage: Squeeze, Überdehnung, S/R-Nähe, News- und Kalender-Konflikte, Hyperliquid-Kontext.", + "card-trail": "Zustand des Trailing-Stops (Phase, aktueller SL, High-Water). Ausgeblendet — das Trailing läuft im Hintergrund weiter.", + "card-stats-live": "Kompakte Bilanz über Woche und Gesamt. Verhältnis = Ø-Gewinn geteilt durch Ø-Verlust; unter 1 heißt, die Verlierer sind größer als die Gewinner.", + "card-agent": "Einschätzung des KI-Copiloten (LLM). Stimmt mit Gewicht 1,0 mit, wenn er eine Richtung nennt — bei NEUTRAL zählt er nicht. Als Prognose nicht belegt.", + "card-patterns": "Mechanisch erkannte Chartmuster auf M30 mit Trigger und Kursziel. Gewicht 0,25. Die Ziel-Trefferquote liegt gemessen nur bei 13–38 % — Kontext, keine Vorhersage.", + "card-structure": "Price-Action-Struktur auf M30: Swing-Folge, letzter Bruch (BOS) und Regressionskanal. Reine Anzeige — als Signal über alle Zeitebenen gemessen und verworfen.", + "card-candles": "Kerzengröße, Dochte und Volumen der letzten M5-Kerzen. Reine Anzeige und bewusst neutral gefärbt: die Lehrbuch-Lesart ist hier gemessen INVERTIERT — der Kurs läuft nach einer Klimax-Kerze eher GEGEN sie.", + "card-manual": "Deine eigenen manuellen Trades im Vergleich zum Bot, aufgeteilt nach Signal-Deckung. Rein deskriptiv.", + "card-trades": "Die zuletzt geschlossenen Trades mit Ergebnis und Schließgrund.", + "card-gaps": "Offene Kurslücken des Jahres. Vakuum = echte Lücke zwischen den Tagesspannen (fließt als S/R in die Konfidenz ein), Eröffnung = Schluss-zu-Eröffnung (reine Anzeige).", +} + +HDR = { + "BALANCE": "Kontostand ohne die offene Position.", + "TAG P/L": "Realisiertes Ergebnis von heute. Brutto — die Quellensteuer wird größtenteils erstattet und ist hier nicht abgezogen.", + "EQUITY": "Kontostand einschließlich der offenen Position.", + "PEPPERSTONE KURS": "Der Kurs, zu dem tatsächlich gehandelt wird. Steht er länger als 3 Minuten still, gilt der Markt als geschlossen und das Label zeigt ZU.", + "HYPERLIQUID KURS": "Roher Kurs des Hyperliquid-Öl-Perps — läuft 24/7, auch wenn Pepperstone geschlossen ist. Anderer Kontrakt, deshalb nicht identisch; der Tooltip am Wert nennt die umgerechnete Entsprechung.", + "G/V": "Gewinn/Verlust der offenen Position, NETTO nach Quellensteuer. Bei geschlossenem Markt eine Schätzung auf Basis des Hyperliquid-Kurses (mit ≈ markiert).", +} + +TB = { + "Laufzeit": "Wie lange der Trade schon läuft. Ab 2 Stunden bernstein — dann greift der Time-Stop, falls der Trade nie in die Gewinnphase kam.", + "Richtung": "LONG = auf steigende Kurse, SHORT = auf fallende.", + "Lots": "Positionsgröße. Ergibt sich aus dem Einsatz-Feld in der Order-Leiste.", + "Einsatz": "Die gebundene Margin dieser Position.", + "Auto-Close": "Schließt am nächsten S/R-Level automatisch, wenn das Level wahrscheinlich hält. Derzeit AUS.", + "SL": "Stop-Loss beim Broker. Ändern schaltet das Trailing ab, damit es die Handeingabe nicht zurückzieht.", + "TP": "Take-Profit beim Broker. Ändern schaltet das Trailing ab.", + "Gewinn-Close": "Mindestgewinn in Euro, unter dem der Auto-Close am Level NICHT schließt. Leer oder 0 = aus.", + "Notfall-Close": "Harte Verlustgrenze in Euro — der Server schließt sofort, wenn sie erreicht ist. Wirkt auch bei gesperrtem Handy. ⚠ Ein gesetzter Wert wird auf den nächsten Trade übernommen, bis er gelöscht wird.", +} + +ELEM = { + "vd-signal": "Die eigentliche Empfehlung samt Zeitebene — sie steuert die Order. Bei WARTEN steht dahinter, was noch fehlt.", + "vd-consensus": "Wie viele der stimmberechtigten Module dieselbe Richtung sehen, plus die aktuellen Handelskosten (Spread geteilt durch ATR).", + "vd-modules": "Die Module mit Stimmrecht. Die Zahl im Chip ist das Gewicht, graue Chips schweigen gerade. Dauerhaft entmachtete Module werden hier nicht mehr gezeigt.", + "vd-meter": "Bias-Nadel: gewichteter Konsens der Module zwischen SHORT und LONG. Reine Anzeige — die Order steuert die Headline.", + "wave-turns": "EMA-Stand je Zeitebene: grün aufwärts, rot abwärts. Eine frische Kreuzung blinkt. Reine Anzeige.", + "wave-squeeze": "Volatilitäts-Squeeze: der Kurs komprimiert und bricht aus. Das einzige 2-Stichproben-validierte Einstiegssignal des Projekts.", + "wave-bounce": "Warnung bei Überdehnung — der Kurs ist weit von seiner EMA weg. KEIN Signal: die Richtungstreffer-Quote liegt gemessen bei ~50 %.", + "cur-near": "Nächstes S/R-Level und Abstand dorthin.", + "wave-reasons": "Die Begründungen, aus denen sich Richtung und Konfidenz zusammensetzen.", + "pos-srhint": "Nähert sich der Kurs dem Ziel-Level, steht hier die Durchbruch-Wahrscheinlichkeit. Das Modell dahinter ist out-of-sample kalibriert (AUC 0,65).", + "pos-stophint": "Dasselbe für das Level auf der Verlustseite — reine Anzeige, hier wird nichts automatisch geschlossen.", + "news-conflict": "Warnt, wenn der News-Flow deutlich gegen die offene Position oder das aktive Signal steht. Kontext — als Prognose nicht belegt.", + "cal-note": "Laufendes oder bevorstehendes High-Impact-Ereignis aus dem Wirtschaftskalender. Sperrt autonome Einstiege, nicht manuelle.", + "flip-note": "Zustand des Auto-Flip-Close. Derzeit aus — in beiden Halbjahren gemessen negativ.", + "agent-bias": "Richtungsaussage des Copiloten. NEUTRAL heißt, er zählt in der Empfehlung nicht mit.", + "agent-reason": "Die Begründung des Copiloten im Klartext.", + "pt-list": "Erkannte Muster mit Skizze, Trigger und Kursziel.", + "ms-swings": "Swing-Folge: HH/HL = Aufwärtsstruktur, LH/LL = Abwärtsstruktur.", + "ms-bos": "Letzter Break of Structure — welches Swing-Level zuletzt gebrochen wurde.", + "ms-chan": "Position des Kurses im Regressionskanal: 0 % = unterer Rand, 100 % = oberer.", + "ca-list": "Erkannte Kerzenformen der letzten M5-Bars mit Volumen-Vergleich.", + "mt-grid": "Deine manuellen Trades über heute, 30 Tage und gesamt, dazu der Bot zum Vergleich.", + "mt-split": "Aufgeteilt danach, ob der Trade MIT oder OHNE Deckung durch die Empfehlung lief. Gegen das Signal kostet gemessen 6,60 € je Lot.", + "trades": "Zuletzt geschlossene Trades: Richtung, Ergebnis und Schließgrund.", + "gaps-list": "Offene Kurslücken mit Zone, Fill-Level und Abstand zum aktuellen Kurs.", + "stx-row": "Trades, Trefferquote, Profitfaktor und das Verhältnis von Ø-Gewinn zu Ø-Verlust.", +} + + +def setze(muster: str, tip: str, text: str) -> str: + """Haengt title= an, wenn noch keins da ist (idempotent).""" + def rep(m): + attrs = m.group(2) + if "title=" in attrs: + return m.group(0) + return m.group(1) + attrs + f' title="{tip}"' + m.group(3) + return re.sub(muster, rep, text, count=1) + + +for i, tip in KARTEN.items(): + t = setze(rf'(
]*id="{re.escape(i)}"[^>]*>\s*]*)(>)', + tip, t) +for lbl, tip in HDR.items(): + t = setze(rf'({re.escape(lbl)})', tip, t) +for lbl, tip in TB.items(): + t = setze(rf'({re.escape(lbl)})', tip, t) +for i, tip in ELEM.items(): + t = setze(rf'(
]*)(>)', tip, t) + +P.write_text(t, encoding="utf-8") +print(f" title-Attribute: {t.count('title=')}") diff --git a/web/app.js b/web/app.js index 4a007e7..f631e6e 100644 --- a/web/app.js +++ b/web/app.js @@ -159,7 +159,14 @@ function renderVerdict(v, snap) { // Modul-Chips const vote = (x) => x > 0 ? ["long", "▲"] : x < 0 ? ["short", "▼"] : ["flat", "—"]; - $("vd-modules").innerHTML = (v.votes || []).map(mod => { + // ⚠ NUR Module zeigen, die wirklich in die Empfehlung einfliessen + // (User-Vorgabe 2026-08-06). `used === false` = dauerhaft entmachtet, weil + // gemessen ohne Inhalt (Elliott: 1.384 Episoden flach bei 25,9 % Einfluss; + // Orderbuch: 2.688 Episoden beidhaelftig negativ). Sie bleiben im Snapshot + // und in `verdict_votes` — nur der Chip entfaellt. + // Module mit `weight === 0` bleiben SICHTBAR: die schweigen nur situativ + // (Welle bei WARTEN, Squeeze ohne Ausbruch) und sprechen wieder. + $("vd-modules").innerHTML = (v.votes || []).filter(m => m.used !== false).map(mod => { const [c, a] = vote(mod.vote); // Gewicht sichtbar machen: Module OHNE Aussage (w=0) grau, sonst das Gewicht // anzeigen — so ist erkennbar, dass z. B. Orderbuch/Liq-Trend (0,5, ungemessen) diff --git a/web/index.html b/web/index.html index dbbcefb..b5cbee4 100644 --- a/web/index.html +++ b/web/index.html @@ -6,7 +6,7 @@ Oil · MT5 - + @@ -36,16 +36,16 @@
-
-
-
-
+
+
+
+
-
-
+
+
@@ -54,32 +54,32 @@
-

Gesamtempfehlung

+

Gesamtempfehlung

-
- ⓘ Richtung ≈ Münzwurf (gemessen 48–51 % Treffer). Der Ertrag kommt aus - Einstiegspreis und Exit, nicht aus der Trefferquote — lies das hier als - Auslöser für eine Order am Level, nicht als Kursprognose. -
@@ -120,9 +107,9 @@
LONG
-
+
-
+
-

Meldungen

-
-
-
- - - - +

Meldungen

+
+
+
+ + + + - -
+ +
Setup
Lauf
@@ -164,7 +151,7 @@ @@ -220,13 +207,13 @@
-

Marktstruktur M30 · nur Anzeige

+

Marktstruktur M30 · nur Anzeige

-
+
-
-
+
+
@@ -239,8 +226,8 @@ Lehrbuch-Deutung ist invertiert, deshalb steht die GEMESSENE Lesart im Hinweistext und die Kachel ist bewusst neutral gefärbt. -->
-

Kerzen-Anatomie M5 · nur Anzeige

-
+

Kerzen-Anatomie M5 · nur Anzeige

+
@@ -275,22 +262,22 @@ rechnet nichts hoch. Der volle Entscheidungskontext (ctx_*) wird erst seit dem 04.08. mitgeschrieben; die Reifegrad-Zeile macht das sichtbar. -->
-

Manuelle Trades deine Historie · 30 Tage

-
-
+

Manuelle Trades deine Historie · 30 Tage

+
+
-

Letzte Trades

-
+

Letzte Trades

+
-

Kurslücken (Gaps 2026)

-
lade …
+

Kurslücken (Gaps 2026)

+
lade …
@@ -345,6 +332,6 @@ - + diff --git a/web/style.css b/web/style.css index 5c13880..6cbbd50 100644 --- a/web/style.css +++ b/web/style.css @@ -215,12 +215,6 @@ main{display:grid;grid-template-columns:1fr 1fr;gap:11px;padding:11px} #vd-conf{line-height:1} .vd-ring-lbl{font-size:10px;font-weight:600;font-style:normal;color:var(--dim); letter-spacing:.5px;line-height:1;margin-top:1px} -/* Stehender Vorbehalt unter der Headline: die Richtung ist gemessen ein Muenzwurf. - Bewusst gedaempft und gestrichelt — Kontext, keine Warnung. */ -.vd-note{font-size:13px;line-height:1.45;color:var(--dim);background:var(--surface-2); - border:1px dashed var(--line);border-radius:var(--r-sm); - padding:7px 10px;margin:0 0 11px} -.vd-note b{color:var(--bright);font-weight:700} /* Block-Verteilung + Selbst-Kalibrierung: beide bewusst leise (Kontext, keine Handlungsaufforderung). Die Trefferquote faerbt nur bei klarer Abweichung von den gemessenen ~50 %, damit Rauschen nicht wie ein Signal aussieht. */