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.esm.js +373 -87
- package/dist/mdas-sdk.esm.js.map +1 -1
- package/dist/mdas-sdk.js +373 -87
- package/dist/mdas-sdk.js.map +1 -1
- package/dist/mdas-sdk.min.js +9 -9
- package/dist/mdas-sdk.min.js.map +1 -1
- package/package.json +1 -1
package/dist/mdas-sdk.esm.js
CHANGED
|
@@ -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
|
-
.
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
38421
|
-
|
|
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();
|