Feste Einsatz-Margin (UI-Feld) + lokale Sprachausgabe via Piper
EINSATZ-FELD (User-Wunsch): Laufzeitwert MANUAL_MARGIN in core/config.py (set/get_manual_margin, Muster wie set_margin_buffer). 0 = automatisch wie bisher (margin_buffer_pct % der freien Margin), > 0 = Position wird auf genau diesen Margin-Einsatz gerechnet. - calc_lots setzt es um und DECKELT auf freie Margin x Buffer; ein zu hoher Wunschwert wird begrenzt und geloggt statt an den Broker durchgereicht. Reicht der Betrag nicht fuers Mindestlot -> 0.0 + Warnung, Trade sauber abgelehnt. - Vorrang vor dem Risiko-Modus in trader._send_locked: eine ausdrueckliche Groessenvorgabe schlaegt die Rechenregel. - Wirkt auf ALLE neuen Positionen, auch die autonomen. - UI-Feld "Einsatz" in der ORDER-Leiste (nicht in der Trade-Leiste: die ist nur bei offener Position sichtbar, der Einsatz muss vorher einstellbar sein), bernstein umrandet solange gesetzt. Enter blurrt nur, change sendet einmal. - POST /api/manualmargin, Snapshot manual_margin, neustart-fest ueber runtime_state.json. Ende-zu-Ende getestet (250 -> Snapshot -> 0 -> persistiert). - Lot-Logik isoliert geprueft: 200 EUR -> 0,58 Lots; 5000 EUR -> gedeckelt. SPRACHAUSGABE: Piper lokal (tools/speak.py). Windows-TTS funktioniert zwar, aber es ist KEINE deutsche Stimme installiert - weder SAPI5 noch OneCore (nur David/Zira/Mark, en-US); deutscher Text kaeme mit englischer Aussprache. Add-WindowsCapability scheitert ohne Adminrechte. Piper gewaehlt: laeuft lokal (passt zum Rest - WireGuard-only, Secrets in der ini, keine Cloud), kostet nichts, aus PowerShell/Python aufrufbar. Stimme thorsten-medium (de_DE), Real-Time-Faktor 0,08 (4,3 s Audio in 0,36 s). Das ZIP entpackt eine Ebene tiefer als erwartet (tools/piper/piper/piper.exe) - speak.py SUCHT Binary und Modell statt Pfade fest zu verdrahten. Der erste Entwurf scheiterte daran; der Fail-safe meldete die Pfade sauber statt stumm zu bleiben. Drei Modi getestet (Argument, Pipe, --wav). tools/piper/ ist gitignored (Binaries + 60-MB-Modell), speak.py versioniert. v=136. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
33b6b8f629
commit
6af4c868bc
+40
@@ -900,6 +900,14 @@ function render(d) {
|
||||
if (smi && document.activeElement !== smi) {
|
||||
smi.value = srMin > 0 ? String(srMin) : "";
|
||||
}
|
||||
// Feste Einsatz-Margin (0/leer = automatisch). Nicht überschreiben, während
|
||||
// getippt wird — sonst löscht der 1-s-Render die Eingabe unter den Fingern weg.
|
||||
const mgi = $("margin-input");
|
||||
if (mgi && document.activeElement !== mgi) {
|
||||
const mm = d.manual_margin || 0;
|
||||
mgi.value = mm > 0 ? String(mm) : "";
|
||||
mgi.classList.toggle("on", mm > 0);
|
||||
}
|
||||
// Einblendung: der Bot hat am S/R automatisch geschlossen (Zähler stieg)
|
||||
const src = d.sr_close_count;
|
||||
if (src != null) {
|
||||
@@ -1267,6 +1275,38 @@ $("srmin-input").addEventListener("keydown", e => {
|
||||
if (e.key === "Enter") { e.preventDefault(); e.target.blur(); }
|
||||
});
|
||||
|
||||
// Feste Einsatz-Margin (User-Wunsch 2026-08-04). Leer/0 = automatisch.
|
||||
// ⚠ Wirkt auf ALLE neuen Positionen, auch die autonomen — deshalb sagt der Toast
|
||||
// ausdrücklich, was gilt, statt nur „gespeichert".
|
||||
async function setManualMargin() {
|
||||
const el = $("margin-input"); if (!el) return;
|
||||
const raw = el.value;
|
||||
const v = raw === "" ? 0 : parseFloat(raw);
|
||||
if (isNaN(v) || v < 0) { toast("Bitte Betrag ≥ 0 eingeben (0 = automatisch)", false); return; }
|
||||
const tok = await ensureToken();
|
||||
if (tok === null) return;
|
||||
el.blur();
|
||||
try {
|
||||
const r = await fetch("api/manualmargin", { method: "POST",
|
||||
headers: { "X-Auth-Token": tok, "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ value: v }) });
|
||||
if (r.status === 401) { clearToken(); throw new Error("401"); }
|
||||
const j = await r.json();
|
||||
toast(v > 0 ? `Einsatz fest: ${fmt(j.value ?? v, 2)} € je Position`
|
||||
: "Einsatz wieder automatisch (95 % der freien Margin)", true);
|
||||
} catch (e) {
|
||||
toast(e.message === "401" ? "Token abgelaufen — neu eingeben" : "Netzwerkfehler", false);
|
||||
}
|
||||
}
|
||||
(() => {
|
||||
const el = $("margin-input");
|
||||
if (!el) return; // null-sicher (Cache-Regel)
|
||||
el.addEventListener("change", setManualMargin);
|
||||
el.addEventListener("keydown", e => {
|
||||
if (e.key === "Enter") { e.preventDefault(); e.target.blur(); }
|
||||
});
|
||||
})();
|
||||
|
||||
// Notfall-Stop: manueller Verlust-Wert, bei dem der Server sofort schließt.
|
||||
// Wieder eingeblendet 2026-07-22 (Backend/Persistenz waren die ganze Zeit aktiv).
|
||||
async function setEmg() {
|
||||
|
||||
+10
-2
@@ -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=135">
|
||||
<link rel="stylesheet" href="style.css?v=136">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modul-Menü (ganz oben) -->
|
||||
@@ -235,6 +235,14 @@
|
||||
|
||||
<!-- Aktionsleiste (Trade-Steuerung) -->
|
||||
<nav id="actions">
|
||||
<!-- Einsatz-Margin manuell vorgeben (User 2026-08-04). Leer/0 = automatisch
|
||||
(margin_buffer_pct % der freien Margin). ⚠ BEWUSST hier und nicht in der
|
||||
Trade-Leiste: die ist nur bei OFFENER Position sichtbar, der Einsatz muss
|
||||
aber VOR dem Öffnen einstellbar sein. Wirkt auf ALLE neuen Positionen. -->
|
||||
<span class="mg-field" title="Feste Einsatz-Margin in € — leer/0 = automatisch (95 % der freien Margin). Gilt auch für autonome Trades.">
|
||||
<label for="margin-input">Einsatz</label>
|
||||
<input id="margin-input" type="number" inputmode="decimal" step="10" min="0" placeholder="auto">
|
||||
</span>
|
||||
<button class="btn long" data-side="long">▲ LONG</button>
|
||||
<button class="btn short" data-side="short">▼ SHORT</button>
|
||||
<button class="btn close" data-side="close">✕ CLOSE</button>
|
||||
@@ -259,6 +267,6 @@
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
|
||||
<script src="lightweight-charts.standalone.production.js?v=114"></script>
|
||||
<script src="app.js?v=135"></script>
|
||||
<script src="app.js?v=136"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -512,3 +512,19 @@ main{padding-bottom:74px} /* Platz für die fixe Leiste */
|
||||
font-size: 13px; font-family: var(--mono);
|
||||
}
|
||||
.mt-note { font-size: 12px; line-height: 1.45; }
|
||||
|
||||
/* ── Feste Einsatz-Margin in der Order-Leiste (2026-08-04) ────────────────
|
||||
Sitzt bewusst bei den Order-Buttons, nicht in der Trade-Leiste: die ist nur
|
||||
bei offener Position sichtbar, der Einsatz muss aber VORHER einstellbar sein. */
|
||||
.mg-field { display: inline-flex; flex-direction: column; gap: 2px; margin-right: 8px; }
|
||||
.mg-field label { font-size: 11px; color: var(--dim); line-height: 1; }
|
||||
.mg-field input {
|
||||
width: 74px; padding: 5px 7px;
|
||||
background: var(--surface-2); color: var(--bright);
|
||||
border: 1px solid var(--border); border-radius: var(--r-sm);
|
||||
font-family: var(--mono); font-size: 14px; text-align: right;
|
||||
}
|
||||
.mg-field input:focus { outline: none; border-color: #1f6feb; }
|
||||
/* aktiv gesetzt = sichtbar hervorgehoben, damit ein fester Einsatz nicht
|
||||
unbemerkt bestehen bleibt */
|
||||
.mg-field input.on { border-color: #d29922; color: #d29922; }
|
||||
|
||||
Reference in New Issue
Block a user