Fix: Track actual historical crossovers and force indicator redraw

Issue 1: Track actual crossovers from history
- Added calculateHistoricalCrossovers() function
- Scans candle history backwards to find most recent crossover
- Updates lastSignalTimestamp when BUY→SELL or SELL→BUY crossover is detected
- Date now reflects when the price actually crossed the MA line

Issue 2: Force full redraw of indicator series
- Changed updateIndicatorCandles() to remove and recreate all series
- Instead of using setData() which may not work reliably
- Full redraw ensures overlay indicators (MA) refresh correctly
- Now indicator lines update properly when new candles finish

Both implementations ensure:
1. Date shows actual crossover time (when candle crossed MA)
2. Indicator lines redraw on new candle completion
3. Works for both overlay (MA, BB, HTS) and pane (RSI, MACD, etc.) indicators
This commit is contained in:
DiTus
2026-03-01 20:12:19 +01:00
parent 0df8547d96
commit 9513f5b426
2 changed files with 85 additions and 45 deletions

View File

@ -813,59 +813,31 @@ function renderIndicatorOnPane(indicator, meta, instance, candles, paneIndex, li
});
}
// Update existing indicator series with new data (for real-time updates)
// Completely redraw indicators (works for both overlay and pane)
export function updateIndicatorCandles() {
if (!window.dashboard || !window.dashboard.chart) return;
console.log('[UpdateIndicators] Removing and recreating all indicator series');
// Remove all existing series
const activeIndicators = getActiveIndicators();
const currentInterval = window.dashboard.currentInterval;
const candles = window.dashboard?.allData?.get(currentInterval);
if (!candles || candles.length === 0) return;
activeIndicators.forEach(indicator => {
if (!indicator.visible || indicator.series.length === 0) return;
const IndicatorClass = IndicatorRegistry[indicator.type];
if (!IndicatorClass) return;
const instance = new IndicatorClass(indicator);
const results = instance.calculate(candles);
if (!results || results.length === 0) return;
const meta = instance.getMetadata();
// Update each plot series
meta.plots.forEach((plot, plotIdx) => {
const series = indicator.series[plotIdx];
if (!series) return;
const plotColor = indicator.params[`_color_${plotIdx}`] || plot.color || '#2962ff';
const lineWidth = indicator.params._lineWidth || 2;
// Build complete data array
const data = [];
for (let i = 0; i < candles.length; i++) {
const value = results[i]?.[plot.id];
if (value !== null && value !== undefined) {
data.push({
time: candles[i].time,
value: value,
color: plotColor,
lineWidth: lineWidth
});
}
}
if (data.length > 0) {
series.setData(data);
indicator.series?.forEach(s => {
try {
window.dashboard.chart.removeSeries(s);
} catch(e) {
console.warn('[UpdateIndicators] Error removing series:', e);
}
});
indicator.series = [];
});
console.log(`[UpdateIndicators] Updated ${activeIndicators.length} indicator series`);
// Clear pane mappings
indicatorPanes.clear();
nextPaneIndex = 1;
// Now call drawIndicatorsOnChart to recreate everything
drawIndicatorsOnChart();
console.log(`[UpdateIndicators] Recreated ${activeIndicators.length} indicators`);
}
// Chart drawing