Trade-Leiste: Laufzeit-Uhr des offenen Trades (v=118)
- trader: open_time (echte Epoch, Broker-Offset korrigiert) aus position.time, im Snapshot; nur 1x je Position berechnet, beim Close auf 0. - _broker_offset_s(sym=None): Symbol explizit uebergebbar -- beim Adoptieren ist self.symbol noch nicht gesetzt (war Offset 0 -> Zeit 3h in der Zukunft); zusaetzlich Selbstheilung bei Zukunftswerten. - app.js/index.html/style.css: Feld #tb-dur + Titel-Uhr #tb-runtime, eigener 1-s-Ticker (flüssig zwischen Snapshots), ab 2h bernstein (Time-Stop-Naehe). - Verifiziert: Live-Trade 48898382 open_time == Log-Zeile 13:22:48. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e9653a842a
commit
919ed7c3ee
+29
@@ -50,6 +50,30 @@ function beepCloseAlert() {
|
||||
// der Button blinkt (Empfehlung aktiv & flat) — einmaliger Piep war überhörbar.
|
||||
const _REC_REBEEP_MS = 30000;
|
||||
let _lastRecBeep = 0, _lastRecSignal = null, _audioHintShown = false, _lastSrCloseCount = null;
|
||||
|
||||
// ── Laufzeit-Uhr des offenen Trades ───────────────────────────────────────────
|
||||
// Öffnungszeit kommt als echte Epoch (Broker-Offset serverseitig korrigiert) im
|
||||
// Snapshot (`position.open_time`); der Ticker läuft eigenständig jede Sekunde,
|
||||
// damit die Uhr auch zwischen den Snapshots (4 s Poll / 1 s WS) flüssig zählt.
|
||||
let _tradeOpenTime = 0;
|
||||
function _fmtDuration(sec) {
|
||||
sec = Math.max(0, Math.floor(sec));
|
||||
const h = Math.floor(sec / 3600), m = Math.floor((sec % 3600) / 60), s = sec % 60;
|
||||
const p2 = (n) => String(n).padStart(2, "0");
|
||||
return h > 0 ? `${h}:${p2(m)}:${p2(s)}` : `${m}:${p2(s)}`;
|
||||
}
|
||||
function _tickTradeDuration() {
|
||||
const el = document.getElementById("tb-dur"), hd = document.getElementById("tb-runtime");
|
||||
if (!el) return;
|
||||
if (!_tradeOpenTime) { el.textContent = "—"; if (hd) hd.textContent = ""; return; }
|
||||
const sec = Date.now() / 1000 - _tradeOpenTime;
|
||||
const txt = _fmtDuration(sec);
|
||||
el.textContent = txt;
|
||||
if (hd) hd.textContent = "⏱ " + txt;
|
||||
// Ab 2 h dezent hervorheben (Time-Stop greift bei 120 min in Phase „Init")
|
||||
el.className = "tb-val" + (sec >= 7200 ? " warn" : "");
|
||||
}
|
||||
setInterval(_tickTradeDuration, 1000);
|
||||
function beepRecommendation(sig, isNew) {
|
||||
if (_muted) return; // auch kein Sperr-Toast
|
||||
if (!_audioCtx || _audioCtx.state !== "running") {
|
||||
@@ -386,12 +410,17 @@ function render(d) {
|
||||
dEl.textContent = long ? "▲ LONG" : "▼ SHORT";
|
||||
$("tb-lots").textContent = fmt(p.lots, 2);
|
||||
$("tb-margin").textContent = p.margin ? cs + fmt(p.margin, 2) : "—";
|
||||
// Laufzeit: Öffnungszeit merken (echte Epoch, Broker-Offset korrigiert) und
|
||||
// sekündlich per Ticker anzeigen — unabhängig vom Snapshot-Intervall.
|
||||
_tradeOpenTime = p.open_time ? Number(p.open_time) : 0;
|
||||
_tickTradeDuration();
|
||||
// SL/TP-Felder nur befüllen, wenn nicht gerade bearbeitet (kein Tipp-Konflikt)
|
||||
const slEl = $("tb-sl"), tpEl = $("tb-tp");
|
||||
if (document.activeElement !== slEl) slEl.value = p.sl ? fmt(p.sl, 2) : "";
|
||||
if (document.activeElement !== tpEl) tpEl.value = p.tp ? fmt(p.tp, 2) : "";
|
||||
} else {
|
||||
tb.classList.add("hidden");
|
||||
_tradeOpenTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-3
@@ -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=117">
|
||||
<link rel="stylesheet" href="style.css?v=118">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modul-Menü (ganz oben) -->
|
||||
@@ -44,8 +44,10 @@
|
||||
<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>
|
||||
<h2 class="tb-title">aktueller Trade läuft <span class="tb-runtime" id="tb-runtime"></span></h2>
|
||||
<div class="tb-row">
|
||||
<span class="tb-field"><label>Laufzeit</label>
|
||||
<b class="tb-val" id="tb-dur">—</b></span>
|
||||
<span class="tb-field"><label>Richtung</label>
|
||||
<b class="tb-val tb-dir" id="tb-dir">—</b></span>
|
||||
<span class="tb-field"><label>Lots</label>
|
||||
@@ -226,6 +228,6 @@
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
|
||||
<script src="lightweight-charts.standalone.production.js?v=114"></script>
|
||||
<script src="app.js?v=117"></script>
|
||||
<script src="app.js?v=118"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -112,6 +112,10 @@ main{display:grid;grid-template-columns:1fr 1fr;gap:11px;padding:11px}
|
||||
#card-trail.hidden{display:none} /* Trailing-Kachel ausgeblendet, 2026-07-22 */
|
||||
.tb-title{margin:0 0 8px;font-size:14px;letter-spacing:1.5px;text-transform:uppercase;
|
||||
color:var(--dim);font-weight:600}
|
||||
/* Laufzeit-Uhr: im Titel mitlaufend (kompakt) + eigenes Feld in der Zeile */
|
||||
.tb-runtime{margin-left:8px;color:var(--bright);font-family:var(--mono);
|
||||
letter-spacing:.5px;text-transform:none}
|
||||
.tb-field .tb-val.warn{color:var(--accent);border-color:#4a3600}
|
||||
.tb-row{display:flex;flex-wrap:wrap;gap:10px}
|
||||
/* EINHEITLICHES Feld-Design: Anzeige-Boxen (Richtung/Lots/Einsatz) und Eingabe-
|
||||
Felder (SL/TP/Gewinn-Close/Notfall-Close) sehen identisch aus (Label über Box). */
|
||||
|
||||
Reference in New Issue
Block a user