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.
@@ -1189,6 +1189,76 @@ const CombinedMarketTemplate = `
1189
1189
  </div>
1190
1190
  `;
1191
1191
 
1192
+ const IntradayChartTemplate = `
1193
+ <div class="intraday-chart-widget">
1194
+ <div class="chart-header">
1195
+ <div class="chart-title-section">
1196
+ <div class="company-market-info">
1197
+ <span class="intraday-company-name"></span>
1198
+ </div>
1199
+ <h3 class="intraday-chart-symbol editable-symbol"
1200
+ title="Double-click to edit symbol"
1201
+ data-original-symbol="">AAPL</h3>
1202
+ </div>
1203
+ <div class="chart-change positive">+0.00 (+0.00%)</div>
1204
+ </div>
1205
+
1206
+ <div class="chart-controls">
1207
+ <div class="chart-range-selector">
1208
+ <button class="range-btn active" data-range="0">1D</button>
1209
+ <button class="range-btn" data-range="5">5D</button>
1210
+ </div>
1211
+ <div class="chart-type-selector">
1212
+ <button class="type-btn active" data-type="line" title="Line Chart">Line</button>
1213
+ <button class="type-btn" data-type="area" title="Area Chart">Mountain</button>
1214
+ <button class="type-btn" data-type="candlestick" title="Candlestick Chart">Candles</button>
1215
+ </div>
1216
+ <button class="zoom-reset-btn" title="Reset Zoom">
1217
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
1218
+ <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"/>
1219
+ <path d="M5 8h6M8 5v6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
1220
+ </svg>
1221
+ Reset Zoom
1222
+ </button>
1223
+ </div>
1224
+
1225
+ <div class="chart-container">
1226
+ <canvas id="intradayChart"></canvas>
1227
+ </div>
1228
+
1229
+ <div class="chart-stats">
1230
+ <div class="stats-header">Daily Stats</div>
1231
+ <div class="stats-grid">
1232
+ <div class="stat-item stat-open">
1233
+ <span class="stat-label">Open</span>
1234
+ <span class="stat-value">$0.00</span>
1235
+ </div>
1236
+ <div class="stat-item stat-high">
1237
+ <span class="stat-label">High</span>
1238
+ <span class="stat-value">$0.00</span>
1239
+ </div>
1240
+ <div class="stat-item stat-low">
1241
+ <span class="stat-label">Low</span>
1242
+ <span class="stat-value">$0.00</span>
1243
+ </div>
1244
+ <div class="stat-item stat-close">
1245
+ <span class="stat-label">Close</span>
1246
+ <span class="stat-value">$0.00</span>
1247
+ </div>
1248
+ <div class="stat-item stat-volume">
1249
+ <span class="stat-label">Volume</span>
1250
+ <span class="stat-value">0</span>
1251
+ </div>
1252
+ </div>
1253
+ </div>
1254
+
1255
+ <div class="widget-loading-overlay hidden">
1256
+ <div class="loading-spinner"></div>
1257
+ <div class="loading-text">Loading chart data...</div>
1258
+ </div>
1259
+ </div>
1260
+ `;
1261
+
1192
1262
  // Widget HTML Templates
1193
1263
  const NightSessionTemplate = `
1194
1264
  <div class="night-session-widget widget">
@@ -1199,13 +1269,12 @@ const NightSessionTemplate = `
1199
1269
  <div class="company-market-info">
1200
1270
  <span class="night-company-name"></span>
1201
1271
  <span class="market-name"></span>
1202
- <span class="market-mic"></span>
1203
1272
  </div>
1204
1273
  <h1 class="symbol editable-symbol"
1205
1274
  title="Double-click to edit symbol"
1206
1275
  data-original-symbol="">
1207
1276
  </h1>
1208
-
1277
+
1209
1278
  </div>
1210
1279
  <div class="price-section">
1211
1280
  <div class="current-price"></div>
@@ -4415,13 +4484,6 @@ class NightSessionWidget extends BaseWidget {
4415
4484
  marketNameElement.textContent = this.exchangeName || data.exchangeName || '';
4416
4485
  }
4417
4486
 
4418
- // Update MIC (Market Identifier Code)
4419
- const marketMicElement = this.container.querySelector('.market-mic');
4420
- if (marketMicElement) {
4421
- const micValue = this.mic || data.mic || '';
4422
- marketMicElement.textContent = micValue;
4423
- }
4424
-
4425
4487
  // Update price
4426
4488
  const currentPriceElement = this.container.querySelector('.current-price');
4427
4489
  if (currentPriceElement) {
@@ -7919,73 +7981,6 @@ class IntradayChartModel {
7919
7981
  }
7920
7982
  }
7921
7983
 
7922
- const IntradayChartTemplate = `
7923
- <div class="intraday-chart-widget">
7924
- <div class="chart-header">
7925
- <div class="chart-title-section">
7926
- <div class="company-market-info">
7927
- <span class="intraday-company-name"></span>
7928
- </div>
7929
- <h3 class="intraday-chart-symbol editable-symbol"
7930
- title="Double-click to edit symbol"
7931
- data-original-symbol="">AAPL</h3>
7932
- </div>
7933
- <div class="chart-change positive">+0.00 (+0.00%)</div>
7934
- </div>
7935
-
7936
- <div class="chart-controls">
7937
- <div class="chart-range-selector">
7938
- <button class="range-btn active" data-range="0">1D</button>
7939
- <button class="range-btn" data-range="5">5D</button>
7940
- </div>
7941
- <div class="chart-type-selector">
7942
- <button class="type-btn active" data-type="line" title="Line Chart">Line</button>
7943
- <button class="type-btn" data-type="area" title="Area Chart">Mountain</button>
7944
- <button class="type-btn" data-type="candlestick" title="Candlestick Chart">Candles</button>
7945
- </div>
7946
- <button class="zoom-reset-btn" title="Reset Zoom">
7947
- <svg width="16" height="16" viewBox="0 0 16 16" fill="none">
7948
- <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"/>
7949
- <path d="M5 8h6M8 5v6" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"/>
7950
- </svg>
7951
- Reset Zoom
7952
- </button>
7953
- </div>
7954
-
7955
- <div class="chart-container">
7956
- <canvas id="intradayChart"></canvas>
7957
- </div>
7958
-
7959
- <div class="chart-stats">
7960
- <div class="stat-item stat-open">
7961
- <span class="stat-label">Open</span>
7962
- <span class="stat-value">$0.00</span>
7963
- </div>
7964
- <div class="stat-item stat-high">
7965
- <span class="stat-label">High</span>
7966
- <span class="stat-value">$0.00</span>
7967
- </div>
7968
- <div class="stat-item stat-low">
7969
- <span class="stat-label">Low</span>
7970
- <span class="stat-value">$0.00</span>
7971
- </div>
7972
- <div class="stat-item stat-close">
7973
- <span class="stat-label">Close</span>
7974
- <span class="stat-value">$0.00</span>
7975
- </div>
7976
- <div class="stat-item stat-volume">
7977
- <span class="stat-label">Volume</span>
7978
- <span class="stat-value">0</span>
7979
- </div>
7980
- </div>
7981
-
7982
- <div class="widget-loading-overlay hidden">
7983
- <div class="loading-spinner"></div>
7984
- <div class="loading-text">Loading chart data...</div>
7985
- </div>
7986
- </div>
7987
- `;
7988
-
7989
7984
  const IntradayChartStyles = `
7990
7985
  .intraday-chart-widget {
7991
7986
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
@@ -8170,14 +8165,28 @@ const IntradayChartStyles = `
8170
8165
  }
8171
8166
 
8172
8167
  .chart-stats {
8173
- display: grid;
8174
- grid-template-columns: repeat(5, 1fr);
8175
- gap: 15px;
8176
8168
  padding: 15px;
8177
8169
  background: #f9fafb;
8178
8170
  border-radius: 8px;
8179
8171
  }
8180
8172
 
8173
+ .stats-header {
8174
+ font-size: 0.875em;
8175
+ font-weight: 700;
8176
+ color: #374151;
8177
+ text-transform: uppercase;
8178
+ letter-spacing: 0.5px;
8179
+ margin-bottom: 12px;
8180
+ padding-bottom: 8px;
8181
+ border-bottom: 2px solid #e5e7eb;
8182
+ }
8183
+
8184
+ .stats-grid {
8185
+ display: grid;
8186
+ grid-template-columns: repeat(5, 1fr);
8187
+ gap: 15px;
8188
+ }
8189
+
8181
8190
  .stat-item {
8182
8191
  display: flex;
8183
8192
  flex-direction: column;
@@ -8246,11 +8255,16 @@ const IntradayChartStyles = `
8246
8255
  padding: 15px;
8247
8256
  }
8248
8257
 
8249
- .chart-stats {
8258
+ .stats-grid {
8250
8259
  grid-template-columns: repeat(3, 1fr);
8251
8260
  gap: 10px;
8252
8261
  }
8253
8262
 
8263
+ .stats-header {
8264
+ font-size: 0.8em;
8265
+ margin-bottom: 10px;
8266
+ }
8267
+
8254
8268
  .chart-container {
8255
8269
  height: 350px;
8256
8270
  }
@@ -37500,6 +37514,11 @@ class IntradayChartWidget extends BaseWidget {
37500
37514
 
37501
37515
  // Symbol editor
37502
37516
  this.symbolEditor = null;
37517
+
37518
+ // Lazy loading cache for chart data
37519
+ this.cached1DData = null;
37520
+ this.cached5DData = null;
37521
+ this.is5DDataLoading = false;
37503
37522
  this.createWidgetStructure();
37504
37523
  this.setupSymbolEditor();
37505
37524
  this.initialize();
@@ -37601,6 +37620,11 @@ class IntradayChartWidget extends BaseWidget {
37601
37620
  this.chartData = null;
37602
37621
  this.livePrice = null;
37603
37622
 
37623
+ // Clear all cached data for old symbol
37624
+ this.cached1DData = null;
37625
+ this.cached5DData = null;
37626
+ this.is5DDataLoading = false;
37627
+
37604
37628
  // Update internal symbol
37605
37629
  this.symbol = upperSymbol;
37606
37630
 
@@ -37715,7 +37739,7 @@ class IntradayChartWidget extends BaseWidget {
37715
37739
  // Update chart type and re-render
37716
37740
  this.chartType = type;
37717
37741
  this.renderChart();
37718
- this.updateStats();
37742
+ // Stats are managed by WebSocket updates only
37719
37743
  });
37720
37744
  });
37721
37745
  }
@@ -37751,7 +37775,31 @@ class IntradayChartWidget extends BaseWidget {
37751
37775
  throw new Error('API service not available');
37752
37776
  }
37753
37777
 
37754
- // FALLBACK LOGIC: Try to find most recent available data
37778
+ // For 5D chart: Load data from multiple days (rangeback 0-6)
37779
+ if (this.rangeBack === 5) {
37780
+ await this.load5DayChartData(apiService);
37781
+ return;
37782
+ }
37783
+
37784
+ // For 1D chart: Check if we have cached data first
37785
+ if (this.rangeBack === 0 && this.cached1DData) {
37786
+ if (this.debug) {
37787
+ console.log('[IntradayChartWidget] Using cached 1D data');
37788
+ }
37789
+
37790
+ // Use cached data
37791
+ this.chartData = this.cached1DData;
37792
+ this.renderChart();
37793
+ // Skip updateStats() - stats will be updated from WebSocket data only
37794
+ this.hideLoading();
37795
+
37796
+ // Restart auto-refresh and live price subscription
37797
+ await this.startAutoRefresh();
37798
+ this.subscribeToLivePrice();
37799
+ return;
37800
+ }
37801
+
37802
+ // FALLBACK LOGIC: Try to find most recent available data (for 1D)
37755
37803
  const MAX_LOOKBACK_DAYS = 7;
37756
37804
  let attemptRangeBack = this.rangeBack;
37757
37805
  let dataFound = false;
@@ -37826,8 +37874,16 @@ class IntradayChartWidget extends BaseWidget {
37826
37874
  console.error('[IntradayChartWidget] Model has no data points after processing');
37827
37875
  throw new Error(`No valid data points for ${this.symbol}`);
37828
37876
  }
37877
+
37878
+ // Cache 1D data for instant switching
37879
+ if (this.rangeBack === 0) {
37880
+ this.cached1DData = this.chartData;
37881
+ if (this.debug) {
37882
+ console.log('[IntradayChartWidget] Cached 1D data for instant switching');
37883
+ }
37884
+ }
37829
37885
  this.renderChart();
37830
- this.updateStats();
37886
+ // Skip updateStats() - stats will be updated from WebSocket data only
37831
37887
  this.hideLoading();
37832
37888
  if (this.debug) {
37833
37889
  console.log(`[IntradayChartWidget] Loaded ${dataArray.length} data points`);
@@ -37840,6 +37896,9 @@ class IntradayChartWidget extends BaseWidget {
37840
37896
  await this.startAutoRefresh();
37841
37897
  // Subscribe to live price updates
37842
37898
  this.subscribeToLivePrice();
37899
+
37900
+ // LAZY LOADING: Preload 5D data in the background after 1D loads
37901
+ this.preload5DDataInBackground();
37843
37902
  } else {
37844
37903
  // Historical data or fallback - don't refresh
37845
37904
  this.stopAutoRefresh();
@@ -37867,6 +37926,165 @@ class IntradayChartWidget extends BaseWidget {
37867
37926
  this.showError(errorMessage);
37868
37927
  }
37869
37928
  }
37929
+ async load5DayChartData(apiService) {
37930
+ try {
37931
+ // Check if we have cached 5D data
37932
+ if (this.cached5DData) {
37933
+ if (this.debug) {
37934
+ console.log('[IntradayChartWidget] Using cached 5D data');
37935
+ }
37936
+
37937
+ // Use cached data
37938
+ this.chartData = this.cached5DData;
37939
+ this.renderChart();
37940
+ // Skip updateStats() - stats will be updated from WebSocket data only
37941
+ this.hideLoading();
37942
+
37943
+ // Subscribe to live price for stats updates (WebSocket only)
37944
+ this.subscribeToLivePrice();
37945
+
37946
+ // Don't auto-refresh for 5D chart
37947
+ this.stopAutoRefresh();
37948
+ return;
37949
+ }
37950
+
37951
+ // No cached data, load it now
37952
+ const combinedData = await this.fetch5DayData(apiService);
37953
+
37954
+ // Process the combined data
37955
+ this.chartData = new IntradayChartModel(combinedData);
37956
+ if (this.chartData.dataPoints.length === 0) {
37957
+ throw new Error(`No valid data points for ${this.symbol}`);
37958
+ }
37959
+
37960
+ // Cache the processed data
37961
+ this.cached5DData = this.chartData;
37962
+ this.renderChart();
37963
+ // Skip updateStats() - stats will be updated from WebSocket data only
37964
+ this.hideLoading();
37965
+ if (this.debug) {
37966
+ console.log(`[IntradayChartWidget] 5D chart loaded with ${this.chartData.dataPoints.length} data points`);
37967
+ }
37968
+
37969
+ // Subscribe to live price for stats updates (WebSocket only)
37970
+ this.subscribeToLivePrice();
37971
+
37972
+ // Don't auto-refresh for 5D chart
37973
+ this.stopAutoRefresh();
37974
+ } catch (error) {
37975
+ console.error('[IntradayChartWidget] Error loading 5D chart data:', error);
37976
+ throw error; // Re-throw to be caught by parent loadChartData
37977
+ }
37978
+ }
37979
+ async fetch5DayData(apiService) {
37980
+ const DAYS_TO_COLLECT = 5;
37981
+ const MAX_RANGEBACK_ATTEMPTS = 7; // API limit: maximum 7 rangeback
37982
+
37983
+ if (this.debug) {
37984
+ console.log('[IntradayChartWidget] Fetching 5D chart data with parallel requests (API limit: rangeback 0-6)');
37985
+ }
37986
+
37987
+ // OPTIMIZATION: Query all rangeback values in parallel (0-6)
37988
+ const rangebackPromises = [];
37989
+ for (let rb = 0; rb < MAX_RANGEBACK_ATTEMPTS; rb++) {
37990
+ rangebackPromises.push(apiService.getIntradayChart(this.source, this.symbol, rb).then(response => {
37991
+ // Extract data array from response
37992
+ let dataArray = response;
37993
+ if (response && response.data && Array.isArray(response.data)) {
37994
+ dataArray = response.data;
37995
+ }
37996
+ return {
37997
+ rangeBack: rb,
37998
+ data: dataArray
37999
+ };
38000
+ }).catch(error => {
38001
+ // If a request fails, return null so we can filter it out
38002
+ if (this.debug) {
38003
+ console.warn(`[IntradayChartWidget] Request failed for rangeback ${rb}:`, error);
38004
+ }
38005
+ return {
38006
+ rangeBack: rb,
38007
+ data: null
38008
+ };
38009
+ }));
38010
+ }
38011
+
38012
+ // Wait for all parallel requests to complete
38013
+ const results = await Promise.all(rangebackPromises);
38014
+ if (this.debug) {
38015
+ console.log('[IntradayChartWidget] All parallel requests completed');
38016
+ }
38017
+
38018
+ // Filter out empty/null responses and collect valid days
38019
+ const collectedDays = results.filter(result => {
38020
+ const isValid = result.data && Array.isArray(result.data) && result.data.length > 0;
38021
+ if (this.debug) {
38022
+ if (isValid) {
38023
+ console.log(`[IntradayChartWidget] Rangeback ${result.rangeBack}: ${result.data.length} data points`);
38024
+ } else {
38025
+ console.log(`[IntradayChartWidget] Rangeback ${result.rangeBack}: No data (skipped)`);
38026
+ }
38027
+ }
38028
+ return isValid;
38029
+ }).slice(0, DAYS_TO_COLLECT); // Take only the first 5 days with data
38030
+
38031
+ if (collectedDays.length === 0) {
38032
+ throw new Error(`No intraday data available for ${this.symbol} in the past ${MAX_RANGEBACK_ATTEMPTS} days`);
38033
+ }
38034
+ if (this.debug) {
38035
+ console.log(`[IntradayChartWidget] Collected ${collectedDays.length}/${DAYS_TO_COLLECT} days of data`);
38036
+ if (collectedDays.length < DAYS_TO_COLLECT) {
38037
+ console.log(`[IntradayChartWidget] Note: Only ${collectedDays.length} days available within API limit (rangeback 0-6)`);
38038
+ }
38039
+ }
38040
+
38041
+ // Combine all collected days into a single array (oldest to newest)
38042
+ const combinedData = [];
38043
+ for (let i = collectedDays.length - 1; i >= 0; i--) {
38044
+ combinedData.push(...collectedDays[i].data);
38045
+ }
38046
+ if (this.debug) {
38047
+ console.log(`[IntradayChartWidget] Combined ${combinedData.length} total data points from ${collectedDays.length} days`);
38048
+ }
38049
+ return combinedData;
38050
+ }
38051
+ preload5DDataInBackground() {
38052
+ // Prevent multiple simultaneous preloads
38053
+ if (this.is5DDataLoading || this.cached5DData) {
38054
+ return;
38055
+ }
38056
+ this.is5DDataLoading = true;
38057
+ if (this.debug) {
38058
+ console.log('[IntradayChartWidget] Starting background preload of 5D data...');
38059
+ }
38060
+
38061
+ // Run in background without blocking
38062
+ setTimeout(async () => {
38063
+ try {
38064
+ const apiService = this.wsManager.getApiService();
38065
+ if (!apiService) {
38066
+ if (this.debug) {
38067
+ console.log('[IntradayChartWidget] API service not available for preload');
38068
+ }
38069
+ return;
38070
+ }
38071
+ const combinedData = await this.fetch5DayData(apiService);
38072
+
38073
+ // Create and cache the model
38074
+ const chartData = new IntradayChartModel(combinedData);
38075
+ this.cached5DData = chartData;
38076
+ if (this.debug) {
38077
+ console.log(`[IntradayChartWidget] ✓ Background preload complete: ${chartData.dataPoints.length} data points cached`);
38078
+ }
38079
+ } catch (error) {
38080
+ if (this.debug) {
38081
+ console.warn('[IntradayChartWidget] Background preload failed:', error);
38082
+ }
38083
+ } finally {
38084
+ this.is5DDataLoading = false;
38085
+ }
38086
+ }, 1000); // Wait 1 second after 1D loads before starting preload
38087
+ }
37870
38088
  subscribeToLivePrice() {
37871
38089
  // Unsubscribe from previous subscription if any
37872
38090
  if (this.unsubscribe) {
@@ -37951,6 +38169,64 @@ class IntradayChartWidget extends BaseWidget {
37951
38169
  } else {
37952
38170
  console.log('[IntradayChartWidget] Invalid price, not updating:', price);
37953
38171
  }
38172
+
38173
+ // Update chart stats with live WebSocket data for both 1D and 5D charts
38174
+ // This shows the current day's stats from live data
38175
+ this.updateStatsFromLiveData(priceData);
38176
+ }
38177
+ updateStatsFromLiveData(data) {
38178
+ if (!data) return;
38179
+
38180
+ // Extract stats from WebSocket data
38181
+ const stats = {
38182
+ high: data.HighPx !== undefined && data.HighPx !== null ? parseFloat(data.HighPx) : null,
38183
+ low: data.LowPx !== undefined && data.LowPx !== null ? parseFloat(data.LowPx) : null,
38184
+ open: data.OpenPx !== undefined && data.OpenPx !== null ? parseFloat(data.OpenPx) : null,
38185
+ close: data.LastPx !== undefined && data.LastPx !== null ? parseFloat(data.LastPx) : data.TradePx !== undefined && data.TradePx !== null ? parseFloat(data.TradePx) : null,
38186
+ volume: data.Volume !== undefined && data.Volume !== null ? parseInt(data.Volume) : null,
38187
+ change: data.Change !== undefined && data.Change !== null ? parseFloat(data.Change) : null,
38188
+ changePercent: data.ChangePercent !== undefined && data.ChangePercent !== null ? parseFloat(data.ChangePercent) * 100 : null
38189
+ };
38190
+ if (this.debug) {
38191
+ console.log('[IntradayChartWidget] Updating stats from live data:', stats);
38192
+ }
38193
+
38194
+ // Update stats display
38195
+ const highElement = this.container.querySelector('.stat-high .stat-value');
38196
+ const lowElement = this.container.querySelector('.stat-low .stat-value');
38197
+ const openElement = this.container.querySelector('.stat-open .stat-value');
38198
+ const closeElement = this.container.querySelector('.stat-close .stat-value');
38199
+ const volumeElement = this.container.querySelector('.stat-volume .stat-value');
38200
+ const changeElement = this.container.querySelector('.chart-change');
38201
+ if (highElement && stats.high !== null) {
38202
+ highElement.textContent = `$${stats.high.toFixed(2)}`;
38203
+ }
38204
+ if (lowElement && stats.low !== null) {
38205
+ lowElement.textContent = `$${stats.low.toFixed(2)}`;
38206
+ }
38207
+ if (openElement && stats.open !== null) {
38208
+ openElement.textContent = `$${stats.open.toFixed(2)}`;
38209
+ }
38210
+ if (closeElement && stats.close !== null) {
38211
+ closeElement.textContent = `$${stats.close.toFixed(2)}`;
38212
+ }
38213
+ if (volumeElement && stats.volume !== null) {
38214
+ volumeElement.textContent = this.formatVolume(stats.volume);
38215
+ }
38216
+ if (changeElement && stats.change !== null && stats.changePercent !== null) {
38217
+ const changeClass = stats.change >= 0 ? 'positive' : 'negative';
38218
+ changeElement.className = `chart-change ${changeClass}`;
38219
+ const sign = stats.change >= 0 ? '+' : '';
38220
+ changeElement.textContent = `${sign}${stats.change.toFixed(2)} (${sign}${stats.changePercent.toFixed(2)}%)`;
38221
+ }
38222
+ }
38223
+ formatVolume(volume) {
38224
+ if (volume >= 1000000) {
38225
+ return (volume / 1000000).toFixed(2) + 'M';
38226
+ } else if (volume >= 1000) {
38227
+ return (volume / 1000).toFixed(2) + 'K';
38228
+ }
38229
+ return volume.toString();
37954
38230
  }
37955
38231
  updateLivePriceLine() {
37956
38232
  if (!this.chartInstance || !this.livePrice) {
@@ -38109,7 +38385,8 @@ class IntradayChartWidget extends BaseWidget {
38109
38385
  if (response && Array.isArray(response)) {
38110
38386
  this.chartData = new IntradayChartModel(response);
38111
38387
  this.renderChart();
38112
- this.updateStats();
38388
+ // Stats are managed by WebSocket updates only
38389
+
38113
38390
  if (this.debug) {
38114
38391
  console.log(`[IntradayChartWidget] Auto-refresh complete - ${response.length} data points`);
38115
38392
  }
@@ -38415,10 +38692,12 @@ class IntradayChartWidget extends BaseWidget {
38415
38692
  autoSkip: true,
38416
38693
  maxRotation: 0,
38417
38694
  minRotation: 0,
38418
- callback: (value, index) => {
38695
+ callback: (value, index, ticks) => {
38419
38696
  if (this.rangeBack > 0) {
38420
- // For multi-day charts with linear scale, show actual time from data point
38421
- const point = validDataPoints[index];
38697
+ // For multi-day charts with linear scale
38698
+ // value is the x-value (index in data array), not the tick index
38699
+ const dataIndex = Math.round(value);
38700
+ const point = validDataPoints[dataIndex];
38422
38701
  if (point) {
38423
38702
  const date = new Date(point.time);
38424
38703
  return date.toLocaleString('en-US', {
@@ -38559,6 +38838,13 @@ class IntradayChartWidget extends BaseWidget {
38559
38838
  });
38560
38839
  }
38561
38840
  }
38841
+
38842
+ /**
38843
+ * DEPRECATED: This method is no longer used. Stats are now exclusively
38844
+ * updated from WebSocket data via updateStatsFromLiveData() to ensure
38845
+ * consistency between 1D and 5D charts (both showing today's stats only).
38846
+ * Kept for reference only.
38847
+ */
38562
38848
  updateStats() {
38563
38849
  if (!this.chartData) return;
38564
38850
  const stats = this.chartData.getStats();