feat(mse): auto pivot-based support/resistance lines on chart

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Mukan Erkin TÖRÜK 2026-04-25 13:10:54 +03:00
parent df9b85e3c6
commit 43f1eb9c6e

View file

@ -532,10 +532,84 @@ async function loadKlines() {
document.getElementById('ohlc-l').textContent = fmt(last.low);
document.getElementById('ohlc-c').textContent = fmt(last.close);
}
drawSupportResistance(candles);
updateChartOverlays();
} catch(e) {}
}
// ── Support / Resistance ──────────────────────────
let srLines = [];
function drawSupportResistance(candles) {
// önceki çizgileri temizle
srLines.forEach(l => candleSeries.removePriceLine(l));
srLines = [];
if (candles.length < 10) return;
const left = 5, right = 5; // her yönde kaç mum komşu bakılacak
const pivotHighs = [], pivotLows = [];
for (let i = left; i < candles.length - right; i++) {
const c = candles[i];
let isHigh = true, isLow = true;
for (let j = i - left; j <= i + right; j++) {
if (j === i) continue;
if (candles[j].high >= c.high) isHigh = false;
if (candles[j].low <= c.low) isLow = false;
}
if (isHigh) pivotHighs.push(c.high);
if (isLow) pivotLows.push(c.low);
}
// yakın seviyeleri cluster'la: fiyat aralığının %0.3'ü içindeki pivotları birleştir
const currentPrice = candles[candles.length - 1].close;
const threshold = currentPrice * 0.003;
function cluster(pivots) {
const sorted = [...pivots].sort((a, b) => a - b);
const groups = [];
for (const p of sorted) {
const last = groups[groups.length - 1];
if (last && p - last[last.length - 1] <= threshold) {
last.push(p);
} else {
groups.push([p]);
}
}
// her grubun ortalamasını al, en az 2 pivot olan seviyeleri döndür
return groups
.filter(g => g.length >= 2)
.map(g => g.reduce((s, v) => s + v, 0) / g.length);
}
const resistances = cluster(pivotHighs);
const supports = cluster(pivotLows);
// mevcut fiyata yakın en fazla 4 direnç + 4 destek çiz
const near = levels => levels
.map(p => ({ p, dist: Math.abs(p - currentPrice) }))
.sort((a, b) => a.dist - b.dist)
.slice(0, 4)
.map(x => x.p);
near(resistances).forEach(price => {
srLines.push(candleSeries.createPriceLine({
price, color: 'rgba(231,76,60,0.55)', lineWidth: 1,
lineStyle: LightweightCharts.LineStyle.Dashed,
axisLabelVisible: false, title: 'R',
}));
});
near(supports).forEach(price => {
srLines.push(candleSeries.createPriceLine({
price, color: 'rgba(46,204,113,0.55)', lineWidth: 1,
lineStyle: LightweightCharts.LineStyle.Dashed,
axisLabelVisible: false, title: 'S',
}));
});
}
let klineWs = null;
function startKlineWs() {
if (klineWs) klineWs.close();