M15-Auto-Entry gebaut (Default AUS) -- gegen die Messung, auf User-Wunsch

User wollte den Auto-Trade testen, nach vollstaendiger Information ueber die
Beleglage. backtest_m15_auto.py (13.08.): die gehandelte Lesart ist in BEIDEN
Halbjahren negativ (OeR -0,162/-0,094, PF 0,72/0,84), beide KI schliessen die
Null aus, Nachbarn monoton schlechter, und sie ist schlechter als die
HTF-Richtung UND als ihr eigenes Gegenteil. Live entkoppelt 46,8 % Treffer.

_check_auto_m15 im _pos_loop: Ausloeser gruen + gerichtet, Richtung exakt wie im
Backtest (auf->LONG, ab->SHORT), Dedup 1x je Episode ueber (Richtung, Level),
nur FLAT, Setup-Tag AUTOM15_*. Erbt die VOLLE Guard-Kette ueber
_auto_guard('m15') -- der Parameter war laut Docstring genau dafuer vorgesehen,
nachgebaut wurde nichts.

Abweichung ausdruecklich benannt: gemessen wurde der Einstieg AM Level mit Fill
bei Beruehrung, gebaut ist der Markt-Einstieg. Der ist hier mehrfach als der
schlechtere gemessen -- die Live-Zahlen sind eher noch unter -0,16/-0,09 zu
erwarten.

Abbruchregel VORAB fixiert: nach >=20 AUTOM15_*-Trades Verhaeltnis < 1,0 ODER
PF < 1 -> auto_m15 = false. Dieselbe Latte wie B5, damit sie nicht nachtraeglich
wandert.

Verifiziert: Toggle, Snapshot-Felder, Deploy mit --feld auto_m15, ruff F821
(neuer Code sitzt in einem except -- der dokumentierte blinde Fleck), 85 Tests.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-08-19 18:01:52 +02:00
co-authored by Claude Opus 5
parent cc3a710752
commit bd65bdaad0
6 changed files with 5185 additions and 4 deletions
+47
View File
@@ -7615,6 +7615,53 @@ vorab fixiert wurde** — also wird sie NICHT gesenkt, sondern als **durch
User-Entscheidung überstimmt** vermerkt. Wer sie ersetzen will, fixiert eine User-Entscheidung überstimmt** vermerkt. Wer sie ersetzen will, fixiert eine
NEUE Latte **vor** der Beobachtung, auf einem NEUEN Zählfenster ab heute. NEUE Latte **vor** der Beobachtung, auf einem NEUEN Zählfenster ab heute.
## ⚠⚠ M15-AUTO-ENTRY GEBAUT — GEGEN DIE MESSUNG, auf User-Wunsch (2026-08-19, v=181)
User: „ich möchte das auto trade testen. Baue den Button.“ — nach vollständiger
Information über die Beleglage. **Default AUS**, Schalter **M15** in der
Aktionsleiste, `[trading] auto_m15 = false`.
⚠⚠ **DIE MESSUNG SAGT NEIN, und zwar deutlich** (`backtest_m15_auto.py`, 13.08.):
| Variante | H1 ØR / PF | H2 ØR / PF |
|---|---|---|
| **A) die gehandelte Lesart** | **0,162 / 0,72** | **0,094 / 0,84** |
| C) Kontrolle HTF-Richtung | 0,085 / 0,85 | 0,030 / 0,95 |
| D) Kontrolle **Gegenrichtung** | 0,070 / 0,87 | **+0,007 / 1,01** |
Beide KI schliessen die Null aus ([0,222…−0,099] / [0,152…−0,038]), die
Nachbar-Schwellen werden **monoton schlechter**, und A ist schlechter als die
HTF-Richtung **und als ihr eigenes Gegenteil**. Live-Gegenprobe (`m15_states`,
entkoppelt): **46,8 %** Treffer auf 30 min. Die Karte steht in **46 %** der Zeit
grün UND gerichtet — als Auslöser also alles andere als selektiv.
**Umsetzung** — `engine._check_auto_m15` im `_pos_loop`:
• Auslöser `status=gruen` + `lesart` in (auf, ab); Richtung **exakt wie im
Backtest**: `auf → LONG`, `ab → SHORT`. • Dedup 1× je Episode über
**(Richtung, Level)** — derselbe Schlüssel `(d_les, nah["level"])`.
**Nur FLAT.** • Erbt die **volle** Guard-Kette: `_auto_guard("m15")` (Nacht,
Circuit-Breaker, News-Blackout) — der Parameter `pfad` war laut Docstring genau
dafür vorgesehen, **nachgebaut wurde nichts**. • Plus Startup-Schonfrist und
beide Wiedereinstiegs-Sperren. • Setup-Tag **`AUTOM15_*`**.
⚠⚠ **ABWEICHUNG VON DER GEMESSENEN VARIANTE, ausdrücklich benannt:** gemessen
wurde der Einstieg **AM Level mit Fill bei Berührung**, gebaut ist der
**MARKT**-Einstieg. Der Markt-Einstieg ist hier mehrfach als der schlechtere
gemessen (Squeeze +0,456 → 0,158 **allein durch den Preis**). Die Live-Zahlen
sind also **eher noch unter** 0,16 / 0,09 zu erwarten. Eine ruhende Order
hätte den geteilten `_pending_ziel`-Manager gebraucht (Squeeze hat dort
Vorrang) — eigener Umbau, bewusst nicht Teil dieses Tests.
**ABBRUCHREGEL, VORAB FIXIERT** (ohne sie wäre es kein Test, sondern nur ein
Schalter): **nach ≥ 20 `AUTOM15_*`-Trades — Verhältnis (ØGewinn/ØVerlust) < 1,0
ODER PF < 1 → `auto_m15 = false`.** Dieselbe Latte wie B5 beim Squeeze, damit
sie vergleichbar und **nicht nachträglich verschiebbar** ist.
⚠ Erwartung aus der Messung: die Regel **wird** greifen. Das ist kein Argument
gegen den Test — aber es ist der Grund, warum die Latte **jetzt** steht.
✅ Verifiziert: Toggle an→aus, Snapshot `auto_m15`/`m15_entry_count`, Deploy mit
`--feld auto_m15` (alle 5 Schritte), `ruff F821` sauber (der neue Code sitzt in
einem `except` — der dokumentierte blinde Fleck), 85 Tests, `node --check`.
**Zurück:** Knopf **M15** bzw. `auto_m15 = false`.
## ⚠ CIRCUIT BREAKER BLEIBT AUS — User-Entscheidung (2026-08-19, abends) ## ⚠ CIRCUIT BREAKER BLEIBT AUS — User-Entscheidung (2026-08-19, abends)
Auf den Hinweis, dass BRK **an** und die Notbremse **aus** ist, kam ein Auf den Hinweis, dass BRK **an** und die Notbremse **aus** ist, kam ein
+111 -2
View File
@@ -382,6 +382,19 @@ class TradingEngine:
# ⚠ ECHTE Order — Default AUS (Autonomie nie stillschweigend an). `[trading] # ⚠ ECHTE Order — Default AUS (Autonomie nie stillschweigend an). `[trading]
# auto_squeeze=true` aktiviert. Dedup über (dir, level) des Ausbruchs. # auto_squeeze=true` aktiviert. Dedup über (dir, level) des Ausbruchs.
self._auto_squeeze = self.cfg["trading"].get("auto_squeeze", "false").lower() == "true" self._auto_squeeze = self.cfg["trading"].get("auto_squeeze", "false").lower() == "true"
# ── M15-KARTEN-AUTO-ENTRY (User-Wunsch 2026-08-19, "ich moechte das
# auto trade testen"). ⚠⚠ GEGEN DIE MESSUNG gebaut und deshalb
# Default AUS: `backtest_m15_auto.py` (13.08.) hat genau diese Regel
# gemessen -- die Lesart ist in BEIDEN Halbjahren negativ
# (OeR -0,162/-0,094, PF 0,72/0,84), das 95-%-KI schliesst beide Male
# die Null aus, und sie ist schlechter als die HTF-Richtung UND als
# ihr eigenes Gegenteil. Live bestaetigt (m15_states, entkoppelt):
# 46,8 % Treffer auf 30 min. Der User hat das nach vollstaendiger
# Information ausdruecklich zum TESTEN gewuenscht.
self._auto_m15 = self.cfg["trading"].get("auto_m15", "false").lower() == "true"
self._m15_last_entry_sig = None # Dedup (Richtung, Level) wie im Backtest
self._m15_entry_count = 0
self._last_m15 = None # letzter berechneter Kartenstand
self._squeeze_skip_night = self.cfg["trading"].get("auto_squeeze_skip_night", "true").lower() == "true" self._squeeze_skip_night = self.cfg["trading"].get("auto_squeeze_skip_night", "true").lower() == "true"
# ── WELCHE Stunden ausgesetzt werden (2026-08-05, gemessen `backtest_cost_gate.py`). # ── WELCHE Stunden ausgesetzt werden (2026-08-05, gemessen `backtest_cost_gate.py`).
# War fest 07. Die Messung zeigt: KEINE Stunde ist in beiden Halbjahren negativ — # War fest 07. Die Messung zeigt: KEINE Stunde ist in beiden Halbjahren negativ —
@@ -825,6 +838,7 @@ class TradingEngine:
self._check_pending_fill() # gefuellte Pending-Order zuordnen self._check_pending_fill() # gefuellte Pending-Order zuordnen
self._manage_squeeze_pending() self._manage_squeeze_pending()
self._check_auto_squeeze() # autonomer Entry auf Squeeze-Ausbruch self._check_auto_squeeze() # autonomer Entry auf Squeeze-Ausbruch
self._check_auto_m15() # autonomer Entry auf die gruene M15-Karte
except Exception as e: except Exception as e:
log.error(f"_pos_loop: {e}", exc_info=True) log.error(f"_pos_loop: {e}", exc_info=True)
self._sleep(_POS_S) self._sleep(_POS_S)
@@ -1158,8 +1172,13 @@ class TradingEngine:
# den Squeeze. Der Parameter `pfad` bleibt in der Signatur — die # den Squeeze. Der Parameter `pfad` bleibt in der Signatur — die
# Guard-Kette ist bewusst EINE Quelle für alle autonomen Wege, und ein # Guard-Kette ist bewusst EINE Quelle für alle autonomen Wege, und ein
# künftiger zweiter Weg soll sie wieder benutzen, nicht nachbauen. # künftiger zweiter Weg soll sie wieder benutzen, nicht nachbauen.
if not self._auto_squeeze: # ⚠ Pfad-abhaengig seit 2026-08-19: der M15-Auto-Entry nutzt DIESELBE
return "Auto-Squeeze aus" # Guard-Kette (Nacht, Circuit, News) statt sie nachzubauen -- genau das,
# wofuer der Parameter laut Docstring gedacht ist.
_an = {"squeeze": self._auto_squeeze,
"m15": getattr(self, "_auto_m15", False)}.get(pfad, self._auto_squeeze)
if not _an:
return ("Auto-M15 aus" if pfad == "m15" else "Auto-Squeeze aus")
skip = self._squeeze_skip_night skip = self._squeeze_skip_night
if self._circuit_halted(): if self._circuit_halted():
return "Circuit-Breaker" return "Circuit-Breaker"
@@ -1179,6 +1198,90 @@ class TradingEngine:
"""Alias — `_check_auto_squeeze` ruft weiterhin diesen Namen.""" """Alias — `_check_auto_squeeze` ruft weiterhin diesen Namen."""
return self._auto_guard("squeeze") return self._auto_guard("squeeze")
def set_auto_m15(self, on: bool) -> bool:
"""M15-Karten-Auto-Entry an/aus. Rueckgabe = neuer Zustand."""
self._auto_m15 = bool(on)
self._m15_last_entry_sig = None
log.info(f"Auto-M15-Entry {'AN' if self._auto_m15 else 'AUS'}")
self._save_runtime_state()
return self._auto_m15
def _check_auto_m15(self):
"""Autonomer Entry auf die GRUENE, gerichtete M15-Karte (Default AUS).
GEGEN DIE MESSUNG. `backtest_m15_auto.py` (13.08.): die Lesart ist in
BEIDEN Halbjahren negativ (OeR -0,162 / -0,094, PF 0,72 / 0,84), das
95-%-KI schliesst beide Male die Null aus, alle Nachbar-Schwellen werden
monoton schlechter, und sie ist schlechter als die HTF-Richtung UND als
ihr eigenes Gegenteil. Auf User-Wunsch zum TESTEN gebaut.
ABWEICHUNG VON DER GEMESSENEN VARIANTE, ausdruecklich benannt: gemessen
wurde der Einstieg AM Level mit Fill bei Beruehrung; hier wird zum MARKT
eingestiegen. Im Projekt ist der Markt-Einstieg mehrfach als der
schlechtere gemessen (Squeeze +0,456 -> -0,158 allein durch den Preis).
Die Live-Zahlen sind also eher noch unter den -0,16/-0,09 zu erwarten.
Eine ruhende Order haette den geteilten `_pending_ziel`-Manager
gebraucht, in dem der Squeeze Vorrang hat -- das ist ein eigener Umbau.
Dedup 1x je Episode ueber (Richtung, Level) -- exakt der Backtest-
Schluessel `(d_les, nah["level"])`. Erbt die volle Guard-Kette
(`_auto_guard("m15")`: Nacht, Circuit-Breaker, News-Blackout) sowie
Startup-Schonfrist, Flat-Bedingung und die Wiedereinstiegs-Sperren.
"""
if not self._auto_m15:
return
try:
if self._in_startup_grace():
return
s = getattr(self, "_last_m15", None)
if not s or s.get("status") != "gruen":
self._m15_last_entry_sig = None # re-armt bei Nicht-Gruen
return
les = s.get("lesart")
if les not in ("auf", "ab"):
self._m15_last_entry_sig = None
return
nah = s.get("nah") or {}
lvl = nah.get("level")
if lvl is None:
return
d = 1 if les == "auf" else -1 # wie im Backtest
sig = (d, round(float(lvl), 3))
if sig == self._m15_last_entry_sig:
return # dieselbe Episode
if (self.trader.snapshot() or {}).get("lots"):
return # nur FLAT
grund = self._auto_guard("m15")
if grund:
return
# Wiedereinstiegs-Sperren teilen wir mit dem Squeeze (gleiche Logik,
# gleiche Begruendung: Open-Close-Kaskaden nach einem Auto-Close).
now = time.time()
if (self._sr_close_dir == d
and now - self._sr_close_ts < _SQUEEZE_SR_COOLDOWN_S):
return
if (self._pos_close_dir == d
and now - self._pos_close_ts < _SQUEEZE_REENTRY_COOLDOWN_S):
return
self._m15_last_entry_sig = sig
want = "long" if d > 0 else "short"
# ⚠ Setup-TAG ist Pflicht, nicht Kosmetik: ohne ihn sind die Trades
# in der DB von manuellen NICHT unterscheidbar und der Test spaeter
# nicht auswertbar (Deployment-Drift Fall 8, 06.08.: vier reale
# Squeeze-Trades landeten als setup=NULL, damit zaehlten B4-Monitor
# und Abbruchregel NULL Bot-Trades).
self._last_rec["setup"] = f"AUTOM15_{want.upper()}"
fn = self.trader.open_long if d > 0 else self.trader.open_short
err = self._open(fn, want, source="auto_m15")
if err:
log.warning(f"Auto-M15-Entry fehlgeschlagen: {err}")
return
self._m15_entry_count += 1
log.info(f"AUTO-M15-ENTRY: {want.upper()} auf gruene Karte "
f"(Lesart {les}, Level {lvl}) — selbstaendig eroeffnet")
except Exception as e:
log.warning(f"_check_auto_m15: {e}")
def _check_pending_fill(self): def _check_pending_fill(self):
"""Hat eine von UNS platzierte Pending-Order gefuellt? Dann nachtragen. """Hat eine von UNS platzierte Pending-Order gefuellt? Dann nachtragen.
@@ -2161,6 +2264,8 @@ class TradingEngine:
if "manual_margin" in st: if "manual_margin" in st:
from core.config import set_manual_margin as _set from core.config import set_manual_margin as _set
self._manual_margin = _set(st["manual_margin"] or 0) self._manual_margin = _set(st["manual_margin"] or 0)
if "auto_m15" in st:
self._auto_m15 = bool(st["auto_m15"])
if "cb_remember" in st: if "cb_remember" in st:
self._cb_remember = float(st["cb_remember"] or 8.0) self._cb_remember = float(st["cb_remember"] or 8.0)
if "cb_limit_pct" in st: if "cb_limit_pct" in st:
@@ -2200,6 +2305,7 @@ class TradingEngine:
# 0 = aus. So ueberlebt auch die Hoehe den Neustart. # 0 = aus. So ueberlebt auch die Hoehe den Neustart.
"cb_limit_pct": getattr(self, "_cb_limit_pct", 0.0), "cb_limit_pct": getattr(self, "_cb_limit_pct", 0.0),
"cb_remember": getattr(self, "_cb_remember", 8.0), "cb_remember": getattr(self, "_cb_remember", 8.0),
"auto_m15": getattr(self, "_auto_m15", False),
# Kegel-ACI-Skalen (2026-08-08): ohne Persistenz waere # Kegel-ACI-Skalen (2026-08-08): ohne Persistenz waere
# die muehsam erlernte Kalibrierung nach jedem Neustart # die muehsam erlernte Kalibrierung nach jedem Neustart
# weg und liefe von 1,0 neu an. ⚠ JSON-Schluessel sind # weg und liefe von 1,0 neu an. ⚠ JSON-Schluessel sind
@@ -4181,6 +4287,7 @@ class TradingEngine:
# die Fehlerklasse, fuer die der Linter am 07.08. eingebaut wurde. # die Fehlerklasse, fuer die der Linter am 07.08. eingebaut wurde.
_m15 = self._m15_setup(market, wave_snap, _cone, _m15 = self._m15_setup(market, wave_snap, _cone,
self._alignment_cached(), wave_signal) self._alignment_cached(), wave_signal)
self._last_m15 = _m15 # fuer `_check_auto_m15` im 1-s-Loop
self._log_m15_state(_m15, market) self._log_m15_state(_m15, market)
self._check_m15_alert(_m15) # Telegram bei Flanke auf GRUEN self._check_m15_alert(_m15) # Telegram bei Flanke auf GRUEN
self._log_cone_check(_cone) self._log_cone_check(_cone)
@@ -4352,6 +4459,8 @@ class TradingEngine:
# ⚠ Eigenes Fenster (ab 01.08.) — NICHT dasselbe wie # ⚠ Eigenes Fenster (ab 01.08.) — NICHT dasselbe wie
# `squeeze_monitor.live` (alle Trades). s. `_squeeze_b5_cached`. # `squeeze_monitor.live` (alle Trades). s. `_squeeze_b5_cached`.
"squeeze_b5": self._squeeze_b5_cached(), "squeeze_b5": self._squeeze_b5_cached(),
"auto_m15": self._auto_m15,
"m15_entry_count": self._m15_entry_count,
# Kennzahlen der MANUELLEN Trades für die gleichnamige Karte # Kennzahlen der MANUELLEN Trades für die gleichnamige Karte
# (2026-08-04). Rein deskriptiv; ~120 s gecacht, damit der heiße # (2026-08-04). Rein deskriptiv; ~120 s gecacht, damit der heiße
# Snapshot-Pfad nicht je Abruf die DB aggregiert. # Snapshot-Pfad nicht je Abruf die DB aggregiert.
File diff suppressed because it is too large Load Diff
+10
View File
@@ -353,6 +353,16 @@ async def toggle_srclose(x_auth_token: str | None = Header(default=None)):
return {"ok": True, "enabled": state} return {"ok": True, "enabled": state}
@app.post("/api/autom15")
async def toggle_autom15(x_auth_token: str | None = Header(default=None)):
"""M15-Karten-Auto-Entry an/aus (User-Test 2026-08-19, gemessen negativ)."""
_require_auth(x_auth_token)
eng = app.state.engine
state = eng.set_auto_m15(not eng._auto_m15)
log.info(f"[WEB] Auto-M15-Entry {'AN' if state else 'AUS'}")
return {"ok": True, "enabled": state}
@app.post("/api/circuit") @app.post("/api/circuit")
async def toggle_circuit(x_auth_token: str | None = Header(default=None)): async def toggle_circuit(x_auth_token: str | None = Header(default=None)):
"""Tagesverlust-Stopp (Circuit Breaker) an/aus (User-Wunsch 2026-08-19).""" """Tagesverlust-Stopp (Circuit Breaker) an/aus (User-Wunsch 2026-08-19)."""
+9
View File
@@ -1155,6 +1155,14 @@ function render(d) {
// Auto-Squeeze-ZUSTAND bleibt in der Breakout-Karte sichtbar -- nur sein // Auto-Squeeze-ZUSTAND bleibt in der Breakout-Karte sichtbar -- nur sein
// Schalter ist weg (jetzt POST-Endpunkt bzw. ini). // Schalter ist weg (jetzt POST-Endpunkt bzw. ini).
const cb = d.circuit_breaker || {}; const cb = d.circuit_breaker || {};
const m15b = $streng("btn-m15");
if (m15b) {
m15b.classList.toggle("on", !!d.auto_m15);
m15b.title = d.auto_m15
? "Auto-Entry auf die gruene M15-Karte AN (" + (d.m15_entry_count || 0)
+ " Entries). ACHTUNG: gemessen negativ -- reiner Test."
: "Auto-Entry auf die gruene M15-Karte AUS (gemessen negativ).";
}
const srb = $streng("btn-sr"); const srb = $streng("btn-sr");
if (srb) { if (srb) {
srb.classList.toggle("on", !!d.auto_sr_close); srb.classList.toggle("on", !!d.auto_sr_close);
@@ -1745,6 +1753,7 @@ _updateMuteBtn();
// Toggle-Buttons (AUTO/TRAIL/S-R-Close) — ohne Bestätigung // Toggle-Buttons (AUTO/TRAIL/S-R-Close) — ohne Bestätigung
$("btn-cb").onclick = () => toggle("api/circuit", "Circuit Breaker"); $("btn-cb").onclick = () => toggle("api/circuit", "Circuit Breaker");
$("btn-sr").onclick = () => toggle("api/srclose", "S/R-Auto-Close"); $("btn-sr").onclick = () => toggle("api/srclose", "S/R-Auto-Close");
$("btn-m15").onclick = () => toggle("api/autom15", "M15-Auto-Entry (gemessen negativ!)");
// (🎯 SIG entfernt 2026-08-12 — s. renderOrderButtons oben) // (🎯 SIG entfernt 2026-08-12 — s. renderOrderButtons oben)
$("btn-trail").onclick = () => toggle("api/trail", "Trailing"); $("btn-trail").onclick = () => toggle("api/trail", "Trailing");
$("srclose-btn").onclick = () => toggle("api/srclose", "Auto-S/R-Close"); $("srclose-btn").onclick = () => toggle("api/srclose", "Auto-S/R-Close");
+7 -2
View File
@@ -12,7 +12,7 @@
⚠ LOKAL eingebunden, kein CDN: die PWA laeuft ueber WireGuard ⚠ LOKAL eingebunden, kein CDN: die PWA laeuft ueber WireGuard
und muss offline funktionieren. --> und muss offline funktionieren. -->
<link rel="stylesheet" href="pico.min.css?v=1"> <link rel="stylesheet" href="pico.min.css?v=1">
<link rel="stylesheet" href="style.css?v=180"> <link rel="stylesheet" href="style.css?v=181">
</head> </head>
<body> <body>
<!-- Modul-Menü (ganz oben) --> <!-- Modul-Menü (ganz oben) -->
@@ -355,6 +355,11 @@
`auto_sr_close` aus demselben Snapshot und koennen nicht `auto_sr_close` aus demselben Snapshot und koennen nicht
auseinanderlaufen. --> auseinanderlaufen. -->
<button class="btn tog" id="btn-sr" title="Auto-Close am S/R-Level an/aus (P(break)-gegatet: schliesst nur, wenn das Level wahrscheinlich haelt)">S/R</button> <button class="btn tog" id="btn-sr" title="Auto-Close am S/R-Level an/aus (P(break)-gegatet: schliesst nur, wenn das Level wahrscheinlich haelt)">S/R</button>
<!-- M15-Karten-Auto-Entry (User-Test 2026-08-19). ⚠ GEGEN DIE MESSUNG:
backtest_m15_auto.py -> Lesart beidhaelftig negativ (OeR -0,162/
-0,094, PF 0,72/0,84), KI ohne Null, schlechter als die
HTF-Richtung UND als ihr eigenes Gegenteil. Default AUS. -->
<button class="btn tog" id="btn-m15" title="Auto-Entry auf die gruene M15-Karte. ACHTUNG: gemessen negativ (OeR -0,162/-0,094) — reiner Test.">M15</button>
<!-- 🎯 SIG (Auto-Signal-Entry) ENTFERNT 2026-08-12: seit 01.08. aus und auf <!-- 🎯 SIG (Auto-Signal-Entry) ENTFERNT 2026-08-12: seit 01.08. aus und auf
BEIDEN Ausfuehrungs-Achsen gemessen negativ (Markt alle 8 Felder, BEIDEN Ausfuehrungs-Achsen gemessen negativ (Markt alle 8 Felder,
ruhende Order mit Touch-Fill alle 6 und schlechter als Markt). --> ruhende Order mit Touch-Fill alle 6 und schlechter als Markt). -->
@@ -376,6 +381,6 @@
</div> </div>
<div id="toast" class="toast hidden"></div> <div id="toast" class="toast hidden"></div>
<script src="app.js?v=180"></script> <script src="app.js?v=181"></script>
</body> </body>
</html> </html>