mdas-jsview-sdk 1.0.11-uat.0 → 1.0.13-uat.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/mdas-sdk.js CHANGED
@@ -1195,6 +1195,76 @@
1195
1195
  </div>
1196
1196
  `;
1197
1197
 
1198
+ const IntradayChartTemplate = `
1199
+ <div class="intraday-chart-widget">
1200
+ <div class="chart-header">
1201
+ <div class="chart-title-section">
1202
+ <div class="company-market-info">
1203
+ <span class="intraday-company-name"></span>
1204
+ </div>
1205
+ <h3 class="intraday-chart-symbol editable-symbol"
1206
+ title="Double-click to edit symbol"
1207
+ data-original-symbol="">AAPL</h3>
1208
+ </div>
1209
+ <div class="chart-change positive">+0.00 (+0.00%)</div>
1210
+ </div>
1211
+
1212
+ <div class="chart-controls">
1213
+ <div class="chart-range-selector">
1214
+ <button class="range-btn active" data-range="0">1D</button>
1215
+ <button class="range-btn" data-range="5">5D</button>
1216
+ </div>
1217
+ <div class="chart-type-selector">
1218
+ <button class="type-btn active" data-type="line" title="Line Chart">Line</button>
1219
+ <button class="type-btn" data-type="area" title="Area Chart">Mountain</button>
1220
+ <button class="type-btn" data-type="candlestick" title="Candlestick Chart">Candles</button>
1221
+ </div>
1222
+ <button class="zoom-reset-btn" title="Reset Zoom">
1223
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
1224
+ <path d="M2 8a6 6 0 1 1 12 0A6 6 0 0 1 2 8zm6-7a7 7 0 1 0 0 14A7 7 0 0 0 8 1z" fill="currentColor"/>
1225
+ <path d="M5 8h6M8 5v6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
1226
+ </svg>
1227
+ Reset Zoom
1228
+ </button>
1229
+ </div>
1230
+
1231
+ <div class="chart-container">
1232
+ <canvas id="intradayChart"></canvas>
1233
+ </div>
1234
+
1235
+ <div class="chart-stats">
1236
+ <div class="stats-header">Daily Stats</div>
1237
+ <div class="stats-grid">
1238
+ <div class="stat-item stat-open">
1239
+ <span class="stat-label">Open</span>
1240
+ <span class="stat-value">$0.00</span>
1241
+ </div>
1242
+ <div class="stat-item stat-high">
1243
+ <span class="stat-label">High</span>
1244
+ <span class="stat-value">$0.00</span>
1245
+ </div>
1246
+ <div class="stat-item stat-low">
1247
+ <span class="stat-label">Low</span>
1248
+ <span class="stat-value">$0.00</span>
1249
+ </div>
1250
+ <div class="stat-item stat-close">
1251
+ <span class="stat-label">Close</span>
1252
+ <span class="stat-value">$0.00</span>
1253
+ </div>
1254
+ <div class="stat-item stat-volume">
1255
+ <span class="stat-label">Volume</span>
1256
+ <span class="stat-value">0</span>
1257
+ </div>
1258
+ </div>
1259
+ </div>
1260
+
1261
+ <div class="widget-loading-overlay hidden">
1262
+ <div class="loading-spinner"></div>
1263
+ <div class="loading-text">Loading chart data...</div>
1264
+ </div>
1265
+ </div>
1266
+ `;
1267
+
1198
1268
  // Widget HTML Templates
1199
1269
  const NightSessionTemplate = `
1200
1270
  <div class="night-session-widget widget">
@@ -1205,13 +1275,12 @@
1205
1275
  <div class="company-market-info">
1206
1276
  <span class="night-company-name"></span>
1207
1277
  <span class="market-name"></span>
1208
- <span class="market-mic"></span>
1209
1278
  </div>
1210
1279
  <h1 class="symbol editable-symbol"
1211
1280
  title="Double-click to edit symbol"
1212
1281
  data-original-symbol="">
1213
1282
  </h1>
1214
-
1283
+
1215
1284
  </div>
1216
1285
  <div class="price-section">
1217
1286
  <div class="current-price"></div>
@@ -4421,13 +4490,6 @@
4421
4490
  marketNameElement.textContent = this.exchangeName || data.exchangeName || '';
4422
4491
  }
4423
4492
 
4424
- // Update MIC (Market Identifier Code)
4425
- const marketMicElement = this.container.querySelector('.market-mic');
4426
- if (marketMicElement) {
4427
- const micValue = this.mic || data.mic || '';
4428
- marketMicElement.textContent = micValue;
4429
- }
4430
-
4431
4493
  // Update price
4432
4494
  const currentPriceElement = this.container.querySelector('.current-price');
4433
4495
  if (currentPriceElement) {
@@ -7925,73 +7987,6 @@ ${SharedStyles}
7925
7987
  }
7926
7988
  }
7927
7989
 
7928
- const IntradayChartTemplate = `
7929
- <div class="intraday-chart-widget">
7930
- <div class="chart-header">
7931
- <div class="chart-title-section">
7932
- <div class="company-market-info">
7933
- <span class="intraday-company-name"></span>
7934
- </div>
7935
- <h3 class="intraday-chart-symbol editable-symbol"
7936
- title="Double-click to edit symbol"
7937
- data-original-symbol="">AAPL</h3>
7938
- </div>
7939
- <div class="chart-change positive">+0.00 (+0.00%)</div>
7940
- </div>
7941
-
7942
- <div class="chart-controls">
7943
- <div class="chart-range-selector">
7944
- <button class="range-btn active" data-range="0">1D</button>
7945
- <button class="range-btn" data-range="5">5D</button>
7946
- </div>
7947
- <div class="chart-type-selector">
7948
- <button class="type-btn active" data-type="line" title="Line Chart">Line</button>
7949
- <button class="type-btn" data-type="area" title="Area Chart">Mountain</button>
7950
- <button class="type-btn" data-type="candlestick" title="Candlestick Chart">Candles</button>
7951
- </div>
7952
- <button class="zoom-reset-btn" title="Reset Zoom">
7953
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
7954
- <path d="M2 8a6 6 0 1 1 12 0A6 6 0 0 1 2 8zm6-7a7 7 0 1 0 0 14A7 7 0 0 0 8 1z" fill="currentColor"/>
7955
- <path d="M5 8h6M8 5v6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
7956
- </svg>
7957
- Reset Zoom
7958
- </button>
7959
- </div>
7960
-
7961
- <div class="chart-container">
7962
- <canvas id="intradayChart"></canvas>
7963
- </div>
7964
-
7965
- <div class="chart-stats">
7966
- <div class="stat-item stat-open">
7967
- <span class="stat-label">Open</span>
7968
- <span class="stat-value">$0.00</span>
7969
- </div>
7970
- <div class="stat-item stat-high">
7971
- <span class="stat-label">High</span>
7972
- <span class="stat-value">$0.00</span>
7973
- </div>
7974
- <div class="stat-item stat-low">
7975
- <span class="stat-label">Low</span>
7976
- <span class="stat-value">$0.00</span>
7977
- </div>
7978
- <div class="stat-item stat-close">
7979
- <span class="stat-label">Close</span>
7980
- <span class="stat-value">$0.00</span>
7981
- </div>
7982
- <div class="stat-item stat-volume">
7983
- <span class="stat-label">Volume</span>
7984
- <span class="stat-value">0</span>
7985
- </div>
7986
- </div>
7987
-
7988
- <div class="widget-loading-overlay hidden">
7989
- <div class="loading-spinner"></div>
7990
- <div class="loading-text">Loading chart data...</div>
7991
- </div>
7992
- </div>
7993
- `;
7994
-
7995
7990
  const IntradayChartStyles = `
7996
7991
  .intraday-chart-widget {
7997
7992
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
@@ -8176,14 +8171,28 @@ ${SharedStyles}
8176
8171
  }
8177
8172
 
8178
8173
  .chart-stats {
8179
- display: grid;
8180
- grid-template-columns: repeat(5, 1fr);
8181
- gap: 15px;
8182
8174
  padding: 15px;
8183
8175
  background: #f9fafb;
8184
8176
  border-radius: 8px;
8185
8177
  }
8186
8178
 
8179
+ .stats-header {
8180
+ font-size: 0.875em;
8181
+ font-weight: 700;
8182
+ color: #374151;
8183
+ text-transform: uppercase;
8184
+ letter-spacing: 0.5px;
8185
+ margin-bottom: 12px;
8186
+ padding-bottom: 8px;
8187
+ border-bottom: 2px solid #e5e7eb;
8188
+ }
8189
+
8190
+ .stats-grid {
8191
+ display: grid;
8192
+ grid-template-columns: repeat(5, 1fr);
8193
+ gap: 15px;
8194
+ }
8195
+
8187
8196
  .stat-item {
8188
8197
  display: flex;
8189
8198
  flex-direction: column;
@@ -8252,11 +8261,16 @@ ${SharedStyles}
8252
8261
  padding: 15px;
8253
8262
  }
8254
8263
 
8255
- .chart-stats {
8264
+ .stats-grid {
8256
8265
  grid-template-columns: repeat(3, 1fr);
8257
8266
  gap: 10px;
8258
8267
  }
8259
8268
 
8269
+ .stats-header {
8270
+ font-size: 0.8em;
8271
+ margin-bottom: 10px;
8272
+ }
8273
+
8260
8274
  .chart-container {
8261
8275
  height: 350px;
8262
8276
  }
@@ -37506,6 +37520,11 @@ ${SharedStyles}
37506
37520
 
37507
37521
  // Symbol editor
37508
37522
  this.symbolEditor = null;
37523
+
37524
+ // Lazy loading cache for chart data
37525
+ this.cached1DData = null;
37526
+ this.cached5DData = null;
37527
+ this.is5DDataLoading = false;
37509
37528
  this.createWidgetStructure();
37510
37529
  this.setupSymbolEditor();
37511
37530
  this.initialize();
@@ -37607,6 +37626,11 @@ ${SharedStyles}
37607
37626
  this.chartData = null;
37608
37627
  this.livePrice = null;
37609
37628
 
37629
+ // Clear all cached data for old symbol
37630
+ this.cached1DData = null;
37631
+ this.cached5DData = null;
37632
+ this.is5DDataLoading = false;
37633
+
37610
37634
  // Update internal symbol
37611
37635
  this.symbol = upperSymbol;
37612
37636
 
@@ -37721,7 +37745,7 @@ ${SharedStyles}
37721
37745
  // Update chart type and re-render
37722
37746
  this.chartType = type;
37723
37747
  this.renderChart();
37724
- this.updateStats();
37748
+ // Stats are managed by WebSocket updates only
37725
37749
  });
37726
37750
  });
37727
37751
  }
@@ -37757,7 +37781,31 @@ ${SharedStyles}
37757
37781
  throw new Error('API service not available');
37758
37782
  }
37759
37783
 
37760
- // FALLBACK LOGIC: Try to find most recent available data
37784
+ // For 5D chart: Load data from multiple days (rangeback 0-6)
37785
+ if (this.rangeBack === 5) {
37786
+ await this.load5DayChartData(apiService);
37787
+ return;
37788
+ }
37789
+
37790
+ // For 1D chart: Check if we have cached data first
37791
+ if (this.rangeBack === 0 && this.cached1DData) {
37792
+ if (this.debug) {
37793
+ console.log('[IntradayChartWidget] Using cached 1D data');
37794
+ }
37795
+
37796
+ // Use cached data
37797
+ this.chartData = this.cached1DData;
37798
+ this.renderChart();
37799
+ // Skip updateStats() - stats will be updated from WebSocket data only
37800
+ this.hideLoading();
37801
+
37802
+ // Restart auto-refresh and live price subscription
37803
+ await this.startAutoRefresh();
37804
+ this.subscribeToLivePrice();
37805
+ return;
37806
+ }
37807
+
37808
+ // FALLBACK LOGIC: Try to find most recent available data (for 1D)
37761
37809
  const MAX_LOOKBACK_DAYS = 7;
37762
37810
  let attemptRangeBack = this.rangeBack;
37763
37811
  let dataFound = false;
@@ -37832,8 +37880,16 @@ ${SharedStyles}
37832
37880
  console.error('[IntradayChartWidget] Model has no data points after processing');
37833
37881
  throw new Error(`No valid data points for ${this.symbol}`);
37834
37882
  }
37883
+
37884
+ // Cache 1D data for instant switching
37885
+ if (this.rangeBack === 0) {
37886
+ this.cached1DData = this.chartData;
37887
+ if (this.debug) {
37888
+ console.log('[IntradayChartWidget] Cached 1D data for instant switching');
37889
+ }
37890
+ }
37835
37891
  this.renderChart();
37836
- this.updateStats();
37892
+ // Skip updateStats() - stats will be updated from WebSocket data only
37837
37893
  this.hideLoading();
37838
37894
  if (this.debug) {
37839
37895
  console.log(`[IntradayChartWidget] Loaded ${dataArray.length} data points`);
@@ -37846,6 +37902,9 @@ ${SharedStyles}
37846
37902
  await this.startAutoRefresh();
37847
37903
  // Subscribe to live price updates
37848
37904
  this.subscribeToLivePrice();
37905
+
37906
+ // LAZY LOADING: Preload 5D data in the background after 1D loads
37907
+ this.preload5DDataInBackground();
37849
37908
  } else {
37850
37909
  // Historical data or fallback - don't refresh
37851
37910
  this.stopAutoRefresh();
@@ -37873,6 +37932,165 @@ ${SharedStyles}
37873
37932
  this.showError(errorMessage);
37874
37933
  }
37875
37934
  }
37935
+ async load5DayChartData(apiService) {
37936
+ try {
37937
+ // Check if we have cached 5D data
37938
+ if (this.cached5DData) {
37939
+ if (this.debug) {
37940
+ console.log('[IntradayChartWidget] Using cached 5D data');
37941
+ }
37942
+
37943
+ // Use cached data
37944
+ this.chartData = this.cached5DData;
37945
+ this.renderChart();
37946
+ // Skip updateStats() - stats will be updated from WebSocket data only
37947
+ this.hideLoading();
37948
+
37949
+ // Subscribe to live price for stats updates (WebSocket only)
37950
+ this.subscribeToLivePrice();
37951
+
37952
+ // Don't auto-refresh for 5D chart
37953
+ this.stopAutoRefresh();
37954
+ return;
37955
+ }
37956
+
37957
+ // No cached data, load it now
37958
+ const combinedData = await this.fetch5DayData(apiService);
37959
+
37960
+ // Process the combined data
37961
+ this.chartData = new IntradayChartModel(combinedData);
37962
+ if (this.chartData.dataPoints.length === 0) {
37963
+ throw new Error(`No valid data points for ${this.symbol}`);
37964
+ }
37965
+
37966
+ // Cache the processed data
37967
+ this.cached5DData = this.chartData;
37968
+ this.renderChart();
37969
+ // Skip updateStats() - stats will be updated from WebSocket data only
37970
+ this.hideLoading();
37971
+ if (this.debug) {
37972
+ console.log(`[IntradayChartWidget] 5D chart loaded with ${this.chartData.dataPoints.length} data points`);
37973
+ }
37974
+
37975
+ // Subscribe to live price for stats updates (WebSocket only)
37976
+ this.subscribeToLivePrice();
37977
+
37978
+ // Don't auto-refresh for 5D chart
37979
+ this.stopAutoRefresh();
37980
+ } catch (error) {
37981
+ console.error('[IntradayChartWidget] Error loading 5D chart data:', error);
37982
+ throw error; // Re-throw to be caught by parent loadChartData
37983
+ }
37984
+ }
37985
+ async fetch5DayData(apiService) {
37986
+ const DAYS_TO_COLLECT = 5;
37987
+ const MAX_RANGEBACK_ATTEMPTS = 7; // API limit: maximum 7 rangeback
37988
+
37989
+ if (this.debug) {
37990
+ console.log('[IntradayChartWidget] Fetching 5D chart data with parallel requests (API limit: rangeback 0-6)');
37991
+ }
37992
+
37993
+ // OPTIMIZATION: Query all rangeback values in parallel (0-6)
37994
+ const rangebackPromises = [];
37995
+ for (let rb = 0; rb < MAX_RANGEBACK_ATTEMPTS; rb++) {
37996
+ rangebackPromises.push(apiService.getIntradayChart(this.source, this.symbol, rb).then(response => {
37997
+ // Extract data array from response
37998
+ let dataArray = response;
37999
+ if (response && response.data && Array.isArray(response.data)) {
38000
+ dataArray = response.data;
38001
+ }
38002
+ return {
38003
+ rangeBack: rb,
38004
+ data: dataArray
38005
+ };
38006
+ }).catch(error => {
38007
+ // If a request fails, return null so we can filter it out
38008
+ if (this.debug) {
38009
+ console.warn(`[IntradayChartWidget] Request failed for rangeback ${rb}:`, error);
38010
+ }
38011
+ return {
38012
+ rangeBack: rb,
38013
+ data: null
38014
+ };
38015
+ }));
38016
+ }
38017
+
38018
+ // Wait for all parallel requests to complete
38019
+ const results = await Promise.all(rangebackPromises);
38020
+ if (this.debug) {
38021
+ console.log('[IntradayChartWidget] All parallel requests completed');
38022
+ }
38023
+
38024
+ // Filter out empty/null responses and collect valid days
38025
+ const collectedDays = results.filter(result => {
38026
+ const isValid = result.data && Array.isArray(result.data) && result.data.length > 0;
38027
+ if (this.debug) {
38028
+ if (isValid) {
38029
+ console.log(`[IntradayChartWidget] Rangeback ${result.rangeBack}: ${result.data.length} data points`);
38030
+ } else {
38031
+ console.log(`[IntradayChartWidget] Rangeback ${result.rangeBack}: No data (skipped)`);
38032
+ }
38033
+ }
38034
+ return isValid;
38035
+ }).slice(0, DAYS_TO_COLLECT); // Take only the first 5 days with data
38036
+
38037
+ if (collectedDays.length === 0) {
38038
+ throw new Error(`No intraday data available for ${this.symbol} in the past ${MAX_RANGEBACK_ATTEMPTS} days`);
38039
+ }
38040
+ if (this.debug) {
38041
+ console.log(`[IntradayChartWidget] Collected ${collectedDays.length}/${DAYS_TO_COLLECT} days of data`);
38042
+ if (collectedDays.length < DAYS_TO_COLLECT) {
38043
+ console.log(`[IntradayChartWidget] Note: Only ${collectedDays.length} days available within API limit (rangeback 0-6)`);
38044
+ }
38045
+ }
38046
+
38047
+ // Combine all collected days into a single array (oldest to newest)
38048
+ const combinedData = [];
38049
+ for (let i = collectedDays.length - 1; i >= 0; i--) {
38050
+ combinedData.push(...collectedDays[i].data);
38051
+ }
38052
+ if (this.debug) {
38053
+ console.log(`[IntradayChartWidget] Combined ${combinedData.length} total data points from ${collectedDays.length} days`);
38054
+ }
38055
+ return combinedData;
38056
+ }
38057
+ preload5DDataInBackground() {
38058
+ // Prevent multiple simultaneous preloads
38059
+ if (this.is5DDataLoading || this.cached5DData) {
38060
+ return;
38061
+ }
38062
+ this.is5DDataLoading = true;
38063
+ if (this.debug) {
38064
+ console.log('[IntradayChartWidget] Starting background preload of 5D data...');
38065
+ }
38066
+
38067
+ // Run in background without blocking
38068
+ setTimeout(async () => {
38069
+ try {
38070
+ const apiService = this.wsManager.getApiService();
38071
+ if (!apiService) {
38072
+ if (this.debug) {
38073
+ console.log('[IntradayChartWidget] API service not available for preload');
38074
+ }
38075
+ return;
38076
+ }
38077
+ const combinedData = await this.fetch5DayData(apiService);
38078
+
38079
+ // Create and cache the model
38080
+ const chartData = new IntradayChartModel(combinedData);
38081
+ this.cached5DData = chartData;
38082
+ if (this.debug) {
38083
+ console.log(`[IntradayChartWidget] ✓ Background preload complete: ${chartData.dataPoints.length} data points cached`);
38084
+ }
38085
+ } catch (error) {
38086
+ if (this.debug) {
38087
+ console.warn('[IntradayChartWidget] Background preload failed:', error);
38088
+ }
38089
+ } finally {
38090
+ this.is5DDataLoading = false;
38091
+ }
38092
+ }, 1000); // Wait 1 second after 1D loads before starting preload
38093
+ }
37876
38094
  subscribeToLivePrice() {
37877
38095
  // Unsubscribe from previous subscription if any
37878
38096
  if (this.unsubscribe) {
@@ -37957,6 +38175,64 @@ ${SharedStyles}
37957
38175
  } else {
37958
38176
  console.log('[IntradayChartWidget] Invalid price, not updating:', price);
37959
38177
  }
38178
+
38179
+ // Update chart stats with live WebSocket data for both 1D and 5D charts
38180
+ // This shows the current day's stats from live data
38181
+ this.updateStatsFromLiveData(priceData);
38182
+ }
38183
+ updateStatsFromLiveData(data) {
38184
+ if (!data) return;
38185
+
38186
+ // Extract stats from WebSocket data
38187
+ const stats = {
38188
+ high: data.HighPx !== undefined && data.HighPx !== null ? parseFloat(data.HighPx) : null,
38189
+ low: data.LowPx !== undefined && data.LowPx !== null ? parseFloat(data.LowPx) : null,
38190
+ open: data.OpenPx !== undefined && data.OpenPx !== null ? parseFloat(data.OpenPx) : null,
38191
+ close: data.LastPx !== undefined && data.LastPx !== null ? parseFloat(data.LastPx) : data.TradePx !== undefined && data.TradePx !== null ? parseFloat(data.TradePx) : null,
38192
+ volume: data.Volume !== undefined && data.Volume !== null ? parseInt(data.Volume) : null,
38193
+ change: data.Change !== undefined && data.Change !== null ? parseFloat(data.Change) : null,
38194
+ changePercent: data.ChangePercent !== undefined && data.ChangePercent !== null ? parseFloat(data.ChangePercent) * 100 : null
38195
+ };
38196
+ if (this.debug) {
38197
+ console.log('[IntradayChartWidget] Updating stats from live data:', stats);
38198
+ }
38199
+
38200
+ // Update stats display
38201
+ const highElement = this.container.querySelector('.stat-high .stat-value');
38202
+ const lowElement = this.container.querySelector('.stat-low .stat-value');
38203
+ const openElement = this.container.querySelector('.stat-open .stat-value');
38204
+ const closeElement = this.container.querySelector('.stat-close .stat-value');
38205
+ const volumeElement = this.container.querySelector('.stat-volume .stat-value');
38206
+ const changeElement = this.container.querySelector('.chart-change');
38207
+ if (highElement && stats.high !== null) {
38208
+ highElement.textContent = `$${stats.high.toFixed(2)}`;
38209
+ }
38210
+ if (lowElement && stats.low !== null) {
38211
+ lowElement.textContent = `$${stats.low.toFixed(2)}`;
38212
+ }
38213
+ if (openElement && stats.open !== null) {
38214
+ openElement.textContent = `$${stats.open.toFixed(2)}`;
38215
+ }
38216
+ if (closeElement && stats.close !== null) {
38217
+ closeElement.textContent = `$${stats.close.toFixed(2)}`;
38218
+ }
38219
+ if (volumeElement && stats.volume !== null) {
38220
+ volumeElement.textContent = this.formatVolume(stats.volume);
38221
+ }
38222
+ if (changeElement && stats.change !== null && stats.changePercent !== null) {
38223
+ const changeClass = stats.change >= 0 ? 'positive' : 'negative';
38224
+ changeElement.className = `chart-change ${changeClass}`;
38225
+ const sign = stats.change >= 0 ? '+' : '';
38226
+ changeElement.textContent = `${sign}${stats.change.toFixed(2)} (${sign}${stats.changePercent.toFixed(2)}%)`;
38227
+ }
38228
+ }
38229
+ formatVolume(volume) {
38230
+ if (volume >= 1000000) {
38231
+ return (volume / 1000000).toFixed(2) + 'M';
38232
+ } else if (volume >= 1000) {
38233
+ return (volume / 1000).toFixed(2) + 'K';
38234
+ }
38235
+ return volume.toString();
37960
38236
  }
37961
38237
  updateLivePriceLine() {
37962
38238
  if (!this.chartInstance || !this.livePrice) {
@@ -38115,7 +38391,8 @@ ${SharedStyles}
38115
38391
  if (response && Array.isArray(response)) {
38116
38392
  this.chartData = new IntradayChartModel(response);
38117
38393
  this.renderChart();
38118
- this.updateStats();
38394
+ // Stats are managed by WebSocket updates only
38395
+
38119
38396
  if (this.debug) {
38120
38397
  console.log(`[IntradayChartWidget] Auto-refresh complete - ${response.length} data points`);
38121
38398
  }
@@ -38421,10 +38698,12 @@ ${SharedStyles}
38421
38698
  autoSkip: true,
38422
38699
  maxRotation: 0,
38423
38700
  minRotation: 0,
38424
- callback: (value, index) => {
38701
+ callback: (value, index, ticks) => {
38425
38702
  if (this.rangeBack > 0) {
38426
- // For multi-day charts with linear scale, show actual time from data point
38427
- const point = validDataPoints[index];
38703
+ // For multi-day charts with linear scale
38704
+ // value is the x-value (index in data array), not the tick index
38705
+ const dataIndex = Math.round(value);
38706
+ const point = validDataPoints[dataIndex];
38428
38707
  if (point) {
38429
38708
  const date = new Date(point.time);
38430
38709
  return date.toLocaleString('en-US', {
@@ -38565,6 +38844,13 @@ ${SharedStyles}
38565
38844
  });
38566
38845
  }
38567
38846
  }
38847
+
38848
+ /**
38849
+ * DEPRECATED: This method is no longer used. Stats are now exclusively
38850
+ * updated from WebSocket data via updateStatsFromLiveData() to ensure
38851
+ * consistency between 1D and 5D charts (both showing today's stats only).
38852
+ * Kept for reference only.
38853
+ */
38568
38854
  updateStats() {
38569
38855
  if (!this.chartData) return;
38570
38856
  const stats = this.chartData.getStats();