Circuit Breaker: Tagesverlust-Stopp (daily_loss_limit_pct=8) — Überlebens-Basis

User-Ziel autonomes Handeln → Notbremse im Code (vorher abgelehnt, reaktiviert).
Erreicht der Tages-P&L (realisiert+offen) -8% der Balance, schließt der Bot die
Position und sperrt neue Auto-Trades bis zum naechsten Tag. _check_circuit_breaker
im _pos_loop (Startup-Grace, ~30s realized-cache, Berlin-Datum-Reset), blockt
Auto-Squeeze, Snapshot + roter Frontend-Banner (v=115). 80%-Margin bleibt (User).
Mit 5 Szenarien getestet.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Axel Hocks
2026-07-27 17:39:55 +02:00
co-authored by Claude Opus 4.8
parent 873b67a521
commit cd8ee5b01b
6 changed files with 148 additions and 5 deletions
+20
View File
@@ -205,6 +205,25 @@ function renderStructure(s) {
}
}
// Circuit Breaker — roter Banner wenn ausgelöst, bernstein wenn nah (>60% des Limits).
function renderCircuitBreaker(cb) {
const el = $("circuit-banner");
if (!el) return;
if (!cb || !cb.enabled) { el.className = "circuit hidden"; el.textContent = ""; return; }
const limit = cb.limit_eur, day = cb.day_total;
if (cb.tripped) {
el.className = "circuit tripped";
el.textContent = `🛑 CIRCUIT BREAKER AKTIV — Tagesverlust ${fmt(day, 2)} € erreicht ` +
`(Limit ${fmt(limit, 0)} €). Keine Auto-Trades mehr heute.`;
} else if (limit && day < 0 && Math.abs(day) >= 0.6 * limit) {
el.className = "circuit near";
el.textContent = `⚠ Tagesverlust ${fmt(day, 2)} € — Stopp bei ${fmt(limit, 0)}` +
`(${Math.round(100 * Math.abs(day) / limit)} % erreicht)`;
} else {
el.className = "circuit hidden"; el.textContent = "";
}
}
function render(d) {
// ── Header ──────────────────────────────
$("conn").className = "dot " + (d.connected ? "on" : "off");
@@ -294,6 +313,7 @@ function render(d) {
// ── Gesamtempfehlung (aggregiert) ───────
renderVerdict(d.verdict || {}, d);
renderCircuitBreaker(d.circuit_breaker);
renderStructure(d.structure);
renderStatsCompact(d.stats_compact, d.market);
renderGaps(d.gaps, d.market);
+4 -2
View File
@@ -6,7 +6,7 @@
<meta name="theme-color" content="#0d1117">
<title>Oil · MT5</title>
<link rel="manifest" href="manifest.json">
<link rel="stylesheet" href="style.css?v=114">
<link rel="stylesheet" href="style.css?v=115">
</head>
<body>
<!-- Modul-Menü (ganz oben) -->
@@ -40,6 +40,8 @@
</header>
<main id="view-dash" class="view">
<!-- Circuit Breaker (Tagesverlust-Stopp) — roter Banner, nur wenn ausgelöst/nah -->
<div id="circuit-banner" class="circuit hidden"></div>
<!-- Aktueller Trade (nur bei offener Position) — Anzeige + SL/TP/Close editierbar -->
<section class="card wide trade-bar hidden" id="trade-bar">
<h2 class="tb-title">aktueller Trade läuft</h2>
@@ -218,6 +220,6 @@
<div id="toast" class="toast hidden"></div>
<script src="lightweight-charts.standalone.production.js?v=114"></script>
<script src="app.js?v=114"></script>
<script src="app.js?v=115"></script>
</body>
</html>
+7
View File
@@ -134,6 +134,13 @@ main{display:grid;grid-template-columns:1fr 1fr;gap:11px;padding:11px}
.tb-btn:active{filter:brightness(1.3)}
/* ── Gesamtempfehlung ───────────────────── */
/* Circuit Breaker Banner (Tagesverlust-Stopp) — ganz oben, rot bei ausgelöst */
.circuit{margin:0 0 11px;padding:11px 14px;border-radius:var(--r);font-weight:700;
font-size:16px;text-align:center;letter-spacing:.2px}
.circuit.hidden{display:none}
.circuit.tripped{background:#3d1a1a;color:#ff6b6b;border:1px solid var(--down);
box-shadow:0 0 0 1px var(--down)}
.circuit.near{background:#2a1f00;color:var(--accent);border:1px solid #4a3600}
#card-verdict{border-color:var(--accent)}
.vd-head{display:flex;align-items:center;gap:14px;margin-bottom:10px}
.vd-ring{width:60px;height:60px;border-radius:50%;flex:0 0 auto;