Chartmuster grafisch: SVG-Skizze in Karte + Trigger/Ziel-Linien im PWA-Chart
- patterns.py: nur AKTIVE, kursnahe Muster (abgearbeitete/Ziel erreicht raus, _MAX_DIST_ATR=5.0 Distanz-Filter) - get_bars liefert bei M30 die Muster (patterns.snapshot) fürs Chart-Overlay - app.js: _patternSvg-Skizze je Muster-Karte + 2 stärkste Muster als Trigger-/Ziel-Preislinien im M30-Chart; Gitternetz dezenter (#10151c) - style.css: .pt-svg; index.html v=116->117; CLAUDE.md aktualisiert Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
21d855b163
commit
ae6bbb2f35
+37
-2
@@ -225,6 +225,26 @@ function renderCircuitBreaker(cb) {
|
||||
}
|
||||
|
||||
// Chartmuster (visuell) — reine Anzeige. Status: bildet sich / bestätigt / (ungültig raus).
|
||||
// Kompakte SVG-Skizze der Muster-Form (viewBox 60×32). Rein schematisch, damit die
|
||||
// Form auf einen Blick erkennbar ist; Farbe = Richtung (grün bull / rot bear / grau).
|
||||
function _patternSvg(type, col) {
|
||||
const P = {
|
||||
double_top: "M2,26 L14,8 L22,16 L34,8 L46,26",
|
||||
double_bottom: "M2,6 L14,24 L22,16 L34,24 L46,6",
|
||||
hs: "M2,24 L12,14 L18,20 L28,4 L38,20 L44,14 L54,24",
|
||||
inv_hs: "M2,8 L12,18 L18,12 L28,28 L38,12 L44,18 L54,8",
|
||||
cup: "M2,6 C2,30 44,30 44,6 M44,6 L54,12",
|
||||
inv_cup: "M2,26 C2,2 44,2 44,26 M44,26 L54,20",
|
||||
tri_asc: "M2,26 L52,26 M2,4 L52,22",
|
||||
tri_desc: "M2,6 L52,6 M2,28 L52,10",
|
||||
tri_sym: "M2,4 L52,16 M2,28 L52,16",
|
||||
};
|
||||
const d = P[type] || "M2,16 L54,16";
|
||||
return `<svg class="pt-svg" viewBox="0 0 56 32" width="56" height="32" aria-hidden="true">
|
||||
<path d="${d}" fill="none" stroke="${col}" stroke-width="2"
|
||||
stroke-linejoin="round" stroke-linecap="round"/></svg>`;
|
||||
}
|
||||
|
||||
function renderPatterns(pt) {
|
||||
const el = $("pt-list");
|
||||
if (!el) return;
|
||||
@@ -235,6 +255,7 @@ function renderPatterns(pt) {
|
||||
}
|
||||
el.innerHTML = items.map(m => {
|
||||
const dirCls = m.dir === "bull" ? "up" : m.dir === "bear" ? "down" : "dim";
|
||||
const col = m.dir === "bull" ? "#3fb950" : m.dir === "bear" ? "#f85149" : "#8b949e";
|
||||
const arr = m.dir === "bull" ? "▲" : m.dir === "bear" ? "▼" : "◆";
|
||||
const st = m.status === "confirmed"
|
||||
? `<span class="pt-badge conf">bestätigt</span>`
|
||||
@@ -243,7 +264,8 @@ function renderPatterns(pt) {
|
||||
? `Ziel <b>${fmt(m.target, 2)}</b>` : `Ausbruch offen`;
|
||||
const q = Math.round((m.quality || 0) * 100);
|
||||
return `<div class="pt-item ${dirCls}">
|
||||
<div class="pt-head"><span class="pt-name">${arr} ${m.name}</span>${st}
|
||||
<div class="pt-head">${_patternSvg(m.type, col)}
|
||||
<span class="pt-name">${arr} ${m.name}</span>${st}
|
||||
<span class="pt-q">Güte ${q}%</span></div>
|
||||
<div class="pt-det">Trigger <b>${fmt(m.trigger, 2)}</b> · ${tgt}
|
||||
· Höhe ${m.height_atr}×ATR · vor ${m.bars_ago} Bars</div>
|
||||
@@ -1161,7 +1183,7 @@ function _makeChart(tf) {
|
||||
const chart = LightweightCharts.createChart(el, {
|
||||
width: el.clientWidth || 320, height: 200,
|
||||
layout: { background: { color: "#0d1117" }, textColor: "#8b949e", fontSize: 15 },
|
||||
grid: { vertLines: { color: "#161b22" }, horzLines: { color: "#161b22" } },
|
||||
grid: { vertLines: { color: "#10151c" }, horzLines: { color: "#10151c" } },
|
||||
timeScale: { borderColor: "#30363d", timeVisible: true, secondsVisible: false },
|
||||
rightPriceScale: { borderColor: "#30363d" },
|
||||
crosshair: { mode: LightweightCharts.CrosshairMode.Normal },
|
||||
@@ -1223,6 +1245,19 @@ function renderChart(tf, d) {
|
||||
(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"];
|
||||
|
||||
+2
-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=116">
|
||||
<link rel="stylesheet" href="style.css?v=117">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Modul-Menü (ganz oben) -->
|
||||
@@ -226,6 +226,6 @@
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
|
||||
<script src="lightweight-charts.standalone.production.js?v=114"></script>
|
||||
<script src="app.js?v=116"></script>
|
||||
<script src="app.js?v=117"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -147,6 +147,8 @@ main{display:grid;grid-template-columns:1fr 1fr;gap:11px;padding:11px}
|
||||
border-radius:var(--r-sm);padding:9px 12px;margin-bottom:8px}
|
||||
.pt-item.up{border-left-color:var(--up)} .pt-item.down{border-left-color:var(--down)}
|
||||
.pt-head{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
|
||||
.pt-svg{flex:0 0 auto;background:var(--bg);border:1px solid var(--border);
|
||||
border-radius:4px;padding:1px 2px}
|
||||
.pt-name{font-weight:700;font-size:15px}
|
||||
.pt-item.up .pt-name{color:var(--up)} .pt-item.down .pt-name{color:var(--down)}
|
||||
.pt-badge{font-size:11px;font-weight:700;border-radius:4px;padding:1px 7px}
|
||||
|
||||
Reference in New Issue
Block a user