Charts-Tab komplett entfernt (User-Vorgabe)
Entfernt: Tab-Button, #view-charts, der gesamte app.js-Chart-Block (Kartenaufbau, renderChart, loadCharts, 20-s-Refresh, Resize-Handler), die Chart-CSS-Regeln, die vendorte Bibliothek web/lightweight-charts.standalone.production.js (164 KB) samt script-Tag - und die Backend-Kette dahinter: /api/bars und engine.get_bars (60 Zeilen). Beide existierten ausschliesslich fuer dieses Tab; geprueft, dass es keinen anderen Aufrufer gibt. Nicht betroffen (sahen nur aehnlich aus): die Chartmuster-Karte (Verdict-Gewicht 0,25, im Tab "SIG Live"), der MQL5-Indikator samt sr_levels.csv-Export (eigener Pfad ueber _write_levels_file) und die Analyse-Module structure/patterns/cone - die speisen den Snapshot, nicht das Chart. Der MT5-Chart bleibt voll bedient. Ein veralteter Kommentar in trader.py, der auf engine.get_bars verwies, wurde auf core/gaps.py umgehaengt. Verifiziert am laufenden Server: /api/bars -> 404, Bibliothek -> 404, data-view="charts" und id="view-charts" nicht mehr im ausgelieferten HTML, 6 Tabs zu 6 Views paarig, keine verwaisten JS-Referenzen, Klammern-Balance ok, keine Fehler im Log. v=142. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
6ff3c15b1d
commit
a1a5d560b9
-137
@@ -1423,7 +1423,6 @@ function showView(name) {
|
||||
if (name === "logs") loadLogs();
|
||||
if (name === "stats") loadStats();
|
||||
if (name === "news") loadNews();
|
||||
if (name === "charts") loadCharts();
|
||||
}
|
||||
// Nur echte View-Tabs registrieren — NICHT den Mute-Button (der trägt .tab nur
|
||||
// fürs Styling; ohne [data-view]-Filter überschrieb das hier seinen onclick und
|
||||
@@ -1572,146 +1571,10 @@ async function loadNews() {
|
||||
} catch (e) { bEl.innerHTML = '<div class="down">Netzwerkfehler</div>'; }
|
||||
}
|
||||
|
||||
// ── Charts (Lightweight Charts): M1/M5/M15/M30/H1 untereinander mit Trend ──
|
||||
const CHART_TFS = ["M1", "M5", "M15", "M30", "H1"];
|
||||
const _charts = {}; // tf → {chart, candle, s12, s50}
|
||||
const _TREND_TXT = { up: ["▲ Aufwärts", "up"], down: ["▼ Abwärts", "down"], flat: ["→ Seitwärts", "flat"] };
|
||||
|
||||
function _ensureChartCard(tf) {
|
||||
if (document.getElementById("chart-" + tf)) return;
|
||||
const card = document.createElement("div");
|
||||
card.className = "chart-card"; card.id = "chart-" + tf;
|
||||
card.innerHTML =
|
||||
`<div class="chart-head"><span class="chart-tf">${tf}</span>` +
|
||||
`<span class="chart-trend" id="ctr-${tf}">—</span>` +
|
||||
`<span class="chart-last" id="clast-${tf}">—</span></div>` +
|
||||
`<div class="chart-cv" id="ccv-${tf}"></div>`;
|
||||
$("charts-body").appendChild(card);
|
||||
}
|
||||
|
||||
function _makeChart(tf) {
|
||||
const el = document.getElementById("ccv-" + tf);
|
||||
// Explizite Größe statt autoSize: autoSize hängt an ResizeObserver und lieferte
|
||||
// auf Mobil-Browsern teils 0×0-Charts (leerer Tab). clientWidth ist gesetzt,
|
||||
// weil loadCharts erst nach dem Einblenden des Tabs läuft.
|
||||
const chart = LightweightCharts.createChart(el, {
|
||||
width: el.clientWidth || 320, height: 200,
|
||||
layout: { background: { color: "#0d1117" }, textColor: "#8b949e", fontSize: 15 },
|
||||
grid: { vertLines: { color: "#10151c" }, horzLines: { color: "#10151c" } },
|
||||
timeScale: { borderColor: "#30363d", timeVisible: true, secondsVisible: false },
|
||||
rightPriceScale: { borderColor: "#30363d" },
|
||||
crosshair: { mode: LightweightCharts.CrosshairMode.Normal },
|
||||
handleScale: { axisPressedMouseMove: false },
|
||||
});
|
||||
const candle = chart.addCandlestickSeries({
|
||||
upColor: "#3fb950", downColor: "#f85149", borderVisible: false,
|
||||
wickUpColor: "#3fb950", wickDownColor: "#f85149",
|
||||
});
|
||||
const line = (color) => chart.addLineSeries(
|
||||
{ color, lineWidth: 1, priceLineVisible: false, lastValueVisible: false, crosshairMarkerVisible: false });
|
||||
const s12 = line("#58a6ff"), s50 = line("#d29922"); // EMA12 blau, EMA50 amber
|
||||
// Regressionskanal (nur M30 bekommt Daten): oben/unten gestrichelt, Mitte gepunktet
|
||||
const chLine = (color, style) => chart.addLineSeries(
|
||||
{ color, lineWidth: 1, lineStyle: style, priceLineVisible: false,
|
||||
lastValueVisible: false, crosshairMarkerVisible: false });
|
||||
const chU = chLine("#8b949e", 2), chM = chLine("#8b949e66", 1), chL = chLine("#8b949e", 2);
|
||||
_charts[tf] = { chart, candle, s12, s50, chU, chM, chL };
|
||||
return _charts[tf];
|
||||
}
|
||||
|
||||
function renderChart(tf, d) {
|
||||
const off = d.broker_utc_offset || 0;
|
||||
const B = d.bars || [];
|
||||
if (d.error || !B.length) {
|
||||
const tr = document.getElementById("ctr-" + tf);
|
||||
if (tr) { tr.textContent = d.error ? "⚠ " + d.error : "keine Daten"; tr.className = "chart-trend flat"; }
|
||||
return;
|
||||
}
|
||||
const candles = B.map(b => ({ time: b.t - off, open: b.o, high: b.h, low: b.l, close: b.c }));
|
||||
const em = (arr) => (arr || []).map((v, i) => (B[i] ? { time: B[i].t - off, value: v } : null)).filter(Boolean);
|
||||
const c = _charts[tf] || _makeChart(tf);
|
||||
c.candle.setData(candles);
|
||||
c.s12.setData(em(d.ema12));
|
||||
c.s50.setData(em(d.ema50));
|
||||
// Regressionskanal (M30) — 3 Linien deckungsgleich mit den Bars; sonst leeren
|
||||
if (c.chU) {
|
||||
const ch = d.channel;
|
||||
if (ch && ch.upper) {
|
||||
c.chU.setData(em(ch.upper)); c.chM.setData(em(ch.mid)); c.chL.setData(em(ch.lower));
|
||||
} else {
|
||||
c.chU.setData([]); c.chM.setData([]); c.chL.setData([]);
|
||||
}
|
||||
}
|
||||
// S/R-Linien + Zonen (Ranges) als horizontale Preislinien einzeichnen
|
||||
(c.lines || []).forEach(pl => { try { c.candle.removePriceLine(pl); } catch (e) {} });
|
||||
c.lines = [];
|
||||
const addLine = (p, color, style, title) => {
|
||||
if (p == null) return;
|
||||
c.lines.push(c.candle.createPriceLine({ price: p, color, lineWidth: 1,
|
||||
lineStyle: style, axisLabelVisible: true, title: title || "" }));
|
||||
};
|
||||
const LV = d.levels || {};
|
||||
// Verständliche Labels: nächstes Level ausgeschrieben, weitere nummeriert
|
||||
(LV.res || []).forEach((p, i) =>
|
||||
addLine(p, "#1f6feb", 2, i === 0 ? "Widerstand" : `Widerstand ${i + 1}`));
|
||||
(LV.sup || []).forEach((p, i) =>
|
||||
addLine(p, "#58a6ff", 2, i === 0 ? "Unterstützung" : `Unterstützung ${i + 1}`));
|
||||
(LV.zones || []).forEach(z => {
|
||||
addLine(z.hi, "#1f6feb", 1, "Zone"); addLine(z.lo, "#1f6feb", 1, "");
|
||||
});
|
||||
// Chartmuster-Overlay (nur M30): Trigger = kräftige Linie (grün bull / rot bear),
|
||||
// Ziel = gepunktete Linie gleicher Farbe. Nur die 2 stärksten, sonst wird's voll.
|
||||
(d.patterns || []).slice(0, 2).forEach(p => {
|
||||
const bull = p.dir === "bull";
|
||||
const col = bull ? "#3fb950" : (p.dir === "bear" ? "#f85149" : "#8b949e");
|
||||
c.lines.push(c.candle.createPriceLine({
|
||||
price: p.trigger, color: col, lineWidth: 2, lineStyle: 0,
|
||||
axisLabelVisible: true, title: (p.status === "confirmed" ? "▶ " : "◌ ") + p.name }));
|
||||
if (p.target != null)
|
||||
c.lines.push(c.candle.createPriceLine({
|
||||
price: p.target, color: col, lineWidth: 1, lineStyle: 1,
|
||||
axisLabelVisible: true, title: "Ziel" }));
|
||||
});
|
||||
c.chart.timeScale().fitContent();
|
||||
const tr = document.getElementById("ctr-" + tf);
|
||||
const [txt, cls] = _TREND_TXT[d.trend] || ["—", "flat"];
|
||||
tr.textContent = txt; tr.className = "chart-trend " + cls;
|
||||
document.getElementById("clast-" + tf).textContent = candles[candles.length - 1].close.toFixed(3);
|
||||
}
|
||||
|
||||
async function loadCharts() {
|
||||
if (typeof LightweightCharts === "undefined") {
|
||||
$("charts-body").innerHTML = '<div class="dim" style="padding:14px">Chart-Framework nicht geladen (Seite neu laden).</div>';
|
||||
return;
|
||||
}
|
||||
for (const tf of CHART_TFS) {
|
||||
_ensureChartCard(tf);
|
||||
try {
|
||||
const d = await (await fetch(`api/bars?tf=${tf}&n=100`)).json();
|
||||
renderChart(tf, d);
|
||||
// Breite nachziehen (Rotation/Resize seit Erstellung)
|
||||
const c = _charts[tf], el = document.getElementById("ccv-" + tf);
|
||||
if (c && el && el.clientWidth > 0) c.chart.applyOptions({ width: el.clientWidth });
|
||||
} catch (e) {
|
||||
// Fehler SICHTBAR machen statt stumm schlucken (war: leere Kacheln ohne Grund)
|
||||
const tr = document.getElementById("ctr-" + tf);
|
||||
if (tr) { tr.textContent = "⚠ " + (e && e.message ? e.message : "Fehler"); tr.className = "chart-trend flat"; }
|
||||
}
|
||||
}
|
||||
}
|
||||
window.addEventListener("resize", () => {
|
||||
for (const tf of CHART_TFS) {
|
||||
const c = _charts[tf], el = document.getElementById("ccv-" + tf);
|
||||
if (c && el && el.clientWidth > 0) c.chart.applyOptions({ width: el.clientWidth });
|
||||
}
|
||||
});
|
||||
|
||||
$("logs-reload").onclick = loadLogs;
|
||||
$("stats-reload").onclick = loadStats;
|
||||
$("news-reload").onclick = loadNews;
|
||||
$("charts-reload").onclick = loadCharts;
|
||||
// Auto-Refresh nur solange der Charts-Tab sichtbar ist (schont den mt5_lock)
|
||||
setInterval(() => { if (!$("view-charts").classList.contains("hidden")) loadCharts(); }, 20000);
|
||||
|
||||
// Sofort einmal per REST laden, dann auf den Live-Stream umschalten
|
||||
fetch("api/snapshot").then(r => r.json()).then(_applySnapshot).catch(() => {});
|
||||
|
||||
+2
-12
@@ -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=141">
|
||||
<link rel="stylesheet" href="style.css?v=142">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modul-Menü (ganz oben) -->
|
||||
@@ -20,7 +20,6 @@
|
||||
<button class="tab" data-view="siganzeige">SIG Anzeige</button>
|
||||
<button class="tab" data-view="logs">Logs</button>
|
||||
<button class="tab" data-view="stats">Statistik</button>
|
||||
<button class="tab" data-view="charts">Charts</button>
|
||||
<button class="tab" data-view="news">News</button>
|
||||
<button class="tab mute-tab" id="mute-btn" title="Töne an/aus">🔊</button>
|
||||
</nav>
|
||||
@@ -262,14 +261,6 @@
|
||||
</section>
|
||||
</section>
|
||||
|
||||
<!-- Charts: M1/M5/M15/M30/H1 untereinander mit Trend (Lightweight Charts) -->
|
||||
<section id="view-charts" class="view hidden">
|
||||
<div class="view-head">
|
||||
<h2>Charts</h2>
|
||||
<button class="reload" id="charts-reload">↻</button>
|
||||
</div>
|
||||
<div id="charts-body"></div>
|
||||
</section>
|
||||
|
||||
<!-- News -->
|
||||
<section id="view-news" class="view hidden">
|
||||
@@ -321,7 +312,6 @@
|
||||
</div>
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
|
||||
<script src="lightweight-charts.standalone.production.js?v=114"></script>
|
||||
<script src="app.js?v=141"></script>
|
||||
<script src="app.js?v=142"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-11
@@ -26,7 +26,7 @@ body{
|
||||
-webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
|
||||
}
|
||||
/* Zahlen-lastige Werte in Mono (aligned, Trading-Terminal-Optik) */
|
||||
#hdr-price,#hdr-pnl,.px span,.tb-val,.tb-field input,.chart-last,
|
||||
#hdr-price,#hdr-pnl,.px span,.tb-val,.tb-field input,
|
||||
.hdr-clock,.gap-zone,.trade .p{font-family:var(--mono)}
|
||||
|
||||
/* ── Header (scrollt unter den Tabs) ────── */
|
||||
@@ -342,16 +342,6 @@ main{padding-bottom:74px} /* Platz für die fixe Leiste */
|
||||
.stx-c b {font-size:18px;color:var(--text-bright);margin-left:3px}
|
||||
|
||||
/* Charts-Tab: M1/M5/M15/M30/H1 untereinander (Lightweight Charts) */
|
||||
#charts-body {display:flex;flex-direction:column;gap:12px;padding:10px}
|
||||
.chart-card {background:var(--surface-2);border:1px solid var(--border);border-radius:10px;overflow:hidden}
|
||||
.chart-head {display:flex;align-items:center;gap:10px;padding:8px 12px;border-bottom:1px solid var(--line)}
|
||||
.chart-tf {font-weight:800;font-size:19px;color:var(--text-bright);letter-spacing:.5px}
|
||||
.chart-trend {font-weight:700;font-size:17px}
|
||||
.chart-trend.up {color:#3fb950}
|
||||
.chart-trend.down {color:#f85149}
|
||||
.chart-trend.flat {color:var(--dim)}
|
||||
.chart-last {margin-left:auto;font-variant-numeric:tabular-nums;color:var(--text-bright);font-size:18px}
|
||||
.chart-cv {height:200px;width:100%}
|
||||
|
||||
/* Kurslücken (Gaps): offene Fill-Magnete */
|
||||
.gaps-list {display:flex;flex-direction:column;gap:6px}
|
||||
|
||||
Reference in New Issue
Block a user