diff --git a/CLAUDE.md b/CLAUDE.md index c2e7db9..f464dc4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4315,7 +4315,7 @@ Trader wäre sie nie abgelaufen. Latte unverändert: Verhältnis < 1,0 ODER PF < („⚠ die Welle (steuert die Order) schweigt"). Live gegengerechnet, beide Zeilen erscheinen wie beabsichtigt. ⚠ Reine Anzeige — an Gewichten, Gates und Order-Logik ist nichts geändert. -- Asset-Version aktuell **v=168** (in `web/index.html` hochzählen, siehe Workflows). +- Asset-Version aktuell **v=169** (in `web/index.html` hochzählen, siehe Workflows). - **✅ SCHRIFT SKALIERT MIT DEM FENSTER (2026-08-13, v=167).** User: „die Größe der Schriftarten im Dashboard auf em einstellen, damit auf jedem Gerät oder je nach Fenstergröße die Schriftgröße automatisch angepasst wird." @@ -5405,6 +5405,59 @@ nicht führbar — und Schritt 4 ist der EINZIGE belastbare Nachweis, dass neuer Python-Code läuft. Jetzt mit **Punktpfaden**; ein Feld mit Wert `None` zählt als vorhanden (geprüft wird der Schlüssel, nicht der Inhalt). +### ⚠⚠ CHART UND M15-KARTE NANNTEN FÜR DASSELBE LEVEL VERSCHIEDENE ZAHLEN (Fix 2026-08-13, v1.35 / v=169) + +User: „die Beschriftung für S/R im Chart stimmt nicht mit der Analyse in der +M15-Karte überein." +✅ **Die LEVEL stimmten — nur die Zahl daneben nicht.** Live gegengeprüft: die +CSV, die der Indikator liest, enthielt `R;82.069;69`, und Gate ③ der Karte +meldete `nah: res 82.069, p_break 69`. Beide kommen aus `_draw_levels()`, sind +also per Konstruktion identisch. Auch die Distanzen sind exakt gerechnet +(nachgerechnet 0,477≈0,48 · 0,909≈0,91 · 0,455≈0,45). +⚠⚠ **DER DEFEKT: das Chart schrieb die NACKTE Zahl, die Karte klappte still auf +den Gegenwert um.** +| P(Bruch) | Chart (v1.34) | M15-Karte (`app.js` `lesart()`) | +|---|---|---| +| 33 % | `Widerstand 82.069 · **33%**` | `Widerstand 82.069 → **67 % Abprall**` | +| 46 % | `… · **46%**` | `… → **unentschieden**` | +| 72 % | `… · **72%**` | `… → **72 % Bruch**` | +Beide Zahlen waren **richtig** — die eine P(Bruch), die andere P(Abprall) — aber +die Chart-Zahl sagte nicht, WAS sie ist. **Gemessen betraf das 88,1 % der Zeit** +(1.797 Vorhersagen/14 Tage: 66,3 % lagen unter 45 %, 21,9 % im unentschiedenen +Band; nur 11,9 % über 55 %, wo beide dieselbe Zahl zeigen). +✅ **Behoben im Indikator (v1.35), wortgleich zu `app.js`:** `69% Bruch` / +`unentschieden` / `67% Abprall`. Über **1.678 echte** P(break)-Werte gegengeprüft: +Übereinstimmung **0 % → 100 %**. +⚠ Die Formulierung lebt jetzt an ZWEI Stellen (MQL5 + `app.js`) — wer eine +ändert, muss die andere mitziehen; beide tragen einen Hinweis darauf. Ein +gemeinsamer Text aus dem CSV wäre sauberer, hätte aber das Format gebrochen. +⚠ **Kompiliert ins RICHTIGE Terminal** (der dokumentierte Fallstrick): es gibt +real **zwei** Ordner, nur `D0E8209F…` bekommt die `sr_levels.csv` +(`0BA5CADA…` nicht). `MetaEditor64.exe /compile` → **0 errors, 0 warnings**, +`.ex5` frisch, `#property version "1.35"` im Terminal gegengeprüft. +✅ **Zwei Verdachtsmomente ausgeschlossen, statt sie zu vermuten:** (a) eine +stehengebliebene Alt-Linie — der Indikator ruft `ObjectsDeleteAll(0, PFX)` bei +jedem Redraw; (b) ein falsch einsortiertes Level — `_draw_levels` wählt seit dem +Fix vom 23.07. nach **Lage zum Kurs**, nicht nach Entstehungstyp. ⚠ Nebenbefund: +82.069 stammt aus `pl` (einem Pivot-**Tief**) und wird korrekt als Widerstand +geführt, weil der Kurs darunter steht — das sieht im Chart nur ungewohnt aus. + +**ZWEITER, unabhängiger Befund derselben Klasse — behoben:** Gate ③ und ③b +nannten Level aus **verschiedenen Zeitebenen**, beide nur als „×ATR": +| | Level-Quelle | ATR | im Chart gezeichnet? | +|---|---|---|---| +| **③** | M30-Pivots (`_draw_levels`) | **ATR_M15** | **ja** | +| **③b** | M5-Pivots (`room_info`) | **ATR_M5** | **nein** | +Real standen damit „0,48×ATR" und „0,45×ATR" nebeneinander, die **nicht +vergleichbar** sind — und die Karte nannte einen „Support 81,78", den man im +Chart vergeblich sucht. ⚠ Verschärfend: zum Prüfzeitpunkt lagen **alle 10 +M30-Pivots über dem Kurs**, es gab also gar keine Support-Linie im Chart. +✅ Die Quellen-Trennung **bleibt** — `entry_room_atr=0,6` ist über 80k Bars auf +M5 kalibriert, sie umzustellen wäre eine Strategie-Änderung. Geändert wurde nur +die Beschriftung: `③ Widerstand M30 82.069 (Chart · 0,48×ATR_M15)` gegen +`③b … Raum ▲ 0,91×ATR_M5 / ▼ 0,45×ATR_M5`. Die Tooltips nennen den Unterschied +ausdrücklich. **Reine Anzeige — an Gates, Gewichten und Order-Logik nichts.** + ### ✅ S/R-AUTO-CLOSE WIEDER AN (User-Entscheidung 2026-08-11) Frage war: „sollten wir Trades bei einem S/R-Bounce automatisch schliessen?" diff --git a/mql5/SR_Levels.mq5 b/mql5/SR_Levels.mq5 index 1204136..851998b 100644 --- a/mql5/SR_Levels.mq5 +++ b/mql5/SR_Levels.mq5 @@ -12,7 +12,15 @@ //| 4) Der Bot muss laufen (schreibt die CSV alle ~5 s). | //+------------------------------------------------------------------+ #property copyright "Oil Trading Bot" -#property version "1.34" +#property version "1.35" +// v1.35 (2026-08-13): S/R-LABEL WORTGLEICH ZUR M15-KARTE (User: „die Beschriftung +// fuer S/R im Chart stimmt nicht mit der Analyse in der M15-Karte ueberein"). +// Das Label trug seit v1.27 die NACKTE Zahl = P(Durchbruch); die Karte klappt +// unter 45 % auf P(Abprall) um und nennt 45-55 % „unentschieden". Dasselbe +// Level stand damit im Chart als „33%" und in der Karte als „67 % Abprall" — +// beide Zahlen richtig, aber die Chart-Zahl sagte nicht, WAS sie ist. +// GEMESSEN in 88,1 % der Zeit verschieden (1.797 Vorhersagen/14 Tage). +// Jetzt: „69% Bruch" / „unentschieden" / „67% Abprall" — identisch zu app.js. // v1.34 (2026-08-01): HYPERLIQUID-KURS (HL;...) unter Kurs und G/V oben rechts, // bernstein. HL handelt 24/7, Pepperstone nicht - am Wochenende der einzige // lebende Kurs; die Basis (~0,45 $ Kontrakt-Differenz) ist herausgerechnet, @@ -472,13 +480,27 @@ void Redraw() double price = StringToDouble(p[1]); if(price <= 0) continue; // Feld 3 (optional) = P(Durchbruch) in % aus dem kalibrierten Modell des - // Bots. Niedrig = Level haelt eher, hoch = bricht eher. Im LABEL steht nur - // die nackte Zahl („Widerstand 84.536 · 34%", User-Wunsch 2026-07-30); - // der ausgeschriebene Hinweis bleibt im Tooltip der Linie. + // Bots. Niedrig = Level haelt eher, hoch = bricht eher. + // ⚠⚠ WORTGLEICH ZUR M15-KARTE (Fix 2026-08-13, v1.35, User: „die + // Beschriftung fuer S/R im Chart stimmt nicht mit der Analyse in der + // M15-Karte ueberein"). Hier stand bis dahin die NACKTE Zahl = P(Bruch). + // Die Karte (`app.js` lesart()/pTxt()) klappt unter 45 % aber auf den + // GEGENWERT P(Abprall) um und nennt 45–55 % „unentschieden" — dasselbe + // Level trug damit im Chart „33%" und in der Karte „67 % Abprall". + // Beide Zahlen waren richtig, aber die Chart-Zahl sagte nicht, WAS sie + // ist. GEMESSEN betraf das 88,1 % der Zeit (1.797 Vorhersagen/14 Tage: + // 66,3 % lagen unter 45 %, 21,9 % im unentschiedenen Band). + // ➜ Wer die Formulierung hier aendert, muss `lesart()` in app.js + // mitaendern — sonst laufen sie wieder auseinander. string lbl = (typ=="R" ? "Widerstand " : "Unterstuetzung ") + DoubleToString(price, (int)_Digits); if(InpShowPBreak && k > 2 && StringLen(p[2]) > 0) - lbl += " · " + p[2] + "%"; // nur die Zahl (User-Wunsch 2026-07-30) + { + int pb = (int)StringToInteger(p[2]); + if(pb >= 45 && pb <= 55) lbl += " · unentschieden"; + else if(pb > 55) lbl += " · " + IntegerToString(pb) + "% Bruch"; + else lbl += " · " + IntegerToString(100-pb) + "% Abprall"; + } color col = (typ=="R" ? InpResColor : InpSupColor); string nm = PFX + typ + "_" + IntegerToString(idx); if(ObjectCreate(0, nm, OBJ_HLINE, 0, 0, price)) diff --git a/web/app.js b/web/app.js index 38540fd..e645d3f 100644 --- a/web/app.js +++ b/web/app.js @@ -219,11 +219,22 @@ function renderM15(s) { const q = bricht ? `${p} % Bruch` : `${100 - p} % Abprall`; return ` → ${q}, eher ${auf ? "aufwärts ▲" : "abwärts ▼"}`; }; + // ⚠⚠ ZEITEBENE MIT IM TEXT (Fix 2026-08-13). ③ liest M30-Level und misst in + // ATR_M15, ③b liest M5-Level und misst in ATR_M5. Beide standen vorher nur als + // „×ATR" da — zwei Zahlen nebeneinander (0,48 und 0,45), die vergleichbar + // AUSSAHEN und verschiedene Bezugsgroessen hatten. Die Quellen-Trennung ist + // Absicht (`entry_room_atr=0,6` ist auf M5 kalibriert), die stumme + // Beschriftung war es nicht. + // ⚠ „(Chart)" markiert, dass GENAU diese Linie im MT5-Chart gezeichnet wird — + // die M5-Level aus ③b werden dort NICHT gezeichnet. $("m15-zone").textContent = z.length - ? "③ " + z.map(x => `${x.seite === "res" ? "Widerstand" : "Support"} ` - + `${f(x.level, 3)} (${f(x.gap_atr15)}×ATR)${lesart(x)}`).join(" · ") + ? "③ " + z.map(x => `${x.seite === "res" ? "Widerstand" : "Support"} M30 ` + + `${f(x.level, 3)} (Chart · ${f(x.gap_atr15)}×ATR_M15)${lesart(x)}`).join(" · ") : "③ kein Level in Sicht"; - $("m15-zone").title = "Richtungs-Lesart BEDINGT auf das Level, keine freie " + $("m15-zone").title = "GENAU diese Linie wird im MT5-Chart gezeichnet (M30-Pivots, " + + "geclustert) — der Chart nennt seit v1.35 dieselbe Zahl mit denselben Worten. " + + "⚠ Die Level in ③b stammen dagegen aus M5 und stehen NICHT im Chart. " + + "Richtungs-Lesart BEDINGT auf das Level, keine freie " + "Prognose: eine solche ist gemessen unmöglich (AUC 0,50 out-of-sample und " + "nur 0,52 in-sample — es steckt keine Richtungsinformation in den Daten). " + "P(break) fragt stattdessen „hält diese Struktur?“ und ist out-of-sample " @@ -275,7 +286,7 @@ function renderM15(s) { const seite = (o, lbl) => { if (!o) return null; if (o.level == null) return `${lbl} frei`; - return `${lbl} ${o.dist_atr}×ATR${o.frei ? "" : " ⚠"}`; + return `${lbl} ${o.dist_atr}×ATR_M5${o.frei ? "" : " ⚠"}`; }; if (mo.block) { // Der Motor blockt — das ist die Information, die gefehlt hat. @@ -300,14 +311,21 @@ function renderM15(s) { moEl.className = "m15-item"; moEl.textContent = "③b Motor —"; } + // ⚠ „M5" und „×ATR_M5" ausgeschrieben: diese Level stammen aus einer ANDEREN + // Zeitebene als ③ (M30) und werden im Chart NICHT gezeichnet. Ohne den Zusatz + // sucht man die genannte Linie dort vergeblich. const teile = [seite(rm.long, "▲"), seite(rm.short, "▼")].filter(Boolean); if (teile.length) { moEl.textContent += ` · Raum ${teile.join(" / ")}` + (rm.gate ? ` (Gate ${rm.gate})` : ""); } moEl.title = "Was der Signal-Motor GERADE blockt, plus der Raum zum nächsten " - + "Gegenlevel je Richtung (M5 — dieselbe Rechnung wie das Gate selbst, kein " - + "Nachbau). Unter 0,6×ATR ist der Ertrag am Level gedeckelt: gemessen " + + "Gegenlevel je Richtung. ⚠ Quelle sind M5-Pivots und ATR_M5 — eine ANDERE " + + "Zeitebene als ③ (M30-Level, ATR_M15), und diese Linien werden im Chart NICHT " + + "gezeichnet. Das ist Absicht: entry_room=0,6 ist über 80k Bars auf M5 " + + "kalibriert. Die beiden ×ATR-Zahlen sind deshalb NICHT vergleichbar. " + + "Dieselbe Rechnung wie das Gate selbst, kein " + + "Nachbau. Unter 0,6×ATR ist der Ertrag am Level gedeckelt: gemessen " + "ØR −0,119/−0,067 bei PF 0,42/0,66 — Trefferquote hoch und trotzdem " + "Verlust. ⚠ Gate ③ liest dieselbe Nähe als GUT (ruhende Order AM Level), " + "entry_room als SCHLECHT (Markt-Einstieg mit dem Level als Hindernis). " diff --git a/web/index.html b/web/index.html index 1eaa785..2095ca6 100644 --- a/web/index.html +++ b/web/index.html @@ -6,7 +6,7 @@