@discomedia/utils 1.0.20 → 1.0.22
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/index-frontend.cjs +45 -32
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +45 -32
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +93 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +93 -52
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +1 -1
- package/dist/test.js +944 -5020
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/market-time.d.ts +25 -43
- package/dist/types/market-time.d.ts.map +1 -1
- package/dist/types-frontend/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types-frontend/index.d.ts +4 -0
- package/dist/types-frontend/index.d.ts.map +1 -1
- package/dist/types-frontend/market-time.d.ts +25 -43
- package/dist/types-frontend/market-time.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -282,7 +282,7 @@ class MarketCalendar {
|
|
|
282
282
|
const yearHolidays = marketHolidays[year];
|
|
283
283
|
if (!yearHolidays)
|
|
284
284
|
return false;
|
|
285
|
-
return Object.values(yearHolidays).some(holiday => holiday.date === formattedDate);
|
|
285
|
+
return Object.values(yearHolidays).some((holiday) => holiday.date === formattedDate);
|
|
286
286
|
}
|
|
287
287
|
/**
|
|
288
288
|
* Checks if a date is an early close day in NY time.
|
|
@@ -398,7 +398,7 @@ function getMarketTimes(date) {
|
|
|
398
398
|
* @param intradayReporting - 'market_hours', 'extended_hours', or 'continuous'
|
|
399
399
|
* @returns true if within hours, false otherwise
|
|
400
400
|
*/
|
|
401
|
-
function
|
|
401
|
+
function isWithinMarketHours(date, intradayReporting = 'market_hours') {
|
|
402
402
|
const calendar = new MarketCalendar();
|
|
403
403
|
if (!calendar.isMarketDay(date))
|
|
404
404
|
return false;
|
|
@@ -441,7 +441,9 @@ function getLastFullTradingDateImpl(currentDate = new Date()) {
|
|
|
441
441
|
marketCloseMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
|
|
442
442
|
}
|
|
443
443
|
// If not a market day, or before open, or during market hours, return previous market day's close
|
|
444
|
-
if (!calendar.isMarketDay(currentDate) ||
|
|
444
|
+
if (!calendar.isMarketDay(currentDate) ||
|
|
445
|
+
minutes < marketOpenMinutes ||
|
|
446
|
+
(minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
|
|
445
447
|
const prevMarketDay = calendar.getPreviousMarketDay(currentDate);
|
|
446
448
|
let prevCloseMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
|
|
447
449
|
if (calendar.isEarlyCloseDay(prevMarketDay)) {
|
|
@@ -557,7 +559,7 @@ function calculatePeriodStartDate(endDate, period) {
|
|
|
557
559
|
* @returns PeriodDates object
|
|
558
560
|
*/
|
|
559
561
|
function getMarketTimePeriod(params) {
|
|
560
|
-
const { period, end = new Date(), intraday_reporting = 'market_hours', outputFormat = 'iso'
|
|
562
|
+
const { period, end = new Date(), intraday_reporting = 'market_hours', outputFormat = 'iso' } = params;
|
|
561
563
|
if (!period)
|
|
562
564
|
throw new Error('Period is required');
|
|
563
565
|
const calendar = new MarketCalendar();
|
|
@@ -620,7 +622,8 @@ function getMarketStatusImpl(date = new Date()) {
|
|
|
620
622
|
let extendedEndMinutes = MARKET_CONFIG.TIMES.EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EXTENDED_END.minute;
|
|
621
623
|
if (isEarlyCloseDay) {
|
|
622
624
|
marketCloseMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
|
|
623
|
-
extendedEndMinutes =
|
|
625
|
+
extendedEndMinutes =
|
|
626
|
+
MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute;
|
|
624
627
|
}
|
|
625
628
|
let status;
|
|
626
629
|
let nextStatus;
|
|
@@ -716,15 +719,36 @@ function getLastFullTradingDate(currentDate = new Date()) {
|
|
|
716
719
|
*/
|
|
717
720
|
function getNextMarketDay({ referenceDate } = {}) {
|
|
718
721
|
const calendar = new MarketCalendar();
|
|
719
|
-
const startDate = referenceDate
|
|
722
|
+
const startDate = referenceDate ?? new Date();
|
|
723
|
+
// Find the next trading day (UTC Date object)
|
|
720
724
|
const nextDate = calendar.getNextMarketDay(startDate);
|
|
721
|
-
|
|
725
|
+
// Convert to NY time before extracting Y-M-D parts
|
|
726
|
+
const nyNext = toNYTime(nextDate);
|
|
727
|
+
const yyyymmdd = `${nyNext.getUTCFullYear()}-${String(nyNext.getUTCMonth() + 1).padStart(2, '0')}-${String(nyNext.getUTCDate()).padStart(2, '0')}`;
|
|
722
728
|
return {
|
|
723
|
-
date: nextDate,
|
|
724
|
-
yyyymmdd,
|
|
729
|
+
date: nextDate, // raw Date, unchanged
|
|
730
|
+
yyyymmdd, // correct trading date string
|
|
725
731
|
dateISOString: nextDate.toISOString(),
|
|
726
732
|
};
|
|
727
733
|
}
|
|
734
|
+
/**
|
|
735
|
+
* Returns the previous market day before the reference date.
|
|
736
|
+
* @param referenceDate - Date object (default: now)
|
|
737
|
+
* @returns Object with date, yyyymmdd string, and ISO string
|
|
738
|
+
*/
|
|
739
|
+
function getPreviousMarketDay({ referenceDate } = {}) {
|
|
740
|
+
const calendar = new MarketCalendar();
|
|
741
|
+
const startDate = referenceDate || new Date();
|
|
742
|
+
const prevDate = calendar.getPreviousMarketDay(startDate);
|
|
743
|
+
// convert to NY time first
|
|
744
|
+
const nyPrev = toNYTime(prevDate); // ← already in this file
|
|
745
|
+
const yyyymmdd = `${nyPrev.getUTCFullYear()}-${String(nyPrev.getUTCMonth() + 1).padStart(2, '0')}-${String(nyPrev.getUTCDate()).padStart(2, '0')}`;
|
|
746
|
+
return {
|
|
747
|
+
date: prevDate,
|
|
748
|
+
yyyymmdd,
|
|
749
|
+
dateISOString: prevDate.toISOString(),
|
|
750
|
+
};
|
|
751
|
+
}
|
|
728
752
|
/**
|
|
729
753
|
* Returns the trading date for a given time. Note: Just trims the date string; does not validate if the date is a market day.
|
|
730
754
|
* @param time - a string, number (unix timestamp), or Date object representing the time
|
|
@@ -759,13 +783,13 @@ function getMarketStatus(options = {}) {
|
|
|
759
783
|
return getMarketStatusImpl(date);
|
|
760
784
|
}
|
|
761
785
|
/**
|
|
762
|
-
* Checks if a date
|
|
786
|
+
* Checks if a date is a market day.
|
|
763
787
|
* @param date - Date object
|
|
764
|
-
* @
|
|
765
|
-
* @returns true if within hours, false otherwise
|
|
788
|
+
* @returns true if market day, false otherwise
|
|
766
789
|
*/
|
|
767
|
-
function
|
|
768
|
-
|
|
790
|
+
function isMarketDay(date) {
|
|
791
|
+
const calendar = new MarketCalendar();
|
|
792
|
+
return calendar.isMarketDay(date);
|
|
769
793
|
}
|
|
770
794
|
/**
|
|
771
795
|
* Returns full trading days from market open to market close.
|
|
@@ -786,7 +810,9 @@ function getTradingStartAndEndDates(options = {}) {
|
|
|
786
810
|
const marketOpenMinutes = MARKET_CONFIG.TIMES.MARKET_OPEN.hour * 60 + MARKET_CONFIG.TIMES.MARKET_OPEN.minute;
|
|
787
811
|
const marketCloseMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
|
|
788
812
|
const minutes = nyEnd.getUTCHours() * 60 + nyEnd.getUTCMinutes();
|
|
789
|
-
if (!calendar.isMarketDay(endDate) ||
|
|
813
|
+
if (!calendar.isMarketDay(endDate) ||
|
|
814
|
+
minutes < marketOpenMinutes ||
|
|
815
|
+
(minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
|
|
790
816
|
// Before market open, not a market day, or during market hours: use previous market day
|
|
791
817
|
endMarketDay = calendar.getPreviousMarketDay(endDate);
|
|
792
818
|
}
|
|
@@ -879,7 +905,7 @@ function countTradingDays(startDate, endDate = new Date()) {
|
|
|
879
905
|
return {
|
|
880
906
|
days: Math.round(days * 1000) / 1000, // Round to 3 decimal places
|
|
881
907
|
hours: Math.round(hours * 100) / 100, // Round to 2 decimal places
|
|
882
|
-
minutes: Math.round(minutes)
|
|
908
|
+
minutes: Math.round(minutes),
|
|
883
909
|
};
|
|
884
910
|
}
|
|
885
911
|
// Export MARKET_TIMES for compatibility
|
|
@@ -887,27 +913,27 @@ const MARKET_TIMES = {
|
|
|
887
913
|
TIMEZONE: MARKET_CONFIG.TIMEZONE,
|
|
888
914
|
PRE: {
|
|
889
915
|
START: { HOUR: 4, MINUTE: 0, MINUTES: 240 },
|
|
890
|
-
END: { HOUR: 9, MINUTE: 30, MINUTES: 570 }
|
|
916
|
+
END: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
891
917
|
},
|
|
892
918
|
EARLY_MORNING: {
|
|
893
919
|
START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
894
|
-
END: { HOUR: 10, MINUTE: 0, MINUTES: 600 }
|
|
920
|
+
END: { HOUR: 10, MINUTE: 0, MINUTES: 600 },
|
|
895
921
|
},
|
|
896
922
|
EARLY_CLOSE_BEFORE_HOLIDAY: {
|
|
897
923
|
START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
898
|
-
END: { HOUR: 13, MINUTE: 0, MINUTES: 780 }
|
|
924
|
+
END: { HOUR: 13, MINUTE: 0, MINUTES: 780 },
|
|
899
925
|
},
|
|
900
926
|
EARLY_EXTENDED_BEFORE_HOLIDAY: {
|
|
901
927
|
START: { HOUR: 13, MINUTE: 0, MINUTES: 780 },
|
|
902
|
-
END: { HOUR: 17, MINUTE: 0, MINUTES: 1020 }
|
|
928
|
+
END: { HOUR: 17, MINUTE: 0, MINUTES: 1020 },
|
|
903
929
|
},
|
|
904
930
|
REGULAR: {
|
|
905
931
|
START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
906
|
-
END: { HOUR: 16, MINUTE: 0, MINUTES: 960 }
|
|
932
|
+
END: { HOUR: 16, MINUTE: 0, MINUTES: 960 },
|
|
907
933
|
},
|
|
908
934
|
EXTENDED: {
|
|
909
935
|
START: { HOUR: 4, MINUTE: 0, MINUTES: 240 },
|
|
910
|
-
END: { HOUR: 20, MINUTE: 0, MINUTES: 1200 }
|
|
936
|
+
END: { HOUR: 20, MINUTE: 0, MINUTES: 1200 },
|
|
911
937
|
},
|
|
912
938
|
};
|
|
913
939
|
|
|
@@ -16013,15 +16039,18 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16013
16039
|
stockSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
16014
16040
|
optionSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
16015
16041
|
setMode(mode = 'production') {
|
|
16016
|
-
if (mode === 'sandbox') {
|
|
16042
|
+
if (mode === 'sandbox') {
|
|
16043
|
+
// sandbox mode
|
|
16017
16044
|
this.stockStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v2/sip';
|
|
16018
16045
|
this.optionStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v1beta3/options';
|
|
16019
16046
|
}
|
|
16020
|
-
else if (mode === 'test') {
|
|
16047
|
+
else if (mode === 'test') {
|
|
16048
|
+
// test mode, can only use ticker FAKEPACA
|
|
16021
16049
|
this.stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/test';
|
|
16022
16050
|
this.optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options'; // there's no test mode for options
|
|
16023
16051
|
}
|
|
16024
|
-
else {
|
|
16052
|
+
else {
|
|
16053
|
+
// production
|
|
16025
16054
|
this.stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/sip';
|
|
16026
16055
|
this.optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options';
|
|
16027
16056
|
}
|
|
@@ -16169,7 +16198,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16169
16198
|
const currentSubscriptions = streamType === 'stock' ? this.stockSubscriptions : this.optionSubscriptions;
|
|
16170
16199
|
Object.entries(subscriptions).forEach(([key, value]) => {
|
|
16171
16200
|
if (value) {
|
|
16172
|
-
currentSubscriptions[key] = (currentSubscriptions[key] || []).filter(s => !value.includes(s));
|
|
16201
|
+
currentSubscriptions[key] = (currentSubscriptions[key] || []).filter((s) => !value.includes(s));
|
|
16173
16202
|
}
|
|
16174
16203
|
});
|
|
16175
16204
|
const unsubMessage = {
|
|
@@ -16232,11 +16261,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16232
16261
|
let pageCount = 0;
|
|
16233
16262
|
let currency = '';
|
|
16234
16263
|
// Initialize bar arrays for each symbol
|
|
16235
|
-
symbols.forEach(symbol => {
|
|
16264
|
+
symbols.forEach((symbol) => {
|
|
16236
16265
|
allBars[symbol] = [];
|
|
16237
16266
|
});
|
|
16238
|
-
log(`Starting historical bars fetch for ${symbolsStr} (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, {
|
|
16239
|
-
type: 'info'
|
|
16267
|
+
log(`Starting historical bars fetch for ${symbolsStr.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, {
|
|
16268
|
+
type: 'info',
|
|
16240
16269
|
});
|
|
16241
16270
|
while (hasMorePages) {
|
|
16242
16271
|
pageCount++;
|
|
@@ -16248,7 +16277,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16248
16277
|
};
|
|
16249
16278
|
const response = await this.makeRequest('/stocks/bars', 'GET', requestParams);
|
|
16250
16279
|
if (!response.bars) {
|
|
16251
|
-
log(`No bars data found in response for ${symbolsStr}`, { type: 'warn' });
|
|
16280
|
+
log(`No bars data found in response for ${symbolsStr.length} symbols`, { type: 'warn' });
|
|
16252
16281
|
break;
|
|
16253
16282
|
}
|
|
16254
16283
|
// Track currency from first response
|
|
@@ -16264,7 +16293,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16264
16293
|
allBars[symbol] = [...allBars[symbol], ...bars];
|
|
16265
16294
|
pageBarsCount += bars.length;
|
|
16266
16295
|
// Track date range for this page
|
|
16267
|
-
bars.forEach(bar => {
|
|
16296
|
+
bars.forEach((bar) => {
|
|
16268
16297
|
const barDate = new Date(bar.t);
|
|
16269
16298
|
if (!earliestTimestamp || barDate < earliestTimestamp) {
|
|
16270
16299
|
earliestTimestamp = barDate;
|
|
@@ -16283,7 +16312,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16283
16312
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
16284
16313
|
: 'unknown range';
|
|
16285
16314
|
log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} bars (total: ${totalBarsCount.toLocaleString()}) for ${symbolsStr}, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
|
|
16286
|
-
type: 'info'
|
|
16315
|
+
type: 'info',
|
|
16287
16316
|
});
|
|
16288
16317
|
// Prevent infinite loops
|
|
16289
16318
|
if (pageCount > 1000) {
|
|
@@ -16292,9 +16321,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16292
16321
|
}
|
|
16293
16322
|
}
|
|
16294
16323
|
// Final summary
|
|
16295
|
-
const symbolCounts = Object.entries(allBars)
|
|
16324
|
+
const symbolCounts = Object.entries(allBars)
|
|
16325
|
+
.map(([symbol, bars]) => `${symbol}: ${bars.length}`)
|
|
16326
|
+
.join(', ');
|
|
16296
16327
|
log(`Historical bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages (${symbolCounts})`, {
|
|
16297
|
-
type: 'info'
|
|
16328
|
+
type: 'info',
|
|
16298
16329
|
});
|
|
16299
16330
|
return {
|
|
16300
16331
|
bars: allBars,
|
|
@@ -16562,11 +16593,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16562
16593
|
let totalBarsCount = 0;
|
|
16563
16594
|
let pageCount = 0;
|
|
16564
16595
|
// Initialize bar arrays for each symbol
|
|
16565
|
-
symbols.forEach(symbol => {
|
|
16596
|
+
symbols.forEach((symbol) => {
|
|
16566
16597
|
allBars[symbol] = [];
|
|
16567
16598
|
});
|
|
16568
|
-
log(`Starting historical options bars fetch for ${symbolsStr} (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, {
|
|
16569
|
-
type: 'info'
|
|
16599
|
+
log(`Starting historical options bars fetch for ${symbolsStr.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`, {
|
|
16600
|
+
type: 'info',
|
|
16570
16601
|
});
|
|
16571
16602
|
while (hasMorePages) {
|
|
16572
16603
|
pageCount++;
|
|
@@ -16576,7 +16607,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16576
16607
|
};
|
|
16577
16608
|
const response = await this.makeRequest('/options/bars', 'GET', requestParams, 'v1beta1');
|
|
16578
16609
|
if (!response.bars) {
|
|
16579
|
-
log(`No options bars data found in response for ${symbolsStr}`, { type: 'warn' });
|
|
16610
|
+
log(`No options bars data found in response for ${symbolsStr.length} symbols`, { type: 'warn' });
|
|
16580
16611
|
break;
|
|
16581
16612
|
}
|
|
16582
16613
|
// Combine bars for each symbol
|
|
@@ -16588,7 +16619,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16588
16619
|
allBars[symbol] = [...allBars[symbol], ...bars];
|
|
16589
16620
|
pageBarsCount += bars.length;
|
|
16590
16621
|
// Track date range for this page
|
|
16591
|
-
bars.forEach(bar => {
|
|
16622
|
+
bars.forEach((bar) => {
|
|
16592
16623
|
const barDate = new Date(bar.t);
|
|
16593
16624
|
if (!earliestTimestamp || barDate < earliestTimestamp) {
|
|
16594
16625
|
earliestTimestamp = barDate;
|
|
@@ -16607,7 +16638,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16607
16638
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
16608
16639
|
: 'unknown range';
|
|
16609
16640
|
log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} option bars (total: ${totalBarsCount.toLocaleString()}) for ${symbolsStr}, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
|
|
16610
|
-
type: 'info'
|
|
16641
|
+
type: 'info',
|
|
16611
16642
|
});
|
|
16612
16643
|
// Prevent infinite loops
|
|
16613
16644
|
if (pageCount > 1000) {
|
|
@@ -16616,9 +16647,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16616
16647
|
}
|
|
16617
16648
|
}
|
|
16618
16649
|
// Final summary
|
|
16619
|
-
const symbolCounts = Object.entries(allBars)
|
|
16650
|
+
const symbolCounts = Object.entries(allBars)
|
|
16651
|
+
.map(([symbol, bars]) => `${symbol}: ${bars.length}`)
|
|
16652
|
+
.join(', ');
|
|
16620
16653
|
log(`Historical options bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages (${symbolCounts})`, {
|
|
16621
|
-
type: 'info'
|
|
16654
|
+
type: 'info',
|
|
16622
16655
|
});
|
|
16623
16656
|
return {
|
|
16624
16657
|
bars: allBars,
|
|
@@ -16642,11 +16675,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16642
16675
|
let totalTradesCount = 0;
|
|
16643
16676
|
let pageCount = 0;
|
|
16644
16677
|
// Initialize trades arrays for each symbol
|
|
16645
|
-
symbols.forEach(symbol => {
|
|
16678
|
+
symbols.forEach((symbol) => {
|
|
16646
16679
|
allTrades[symbol] = [];
|
|
16647
16680
|
});
|
|
16648
|
-
log(`Starting historical options trades fetch for ${symbolsStr} (${params.start || 'no start'} to ${params.end || 'no end'})`, {
|
|
16649
|
-
type: 'info'
|
|
16681
|
+
log(`Starting historical options trades fetch for ${symbolsStr.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`, {
|
|
16682
|
+
type: 'info',
|
|
16650
16683
|
});
|
|
16651
16684
|
while (hasMorePages) {
|
|
16652
16685
|
pageCount++;
|
|
@@ -16656,7 +16689,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16656
16689
|
};
|
|
16657
16690
|
const response = await this.makeRequest('/options/trades', 'GET', requestParams, 'v1beta1');
|
|
16658
16691
|
if (!response.trades) {
|
|
16659
|
-
log(`No options trades data found in response for ${symbolsStr}`, { type: 'warn' });
|
|
16692
|
+
log(`No options trades data found in response for ${symbolsStr.length} symbols`, { type: 'warn' });
|
|
16660
16693
|
break;
|
|
16661
16694
|
}
|
|
16662
16695
|
// Combine trades for each symbol
|
|
@@ -16668,7 +16701,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16668
16701
|
allTrades[symbol] = [...allTrades[symbol], ...trades];
|
|
16669
16702
|
pageTradesCount += trades.length;
|
|
16670
16703
|
// Track date range for this page
|
|
16671
|
-
trades.forEach(trade => {
|
|
16704
|
+
trades.forEach((trade) => {
|
|
16672
16705
|
const tradeDate = new Date(trade.t);
|
|
16673
16706
|
if (!earliestTimestamp || tradeDate < earliestTimestamp) {
|
|
16674
16707
|
earliestTimestamp = tradeDate;
|
|
@@ -16686,8 +16719,8 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16686
16719
|
const dateRangeStr = earliestTimestamp && latestTimestamp
|
|
16687
16720
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
16688
16721
|
: 'unknown range';
|
|
16689
|
-
log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} option trades (total: ${totalTradesCount.toLocaleString()}) for ${symbolsStr}, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
|
|
16690
|
-
type: 'info'
|
|
16722
|
+
log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} option trades (total: ${totalTradesCount.toLocaleString()}) for ${symbolsStr.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
|
|
16723
|
+
type: 'info',
|
|
16691
16724
|
});
|
|
16692
16725
|
// Prevent infinite loops
|
|
16693
16726
|
if (pageCount > 1000) {
|
|
@@ -16696,9 +16729,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16696
16729
|
}
|
|
16697
16730
|
}
|
|
16698
16731
|
// Final summary
|
|
16699
|
-
const symbolCounts = Object.entries(allTrades)
|
|
16732
|
+
const symbolCounts = Object.entries(allTrades)
|
|
16733
|
+
.map(([symbol, trades]) => `${symbol}: ${trades.length}`)
|
|
16734
|
+
.join(', ');
|
|
16700
16735
|
log(`Historical options trades fetch complete: ${totalTradesCount.toLocaleString()} total trades across ${pageCount} pages (${symbolCounts})`, {
|
|
16701
|
-
type: 'info'
|
|
16736
|
+
type: 'info',
|
|
16702
16737
|
});
|
|
16703
16738
|
return {
|
|
16704
16739
|
trades: allTrades,
|
|
@@ -16843,7 +16878,9 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
16843
16878
|
...(symbol && { symbols: symbol }),
|
|
16844
16879
|
...(mergedParams.limit && { limit: Math.min(50, maxLimit - fetchedCount).toString() }),
|
|
16845
16880
|
...(mergedParams.sort && { sort: mergedParams.sort }),
|
|
16846
|
-
...(mergedParams.include_content !== undefined
|
|
16881
|
+
...(mergedParams.include_content !== undefined
|
|
16882
|
+
? { include_content: mergedParams.include_content.toString() }
|
|
16883
|
+
: {}),
|
|
16847
16884
|
...(pageToken && { page_token: pageToken }),
|
|
16848
16885
|
});
|
|
16849
16886
|
const url = `${this.v1beta1url}/news?${queryParams}`;
|
|
@@ -18270,10 +18307,14 @@ const disco = {
|
|
|
18270
18307
|
getMarketOpenClose: getMarketOpenClose,
|
|
18271
18308
|
getLastFullTradingDate: getLastFullTradingDate,
|
|
18272
18309
|
getNextMarketDay: getNextMarketDay,
|
|
18310
|
+
getPreviousMarketDay: getPreviousMarketDay,
|
|
18311
|
+
getMarketTimePeriod: getMarketTimePeriod,
|
|
18273
18312
|
getMarketStatus: getMarketStatus,
|
|
18274
18313
|
getNYTimeZone: getNYTimeZone,
|
|
18275
18314
|
getTradingDate: getTradingDate,
|
|
18276
18315
|
getTradingStartAndEndDates: getTradingStartAndEndDates,
|
|
18316
|
+
isMarketDay: isMarketDay,
|
|
18317
|
+
isWithinMarketHours: isWithinMarketHours,
|
|
18277
18318
|
countTradingDays: countTradingDays,
|
|
18278
18319
|
MARKET_TIMES: MARKET_TIMES,
|
|
18279
18320
|
},
|