Breakout-Karte vorbereitet (inaktiv bis Neustart) + Bewertung der Margin-Idee
User-Idee: 40 % Margin manuell, 50 % fuer Breakout reservieren, neue Karte. Bewertung: (1) 40 % ist der groesste gemessene Hebel (MaxDD 82,8 %) und ein Schalter ohne Neustart. (2) Reserve ist technisch moeglich (Konto ist RETAIL_HEDGING), aber _check_auto_squeeze feuert 'nur FLAT' und engine.py hat 17 Einzel-Positions-Annahmen -- Kern-Umbau, kein Parameter. Zudem steht die Zuteilung gegen die Messung: autonom -4,71 EUR/Lot gegen Mensch +1,56 EUR/Lot. Live-Befund macht (1) dringlich: freie Margin -6,21 EUR, Margin-Level 99,3 %. Es gibt derzeit nichts zu reservieren. Gebaut (inaktiv): history.fetch_squeeze_since, engine._squeeze_b5_cached (120 s gecacht), Snapshot-Feld squeeze_b5, Karte #card-brk. Eigenes Fenster ab 01.08. -- squeeze_monitor.live rechnet ueber alle 42 Trades, B5 zaehlt 11. Die Karte zeigt beide Zahlen, weil der Monitor 'ontrack' aus der MECHANIK meldet, waehrend live Verhaeltnis 0,14 / PF 0,39 steht. Live aendert sich nichts: Karte ist hidden, renderBrk blendet sie aus solange squeeze_b5 fehlt. Aktiv nach dem naechsten Neustart (wartet auf den Trade). BEINAHE-SCHADEN: ein UnicodeEncodeError liess web/app.js mit 0 Bytes zurueck. node --check bestand trotzdem -- eine leere Datei ist gueltiges JS. Gefangen hat es erst der Groessenvergleich. Neue Regel: erst .tmp schreiben, Groesse pruefen, dann os.replace. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
3affe51030
commit
30cb77b795
@@ -7434,6 +7434,47 @@ vollständig.
|
||||
⚠ **Verifikation der Zustellung steht aus** — sie erfolgt mit dem Report am
|
||||
nächsten Morgen um 07:30. Die Bausteine sind einzeln live gegengeprüft.
|
||||
|
||||
## ⚙ BREAKOUT-KARTE VORBEREITET — aktiv erst nach dem nächsten Neustart (2026-08-19, v=176)
|
||||
|
||||
User-Idee: (1) manuell fest 40 % Margin, (2) 50 % für Breakout reservieren,
|
||||
(3) neue Dashboard-Karte. **Bewertung:**
|
||||
| Punkt | Urteil |
|
||||
|---|---|
|
||||
| ① 40 % fest | ✅ grösster gemessener Hebel (MaxDD **82,8 %**, schlechtester Trade −381 €). **Ein Schalter, kein Umbau** — Feld „Einsatz %“, ohne Neustart, nur auf neue Positionen. |
|
||||
| ② 50 % Reserve | ⚠ Konto ist **RETAIL_HEDGING**, also technisch möglich — aber: `_check_auto_squeeze` feuert **„nur FLAT“**, dazu **17 Einzel-Positions-Annahmen** in `engine.py` (Trailing, Notfall-Stop, S/R-Close, Time-Stop, Breaker verwalten je EINE Position). Kern-Umbau, kein Parameter. |
|
||||
| ③ Karte | ✅ gebaut, s. u. |
|
||||
|
||||
⚠⚠ **Der Live-Befund macht ① dringlich:** Balance 937,40 € · Equity 877,41 € ·
|
||||
Margin belegt 883,62 € → **freie Margin −6,21 €, Margin-Level 99,3 %**. EINE
|
||||
Position (1,19 Lot) frisst das ganze Konto. **Es gibt derzeit nichts zu
|
||||
reservieren** — die Reserve aus ② entsteht überhaupt erst durch ①.
|
||||
⚠⚠ **Und die Zuteilung steht gegen die Messung:** seit 01.08. je Lot
|
||||
**autonom −4,71 €** (n=11) gegen **Mensch +1,56 €** (n=185). ② gäbe dem
|
||||
gemessen schlechteren Pfad den grösseren Anteil; 40+50 lassen zudem nur 10 %
|
||||
Puffer. **Empfehlung: ① und ③ jetzt, ② erst wenn freie Margin existiert UND
|
||||
der autonome Pfad auf einem NEU vorab fixierten Fenster nicht negativ ist.**
|
||||
|
||||
**Gebaut (inaktiv):** `history.fetch_squeeze_since` · `engine._squeeze_b5_cached`
|
||||
(~120 s gecacht, Muster `_alignment_cached`) · Snapshot-Feld `squeeze_b5` ·
|
||||
Karte `#card-brk` (Zustand · Squeeze jetzt · liegende Orders · **B5-Stand**).
|
||||
⚠ **Eigenes Fenster ab 01.08.** — `squeeze_monitor.live` rechnet über **alle 42**
|
||||
Trades, B5 zählt **11**. Beide ungetrennt zu zeigen wäre dieselbe stille
|
||||
Fenster-Verwechslung wie bei `pbreak_accuracy_v2`.
|
||||
⚠ Die Karte nennt beide Zahlen: der Monitor meldet **`ontrack`** aus der
|
||||
**Mechanik** (ØR +0,163 / PF 1,24), während live **Verhältnis 0,14 / PF 0,39**
|
||||
steht. Die Lücke IST der B4-Befund — eine der beiden allein wäre irreführend.
|
||||
✅ **Live ändert sich nichts:** die Karte ist `hidden` und `renderBrk` blendet
|
||||
sie aus, solange `squeeze_b5` fehlt. Aktiv nach dem nächsten Neustart — der
|
||||
wartet auf User-Wunsch, bis die offene Position zu ist.
|
||||
|
||||
⚠⚠ **BEINAHE-SCHADEN, dokumentiert weil es eine Fehlerklasse ist:** ein
|
||||
`UnicodeEncodeError` (Emoji-Escapes) brach mitten im Schreiben ab und liess
|
||||
**`web/app.js` mit 0 Bytes** zurück — `io.open(p,"w")` kürzt VOR dem Schreiben.
|
||||
⚠ **`node --check` bestand trotzdem: eine LEERE Datei ist gültiges JS.** Die
|
||||
Syntaxprüfung allein hätte den Totalverlust durchgewinkt; gefangen hat ihn erst
|
||||
der Grössenvergleich. **Regel: Datei erst in `.tmp` schreiben, Grösse gegen das
|
||||
Original prüfen, dann `os.replace`** — so ist es jetzt gemacht.
|
||||
|
||||
## ✅ BRK BLEIBT AN (User 2026-08-19) — und die 13-tägige Flaute war kein Defekt
|
||||
|
||||
User: „Breakout-Squeeze soll an bleiben. Rechne und überprüfe erneut.“
|
||||
|
||||
@@ -3248,6 +3248,48 @@ class TradingEngine:
|
||||
self._align_ts = now
|
||||
return getattr(self, "_align_cache", None)
|
||||
|
||||
def _squeeze_b5_cached(self) -> dict | None:
|
||||
"""B5-Stand des Auto-Squeeze fuer die Breakout-Karte (2026-08-19).
|
||||
|
||||
⚠⚠ WARUM EIN EIGENES FELD und nicht `squeeze_monitor.live`: der Monitor
|
||||
rechnet ueber ALLE SQUEEZE_*-Trades (n=42). Die B5-Abbruchregel zaehlt
|
||||
aber ausdruecklich **ab dem 01.08.** (n=11). Beide Zahlen im selben Bild
|
||||
zu zeigen, ohne sie zu trennen, waere genau die Sorte stille
|
||||
Fenster-Verwechslung, an der `pbreak_accuracy_v2` und die
|
||||
Verdict-Faelligkeit schon aufgelaufen sind.
|
||||
|
||||
⚠ Der Monitor meldet zudem `verdict: ontrack` aus der **Mechanik**
|
||||
(Regel neu gerechnet, OeR +0,163 / PF 1,24) — waehrend die LIVE-Bilanz
|
||||
im selben Moment bei Verhaeltnis 0,14 / PF 0,39 steht. Genau diese
|
||||
Luecke ist der B4-Befund; die Karte muss beide Zahlen nebeneinander
|
||||
zeigen, sonst liest sich 'ontrack' wie eine Entwarnung.
|
||||
|
||||
DB-Query ~120 s gecacht (Muster wie `_alignment_cached`)."""
|
||||
now = time.time()
|
||||
if now - getattr(self, "_b5_ts", 0.0) > 120:
|
||||
self._b5_cache = None
|
||||
try:
|
||||
ab = int(datetime(2026, 8, 1, tzinfo=_BERLIN).timestamp())
|
||||
rows = self.history.fetch_squeeze_since(ab)
|
||||
g = [x for x in rows if x > 0]
|
||||
v = [x for x in rows if x <= 0]
|
||||
og = (sum(g) / len(g)) if g else 0.0
|
||||
ov = abs(sum(v) / len(v)) if v else 0.0
|
||||
self._b5_cache = {
|
||||
"n": len(rows), "ziel": 20,
|
||||
"wins": len(g), "losses": len(v),
|
||||
"avg_win": round(og, 2), "avg_loss": round(-ov, 2),
|
||||
# die beiden Groessen, an denen die Regel haengt
|
||||
"ratio": round(og / ov, 2) if ov else None,
|
||||
"pf": round(sum(g) / abs(sum(v)), 2) if v and sum(v) else None,
|
||||
"sum_eur": round(sum(rows), 2),
|
||||
"latte": 1.0,
|
||||
}
|
||||
except Exception as e:
|
||||
log.debug(f"squeeze_b5: {e}")
|
||||
self._b5_ts = now
|
||||
return getattr(self, "_b5_cache", None)
|
||||
|
||||
def _hl_ctx_refresh(self):
|
||||
"""Holt den HL-Kontext im Hintergrund (s. Aufrufstelle im Trend-Loop)."""
|
||||
try:
|
||||
@@ -4231,6 +4273,10 @@ class TradingEngine:
|
||||
# kostet ungenutzt nichts (sie laeuft nur beim Aufruf).
|
||||
"hl_ctx": getattr(self, "_hl_ctx", None),
|
||||
"rec_track": self._rec_track_cached(),
|
||||
# B5-Stand des Auto-Squeeze fuer die Breakout-Karte (2026-08-19).
|
||||
# ⚠ Eigenes Fenster (ab 01.08.) — NICHT dasselbe wie
|
||||
# `squeeze_monitor.live` (alle Trades). s. `_squeeze_b5_cached`.
|
||||
"squeeze_b5": self._squeeze_b5_cached(),
|
||||
# Kennzahlen der MANUELLEN Trades für die gleichnamige Karte
|
||||
# (2026-08-04). Rein deskriptiv; ~120 s gecacht, damit der heiße
|
||||
# Snapshot-Pfad nicht je Abruf die DB aggregiert.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -855,6 +855,32 @@ class HistoryLogger:
|
||||
"pct": round(100.0 * (r["c"] or 0) / (r["n"] or 1), 1)}
|
||||
return out
|
||||
|
||||
def fetch_squeeze_since(self, ab: int) -> list:
|
||||
"""P&L aller geschlossenen SQUEEZE_*-Trades ab Epoch `ab` (2026-08-19).
|
||||
|
||||
⚠ Bewusst NUR `setup LIKE 'SQUEEZE%'` — die `setup`-Spalte taugt NICHT
|
||||
als allgemeine Bot/Mensch-Trennung: `engine._open` schreibt die
|
||||
Wellenlage auch bei MANUELLEN Trades mit (`WAVE`, n=124). Nur
|
||||
`SQUEEZE_*` ist autonom eroeffnet. Ein erster Auswertungsversuch am
|
||||
13.08. hat genau das verwechselt und dem Bot 152 Trades zugeschrieben.
|
||||
|
||||
⚠ NICHT je Lot normiert: die B5-Regel ist ausdruecklich auf
|
||||
OeGewinn/OeVerlust in EURO fixiert worden. Sie hier still auf eine
|
||||
andere Einheit umzustellen waere ein nachtraegliches Verschieben der
|
||||
Latte.
|
||||
|
||||
Fail-open (leere Liste) — `core/history.py` hat bewusst keinen Logger.
|
||||
"""
|
||||
try:
|
||||
with self._connect() as c:
|
||||
return [float(r[0]) for r in c.execute(
|
||||
"SELECT pnl FROM trades "
|
||||
" WHERE setup LIKE 'SQUEEZE%' AND exit_time IS NOT NULL "
|
||||
" AND pnl IS NOT NULL AND entry_time > ? "
|
||||
" ORDER BY entry_time", (int(ab),))]
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
def alignment_stats(self, last_n: int = 0) -> dict:
|
||||
"""Ausrichtungs-Split: liefen die Trades MIT, GEGEN oder OHNE die Empfehlung?
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+53
@@ -153,6 +153,58 @@ function beepRecommendation(sig, isNew) {
|
||||
// muss jedes Gate EINZELN passieren. Ein Gate, das fällt, lässt sich nicht
|
||||
// durch ein anderes ausgleichen.
|
||||
// ══════════════════════════════════════════════════════════════════════════
|
||||
// Breakout-Autotrader-Karte (2026-08-19). Nur ANZEIGE aus vorhandenen
|
||||
// Snapshot-Feldern -- hier wird nichts neu gerechnet.
|
||||
// Die Karte bleibt VERSTECKT, solange `squeeze_b5` fehlt (aelterer Server, das
|
||||
// Feld gibt es erst nach einem Neustart). Eine halb gefuellte Karte waere
|
||||
// schlimmer als keine: sie saehe aus wie ein Zustand statt wie eine fehlende
|
||||
// Quelle.
|
||||
function renderBrk(d) {
|
||||
const box = $streng("card-brk");
|
||||
if (!box) return;
|
||||
const b5 = d.squeeze_b5;
|
||||
if (!b5) { box.classList.add("hidden"); return; }
|
||||
box.classList.remove("hidden");
|
||||
|
||||
const an = !!d.auto_squeeze;
|
||||
const nh = (d.squeeze_night_hours || []).map((h) => h + ":00").join(", ");
|
||||
$("brk-state").textContent = (an ? "AN" : "AUS")
|
||||
+ (d.squeeze_pending ? " · ruhende Stop-Order" : " · Market-Fallback")
|
||||
+ (nh ? " · Nachtsperre " + nh : "");
|
||||
$("brk-state").className = an ? "ok" : "warn";
|
||||
|
||||
const sq = (d.wave || {}).squeeze || {};
|
||||
const st = sq.state;
|
||||
$("brk-squeeze").textContent =
|
||||
st === "active" ? "AUSBRUCH " + (sq.dir || "") + " @ " + (sq.level ?? "?")
|
||||
: st === "armed" ? "komprimiert — Ausbruch steht bevor"
|
||||
: "keine Kompression (Box " + (sq.box_atr ?? "?") + "×ATR)";
|
||||
|
||||
const pl = d.pending_levels || [];
|
||||
$("brk-pending").textContent = pl.length
|
||||
? pl.length + " liegend (" + (d.pending_quelle || "?") + ")"
|
||||
: "keine — " + (an ? "Squeeze nicht armiert oder Position offen" : "Trader aus");
|
||||
|
||||
// B5: der Stand der einzigen Regel, die die Autonomie beenden kann.
|
||||
const r = b5.ratio, pf = b5.pf;
|
||||
const erf = r != null && pf != null && r >= b5.latte && pf >= 1;
|
||||
$("brk-b5").textContent = b5.n + "/" + b5.ziel + " Trades · Verhältnis "
|
||||
+ (r == null ? "—" : r.toFixed(2)) + " · PF "
|
||||
+ (pf == null ? "—" : pf.toFixed(2))
|
||||
+ " · " + b5.sum_eur.toFixed(2) + " €";
|
||||
$("brk-b5").className = erf ? "ok" : "bad";
|
||||
|
||||
const el = $("brk-note");
|
||||
if (el) {
|
||||
el.textContent = erf
|
||||
? "Latte (Verhältnis ≥ 1,0 UND PF ≥ 1) erfüllt."
|
||||
: "⚠ Latte verfehlt (Ziel: Verhältnis ≥ 1,0 UND PF ≥ 1). Der Monitor "
|
||||
+ "im Statistik-Tab meldet daneben „ontrack“ — das kommt aus der MECHANIK "
|
||||
+ "(Regel neu gerechnet), nicht aus diesen echten Trades. Die Lücke "
|
||||
+ "zwischen beiden ist der Befund, kein Widerspruch.";
|
||||
}
|
||||
}
|
||||
|
||||
function renderM15(s) {
|
||||
const st = $("m15-status");
|
||||
if (!s) { st.className = "m15-status"; st.textContent = "— keine Daten"; return; }
|
||||
@@ -936,6 +988,7 @@ function render(d) {
|
||||
|
||||
// ── Gesamtempfehlung (aggregiert) ───────
|
||||
renderM15(d.m15_setup);
|
||||
renderBrk(d);
|
||||
renderKontext(d);
|
||||
renderCircuitBreaker(d.circuit_breaker);
|
||||
renderPatterns(d.patterns);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+19
-2
@@ -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=175">
|
||||
<link rel="stylesheet" href="style.css?v=176">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modul-Menü (ganz oben) -->
|
||||
@@ -156,6 +156,23 @@
|
||||
<div class="reasons" id="wave-reasons" title="Die Begründungen, aus denen sich Richtung und Konfidenz zusammensetzen."></div>
|
||||
</section>
|
||||
|
||||
<!-- Breakout-Autotrader (User-Wunsch 2026-08-19). ⚠ Der autonome Pfad handelt
|
||||
echtes Geld, seine Abbruchregel (B5) stand bisher NUR im taeglichen
|
||||
Report. Diese Karte macht ihn sichtbar — Zustand, liegende Orders und
|
||||
B5-Stand an einer Stelle.
|
||||
⚠⚠ Sie zeigt BEIDE Zahlen getrennt: die B4-'Mechanik' (Regel neu
|
||||
gerechnet, sieht gut aus) und die LIVE-Bilanz (verliert). Genau diese
|
||||
Luecke IST der Befund — eine der beiden allein waere irrefuehrend.
|
||||
Reine ANZEIGE: schaltet nichts, blockiert nichts. -->
|
||||
<section class="card wide hidden" id="card-brk">
|
||||
<h2 title="Autonomer Entry auf den Squeeze-Ausbruch. Einziges 2-Stichproben-validiertes Auto-Setup des Projekts.">🚀 Breakout-Autotrader</h2>
|
||||
<div class="kv"><span>Zustand</span><b id="brk-state">—</b></div>
|
||||
<div class="kv"><span>Squeeze jetzt</span><b id="brk-squeeze">—</b></div>
|
||||
<div class="kv"><span>Liegende Orders</span><b id="brk-pending">—</b></div>
|
||||
<div class="kv" title="B5 = die VORAB fixierte Abbruchregel: nach 20 Trades ab 01.08. muss Verhaeltnis (OeGewinn/OeVerlust) >= 1,0 UND PF >= 1 sein."><span>B5-Regel</span><b id="brk-b5">—</b></div>
|
||||
<div id="brk-note" class="hint"></div>
|
||||
</section>
|
||||
|
||||
<section class="card wide" id="card-kontext">
|
||||
<h2 title="Drei unabhaengige Kontext-Anzeigen. KEINE Empfehlung und keine Richtungsaussage - die Aggregation zu einer Gesamtempfehlung wurde am 08.08. entfernt.">Marktkontext</h2>
|
||||
<!-- Zeitebenen-Ampel (M1/M5/M15/M30/H1) -->
|
||||
@@ -370,6 +387,6 @@
|
||||
</div>
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
|
||||
<script src="app.js?v=175"></script>
|
||||
<script src="app.js?v=176"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user