Add indicator recalculation on timeframe change and new candle

Changes:
- Added lastCandleTimestamp to track candle completion
- Detect new candle when timestamp increases
- Clear indicator caches when new candle detected
- Clear indicator caches when timeframe changes
- Recalculate indicators and signals in both cases
- Refresh chart when new candle is detected

This ensures indicators are always recalculated with fresh data when:
1. Timeframe is switched
2. A new candle completes

Both cases now force:
- Cache clearing
- Indicator recalculation
- Chart refresh
- Signal recalculation
This commit is contained in:
DiTus
2026-03-01 19:58:14 +01:00
parent 11c805917c
commit 61aaa2d122

View File

@ -23,6 +23,7 @@ constructor() {
this.taData = null; this.taData = null;
this.indicatorSignals = []; this.indicatorSignals = [];
this.summarySignal = null; this.summarySignal = null;
this.lastCandleTimestamp = null;
this.init(); this.init();
} }
@ -294,10 +295,21 @@ constructor() {
} else if (e.key === 'ArrowUp') { } else if (e.key === 'ArrowUp') {
this.navigateToRecent(); this.navigateToRecent();
} }
}); });
} }
async loadInitialData() { clearIndicatorCaches() {
const activeIndicators = window.getActiveIndicators?.() || [];
activeIndicators.forEach(indicator => {
indicator.cachedResults = null;
indicator.cachedMeta = null;
indicator.lastSignalTimestamp = null;
indicator.lastSignalType = null;
});
console.log(`[Dashboard] Cleared caches for ${activeIndicators.length} indicators`);
}
async loadInitialData() {
await Promise.all([ await Promise.all([
this.loadData(2000, true), this.loadData(2000, true),
this.loadStats() this.loadStats()
@ -377,6 +389,19 @@ async loadNewData() {
volume: parseFloat(c.volume || 0) volume: parseFloat(c.volume || 0)
})); }));
const latest = chartData[chartData.length - 1];
// Check if new candle detected
const isNewCandle = this.lastCandleTimestamp !== null && latest.time > this.lastCandleTimestamp;
if (isNewCandle) {
console.log(`[NewData Load] New candle detected: ${this.lastCandleTimestamp} -> ${latest.time}`);
// Clear indicator caches to force recalculation
this.clearIndicatorCaches();
}
this.lastCandleTimestamp = latest.time;
chartData.forEach(candle => { chartData.forEach(candle => {
if (candle.time >= lastTimestamp) { if (candle.time >= lastTimestamp) {
this.candleSeries.update(candle); this.candleSeries.update(candle);
@ -392,7 +417,6 @@ async loadNewData() {
this.chart.timeScale().scrollToRealTime(); this.chart.timeScale().scrollToRealTime();
} }
const latest = chartData[chartData.length - 1];
this.updateStats(latest); this.updateStats(latest);
// Recalculate indicators and signals when new data loads // Recalculate indicators and signals when new data loads
@ -400,6 +424,11 @@ async loadNewData() {
window.drawIndicatorsOnChart(); window.drawIndicatorsOnChart();
} }
await this.loadSignals(); await this.loadSignals();
// Refresh chart if new candle detected
if (isNewCandle) {
this.chart.timeScale().scrollToRealTime();
}
} }
} catch (error) { } catch (error) {
console.error('Error loading new data:', error); console.error('Error loading new data:', error);
@ -675,7 +704,7 @@ const signalsHtml = this.indicatorSignals?.length > 0 ? this.indicatorSignals.ma
} }
} }
switchTimeframe(interval) { switchTimeframe(interval) {
if (!this.intervals.includes(interval) || interval === this.currentInterval) return; if (!this.intervals.includes(interval) || interval === this.currentInterval) return;
const oldInterval = this.currentInterval; const oldInterval = this.currentInterval;
@ -686,8 +715,13 @@ const signalsHtml = this.indicatorSignals?.length > 0 ? this.indicatorSignals.ma
btn.classList.toggle('active', btn.dataset.interval === interval); btn.classList.toggle('active', btn.dataset.interval === interval);
}); });
// Clear indicator caches before switching timeframe
this.clearIndicatorCaches();
// Clear old interval data, not new interval // Clear old interval data, not new interval
this.allData.delete(oldInterval); this.allData.delete(oldInterval);
this.lastCandleTimestamp = null;
this.loadInitialData(); this.loadInitialData();
window.clearSimulationResults?.(); window.clearSimulationResults?.();