From eb18de9bb94401f461a594e752f538742951676b Mon Sep 17 00:00:00 2001 From: Chris Amow Date: Wed, 26 Aug 2026 02:01:45 -0500 Subject: [PATCH] Do not put off-window trendline times on the shared scale. Sampling every source-TF timestamp pulled months of 30m/1d history onto the 1m chart and dropped the lines. Clip samples to the displayed window and never hand Lightweight Charts a null value. --- static/chart.js | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/static/chart.js b/static/chart.js index ff7d9fa..f70f012 100644 --- a/static/chart.js +++ b/static/chart.js @@ -1305,6 +1305,7 @@ class ConfluenceChart { } } for (const level of flat) { + if (!Number.isFinite(level.anchor_p)) continue; const options = { price: level.anchor_p, color: ConfluenceChart.levelColor(level), @@ -1355,6 +1356,7 @@ class ConfluenceChart { } return [...byTime.entries()] .sort((a, b) => a[0] - b[0]) + .filter(([, value]) => Number.isFinite(value)) .map(([time, value]) => ({ time, value })); } @@ -1418,6 +1420,14 @@ class ConfluenceChart { } else { data = level.kind === 'manual' ? this.seriesLineData(level) : this.lineData(level); } + data = (data || []).filter(point => Number.isFinite(point?.value) && point.time != null); + if (!data.length) { + if (entry) { + this.chart.removeSeries(entry.series); + this.levelSeries.delete(level.id); + } + continue; + } entry.series.setData(data); } // Re-anchor once, after the level series have reshaped the scale. setBars @@ -2494,19 +2504,27 @@ class ConfluenceChart { let points; if (this.trendlineGeometryMode === 'source_tf') { const cutoff = level.cutoff_t ?? Infinity; + const first = this.bars[0].t; + const lastBar = this.bars[this.bars.length - 1].t; const stamps = new Set(); const source = this.sourceSeries(level); - for (const time of ConfluenceChart.sourceTimes(source) || []) { - if (time >= level.anchor_t && time <= cutoff) stamps.add(time); + const native = this.bars[0]?.tf === level.tf; + if (native) { + for (const bar of this.bars) { + if (bar.t >= level.anchor_t && bar.t <= cutoff) stamps.add(bar.t); + } + } else { + for (const time of ConfluenceChart.sourceTimes(source) || []) { + if (time >= first && time <= lastBar && time >= level.anchor_t && time <= cutoff) { + stamps.add(time); + } + } + if (lastBar >= level.anchor_t && lastBar <= cutoff) stamps.add(lastBar); } - stamps.add(level.anchor_t); - stamps.add(level.last_t); - const lastBar = this.bars[this.bars.length - 1]?.t; - if (lastBar != null && lastBar >= level.anchor_t && lastBar <= cutoff) stamps.add(lastBar); points = [...stamps] .sort((a, b) => a - b) .map(time => ({ time, value: this.sourceLinePriceAt(level, time) })) - .filter(point => point.value != null); + .filter(point => Number.isFinite(point.value)); } else { const start = this.indexAt(level.anchor_t); const lastBar = this.bars.length - 1;