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>
This commit is contained in:
Axel Hocks
2026-08-20 09:00:01 +02:00
co-authored by Claude Opus 5
parent 5e476025d7
commit 5925d9a527
3 changed files with 93 additions and 2 deletions
+66
View File
@@ -416,6 +416,45 @@ function renderM15(s, snap) {
+ "gedeckelt, der Verlust laeuft bis zum Stop. Reine Anzeige.";
}
// --- SETUP-BLOCK: Entry Zone · SL · TP1-3 (User-Wunsch 2026-08-20) ------
// ⚠⚠ Die RICHTUNG kommt aus dem VETO (erlaubte Richtung), NICHT aus einer
// Prognose — die Karte gibt keine ab, und das ist gemessen richtig so
// (1.071 Live-Episoden, 4851 % Treffer). Der Block beantwortet nur:
// WENN gehandelt wird, zu welchen Preisen.
// ⚠ Nichts wird neu gerechnet — Zonen, ATR und Kegel stehen im Snapshot.
// ⚠ TP1 ist ein LEVEL, kein Auftrag: ein fester TP am Gegenlevel ist der
// staerkste Gewinner-Kappen-Beleg des Projekts (Squeeze +0,102/+0,108 →
// 0,066/0,004). Deshalb steht bei TP2, dass das Trailing fuehrt.
{
const sb = $streng("m15-setupblock");
const verb = ((s.bias || {}).verboten || "").toUpperCase();
const erl = verb === "SHORT" ? "LONG" : verb === "LONG" ? "SHORT" : null;
const zonen = s.zonen || [];
const nah = zonen.slice().sort((a, b) => (a.gap_atr15 ?? 9) - (b.gap_atr15 ?? 9))[0];
const atr = s.atr_m15 || 0;
if (sb && erl && nah && atr > 0) {
const lg = erl === "LONG";
const e = nah.level, tol = 0.15 * atr;
const sl = lg ? e - 2.0 * atr : e + 2.0 * atr;
const geg = zonen.find(z => lg ? z.level > e : z.level < e);
const lv = ((snap || {}).cone || {}).levels || [];
const k120 = lv.find(x => x.band === 80 && x.minutes === 120);
const zl2 = [`<b>${lg ? "▲" : "▼"} ${erl}</b> <span class="dim">— nur wenn die Kette gruen ist</span>`,
`Entry Zone: <b>${f(e - tol, 3)} ${f(e + tol, 3)}</b>`,
`Stop Loss: <b>${f(sl, 3)}</b> <span class="dim">(2,0×ATR_M15)</span>`];
if (geg) zl2.push(`TP1: <b>${f(geg.level, 3)}</b> <span class="dim">(Level · ` +
`${100 - (geg.p_break ?? 50)} % haelt)</span>`);
zl2.push(`TP2: <b>${f(lg ? e + 3.5 * atr : e - 3.5 * atr, 3)}</b> ` +
`<span class="dim">(3,5×ATR — das Trailing fuehrt ihn nach)</span>`);
if (k120) zl2.push(`TP3: <b>${f(lg ? k120.hi : k120.lo, 3)}</b> ` +
`<span class="dim">(Kegel 120, trifft ${Math.round(k120.coverage || 0)} %)</span>`);
sb.innerHTML = zl2.join("<br>");
sb.hidden = false;
} else if (sb) {
sb.hidden = true;
}
}
// --- M5-Kontext: reine ZUSTANDS-Zeile, keine Richtung, kein Banner ------
// Bewusst KEINE eigene M5-Karte (User-Entscheidung 19.08.): die entkoppelte
// Selbstmessung dieser Karte steht bei n=342 auf 53,5 % [48,2 .. 58,8] und
@@ -1158,6 +1197,33 @@ function render(d) {
// Enter darauf schickt den GERUNDETEN Wert an den Broker — der Stop
// verschiebt sich also still um bis zu 0,5 Cent. Bei einem Trail von
// 11 Cent (ATR_M5 0,11 in dieser Nacht) sind das 5 % der Distanz.
// --- TP1/TP2/TP3: voraussichtliche Ziele (User-Wunsch 2026-08-20) -----
// ⚠⚠ REINE ANZEIGE — keines davon wird an den Broker geschickt. Ein FESTER
// TP am Gegenlevel ist im Projekt der staerkste Gewinner-Kappen-Beleg:
// er drehte den Squeeze von +0,102/+0,108 auf 0,066/0,004
// (backtest_trailing_sr.py). Die drei Zahlen sind Orientierung, kein
// Auftrag — deshalb Anzeige-Boxen und keine Eingabefelder.
// ⚠ NICHTS wird neu gerechnet: Zonen und Kegel stehen ohnehin im Snapshot.
// Ein zweiter Rechenweg waere die Divergenz-Falle (dreimal zugeschlagen).
{
const lg = p.order_type === 0;
const ep = Number(p.entry_price) || 0;
// TP1 — naechstes STEHENDES Level in Trade-Richtung
const zn = ((d.m15_setup || {}).zonen) || [];
const ziel = zn.find(z => lg ? (z.seite === "res" && z.level > ep)
: (z.seite === "sup" && z.level < ep));
$("tb-tp1").textContent = ziel
? `${fmt(ziel.level, 3)} (${100 - (ziel.p_break ?? 50)}% hält)`
: "—";
// TP2 — der Broker-TP, den das Trailing fuehrt
$("tb-tp2").textContent = p.tp ? fmt(p.tp, 3) : "—";
// TP3 — Obergrenze des 80-%-Kegels auf 120 min
const lv = ((d.cone || {}).levels) || [];
const k = lv.find(x => x.band === 80 && x.minutes === 120);
$("tb-tp3").textContent = k
? fmt(lg ? k.hi : k.lo, 3) + (k.coverage ? ` (trifft ${Math.round(k.coverage)}%)` : "")
: "—";
}
if (document.activeElement !== slEl) slEl.value = p.sl ? fmt(p.sl, 3) : "";
if (document.activeElement !== tpEl) tpEl.value = p.tp ? fmt(p.tp, 3) : "";
} else {
+14 -2
View File
@@ -12,7 +12,7 @@
⚠ LOKAL eingebunden, kein CDN: die PWA laeuft ueber WireGuard
und muss offline funktionieren. -->
<link rel="stylesheet" href="pico.min.css?v=1">
<link rel="stylesheet" href="style.css?v=193">
<link rel="stylesheet" href="style.css?v=195">
</head>
<body>
<!-- Modul-Menü (ganz oben) -->
@@ -82,6 +82,12 @@
<input id="tb-sl" type="number" inputmode="decimal" step="0.01" placeholder="—"></span>
<span class="tb-field gain"><label title="Take-Profit beim Broker. Ändern schaltet das Trailing ab.">TP</label>
<input id="tb-tp" type="number" inputmode="decimal" step="0.01" placeholder="—"></span>
<span class="tb-field gain"><label title="TP1 — das nächste STEHENDE Level in Trade-Richtung (M30-Pivots, dieselbe Quelle wie Chart und Gate ③), mit der Durchbruchwahrscheinlichkeit. ⚠ REINE ANZEIGE, wird nicht an den Broker geschickt. Ein fester TP am Gegenlevel ist gemessen der STÄRKSTE Gewinner-Kappen-Beleg des Projekts: er drehte den Squeeze von +0,102/+0,108 auf 0,066/0,004 (backtest_trailing_sr.py). Als Orientierung nützlich, als Auftrag nicht.">TP1 · Level</label>
<span class="tb-val" id="tb-tp1"></span></span>
<span class="tb-field gain"><label title="TP2 — der Broker-TP, den das Trailing dynamisch führt (Entry ± 3,5×ATR in Phase Init, danach mit dem Lauf nachgezogen). Das ist der einzige TP, der tatsächlich am Broker liegt.">TP2 · Trailing</label>
<span class="tb-val" id="tb-tp2"></span></span>
<span class="tb-field gain"><label title="TP3 — die Obergrenze des 80-%-Kegels auf 120 Minuten (core/cone.py). Out-of-sample geprüft: die 80-%-Bänder treffen real 77 %. ⚠ Das ist eine Aussage über die REICHWEITE, nicht über die Richtung — weiter kommt der Kurs in dieser Zeit selten, nicht: er kommt dorthin.">TP3 · Kegel 120</label>
<span class="tb-val" id="tb-tp3"></span></span>
<span class="tb-field gain"><label title="Mindestgewinn in Euro, unter dem der Auto-Close am Level NICHT schließt. Leer oder 0 = aus.">Gewinn-Close</label>
<input id="srmin-input" type="number" inputmode="decimal" step="1" placeholder="€"></span>
<span class="tb-field stop"><label title="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.">Notfall-Close</label>
@@ -116,6 +122,12 @@
wurde im Projekt verworfen, und User-Uebersteuerungen liefen
gemessen 68 % WR. Sichtbar machen, nicht bevormunden. -->
<div class="m15-status" id="m15-status"></div>
<!-- ⚠⚠ SETUP-BLOCK "Entry Zone / SL / TP1-3" (User-Wunsch 2026-08-20).
Die RICHTUNG kommt ausschliesslich aus dem VETO — die Karte gibt
weiterhin KEINE Richtungsprognose ab (ueber 1.071 Live-Episoden als
Muenzwurf gemessen, 48-51 %). Der Block sagt: WENN gehandelt wird,
dann zu diesen Preisen. -->
<div class="m15-setup" id="m15-setupblock" hidden></div>
<div class="m15-grid">
<details class="m15-akk" data-akk="prüfkette" open>
<summary> ④ Prüfkette</summary>
@@ -396,6 +408,6 @@
</div>
<div id="toast" class="toast hidden"></div>
<script src="app.js?v=193"></script>
<script src="app.js?v=195"></script>
</body>
</html>
+13
View File
@@ -662,3 +662,16 @@ main{padding-bottom:4.1111rem} /* Platz für die fixe Leiste */
filter:saturate(.55) brightness(.85);
}
.btn.eng-raum .btn-raum{ color:var(--accent); font-weight:700; }
/* ── M15-Setup-Block: Entry Zone · SL · TP1-3 (2026-08-20) ────────────────
⚠ Bewusst NEUTRAL gerahmt, nicht gruen/rot: die Karte gibt keine
Richtungsprognose ab (ueber 1.071 Live-Episoden 48-51 % Treffer). Der Block
sagt nur, ZU WELCHEN PREISEN gehandelt wuerde, wenn die Kette gruen ist. */
.m15-setup{
margin:0.4444rem 0; padding:0.5rem 0.6667rem;
border:1px solid var(--line); border-left:3px solid var(--dim);
border-radius:var(--r-sm); background:var(--surface-2);
font-size:0.8889rem; line-height:1.7;
}
.m15-setup[hidden]{display:none}
.m15-setup .dim{color:var(--dim); font-size:0.8rem}