This commit is contained in:
2026-04-17 17:15:33 -04:00
parent c8fa99c6d2
commit 6f118107d9
16 changed files with 128 additions and 18 deletions

View File

@@ -45,6 +45,9 @@ export class WebSocketDatafeed implements IBasicDataFeed {
private configuration: DatafeedConfiguration | null = null
private messageHandler: MessageHandler
private symbolDenominators: Map<string, SymbolDenominators> = new Map() // Track denominators per symbol
// Tracks the last bar time (ms) returned by getBars per "symbolKey_periodSeconds".
// bar_updates with time < this watermark are stale and already covered by history.
private lastBarTimes: Map<string, number> = new Map()
constructor() {
// Use the shared WebSocket connection (managed by App.vue authentication)
@@ -118,6 +121,14 @@ export class WebSocketDatafeed implements IBasicDataFeed {
const symbolKey = subscription.symbolInfo.ticker || subscription.symbolInfo.name
const denoms = this.symbolDenominators.get(symbolKey) || { tick: 1, base: 1 }
// Drop bars already covered by getBars history to prevent time-order violations
const barTimeMs = message.bar.time * 1000
const barKey = `${symbolKey}_${message.period_seconds}`
const watermark = this.lastBarTimes.get(barKey) ?? 0
if (barTimeMs < watermark) {
return
}
const bar: Bar = {
time: message.bar.time * 1000, // Convert to milliseconds
open: parseFloat(message.bar.open) / denoms.tick,
@@ -284,6 +295,16 @@ export class WebSocketDatafeed implements IBasicDataFeed {
bars.sort((a, b) => a.time - b.time)
// Update last-bar watermark so bar_update handler can drop stale replays
if (bars.length > 0) {
const barKey = `${symbolKey}_${intervalToSeconds(resolution)}`
const newLast = bars[bars.length - 1].time
const prevLast = this.lastBarTimes.get(barKey) ?? 0
if (newLast > prevLast) {
this.lastBarTimes.set(barKey, newLast)
}
}
console.log('[TradingView Datafeed] Scaled bar sample:', bars[0])
const meta: HistoryMetadata = {