@discomedia/utils 1.0.30 → 1.0.32
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 +103 -3
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +103 -3
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +106 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +106 -5
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +4 -4
- package/dist/test.js +793 -85
- package/dist/test.js.map +1 -1
- package/dist/types/index-frontend.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/market-time.d.ts.map +1 -1
- package/dist/types-frontend/index-frontend.d.ts +1 -1
- package/dist/types-frontend/index.d.ts +1 -1
- package/dist/types-frontend/market-time.d.ts.map +1 -1
- package/package.json +4 -4
- package/dist/alpaca-trading-api-CPaXTnjf.js +0 -1412
- package/dist/alpaca-trading-api-CPaXTnjf.js.map +0 -1
package/dist/test.js
CHANGED
|
@@ -146,12 +146,18 @@ const marketEarlyCloses = {
|
|
|
146
146
|
|
|
147
147
|
// Constants for NY market times (Eastern Time)
|
|
148
148
|
const MARKET_CONFIG = {
|
|
149
|
+
TIMEZONE: 'America/New_York',
|
|
149
150
|
UTC_OFFSET_STANDARD: -5, // EST
|
|
150
151
|
UTC_OFFSET_DST: -4, // EDT
|
|
151
152
|
TIMES: {
|
|
153
|
+
EXTENDED_START: { hour: 4, minute: 0 },
|
|
152
154
|
MARKET_OPEN: { hour: 9, minute: 30 },
|
|
155
|
+
EARLY_MARKET_END: { hour: 10, minute: 0 },
|
|
153
156
|
MARKET_CLOSE: { hour: 16, minute: 0 },
|
|
154
|
-
EARLY_CLOSE: { hour: 13, minute: 0 }
|
|
157
|
+
EARLY_CLOSE: { hour: 13, minute: 0 },
|
|
158
|
+
EXTENDED_END: { hour: 20, minute: 0 },
|
|
159
|
+
EARLY_EXTENDED_END: { hour: 17, minute: 0 },
|
|
160
|
+
},
|
|
155
161
|
};
|
|
156
162
|
// Helper: Get NY offset for a given UTC date (DST rules for US)
|
|
157
163
|
/**
|
|
@@ -219,6 +225,33 @@ function fromNYTime(date) {
|
|
|
219
225
|
const utcMillis = nyMillis - offset * 60 * 60 * 1000;
|
|
220
226
|
return new Date(utcMillis);
|
|
221
227
|
}
|
|
228
|
+
// Helper: Format date in ISO, unix, etc.
|
|
229
|
+
/**
|
|
230
|
+
* Formats a date in ISO, unix-seconds, or unix-ms format.
|
|
231
|
+
* @param date - Date object
|
|
232
|
+
* @param outputFormat - Output format ('iso', 'unix-seconds', 'unix-ms')
|
|
233
|
+
* @returns Formatted date string or number
|
|
234
|
+
*/
|
|
235
|
+
function formatDate(date, outputFormat = 'iso') {
|
|
236
|
+
switch (outputFormat) {
|
|
237
|
+
case 'unix-seconds':
|
|
238
|
+
return Math.floor(date.getTime() / 1000);
|
|
239
|
+
case 'unix-ms':
|
|
240
|
+
return date.getTime();
|
|
241
|
+
case 'iso':
|
|
242
|
+
default:
|
|
243
|
+
return date.toISOString();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Helper: Format date in NY locale string
|
|
247
|
+
/**
|
|
248
|
+
* Formats a date in NY locale string.
|
|
249
|
+
* @param date - Date object
|
|
250
|
+
* @returns NY locale string
|
|
251
|
+
*/
|
|
252
|
+
function formatNYLocale(date) {
|
|
253
|
+
return date.toLocaleString('en-US', { timeZone: 'America/New_York' });
|
|
254
|
+
}
|
|
222
255
|
// Market calendar logic
|
|
223
256
|
/**
|
|
224
257
|
* Market calendar logic for holidays, weekends, and market days.
|
|
@@ -314,6 +347,82 @@ class MarketCalendar {
|
|
|
314
347
|
return prevDay;
|
|
315
348
|
}
|
|
316
349
|
}
|
|
350
|
+
// Market open/close times
|
|
351
|
+
/**
|
|
352
|
+
* Returns market open/close times for a given date, including extended and early closes.
|
|
353
|
+
* @param date - Date object
|
|
354
|
+
* @returns MarketOpenCloseResult
|
|
355
|
+
*/
|
|
356
|
+
function getMarketTimes(date) {
|
|
357
|
+
const calendar = new MarketCalendar();
|
|
358
|
+
const nyDate = toNYTime(date);
|
|
359
|
+
if (!calendar.isMarketDay(date)) {
|
|
360
|
+
return {
|
|
361
|
+
marketOpen: false,
|
|
362
|
+
open: null,
|
|
363
|
+
close: null,
|
|
364
|
+
openExt: null,
|
|
365
|
+
closeExt: null,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
const year = nyDate.getUTCFullYear();
|
|
369
|
+
const month = nyDate.getUTCMonth();
|
|
370
|
+
const day = nyDate.getUTCDate();
|
|
371
|
+
// Helper to build NY time for a given hour/minute
|
|
372
|
+
function buildNYTime(hour, minute) {
|
|
373
|
+
const d = new Date(Date.UTC(year, month, day, hour, minute, 0, 0));
|
|
374
|
+
return fromNYTime(d);
|
|
375
|
+
}
|
|
376
|
+
let open = buildNYTime(MARKET_CONFIG.TIMES.MARKET_OPEN.hour, MARKET_CONFIG.TIMES.MARKET_OPEN.minute);
|
|
377
|
+
let close = buildNYTime(MARKET_CONFIG.TIMES.MARKET_CLOSE.hour, MARKET_CONFIG.TIMES.MARKET_CLOSE.minute);
|
|
378
|
+
let openExt = buildNYTime(MARKET_CONFIG.TIMES.EXTENDED_START.hour, MARKET_CONFIG.TIMES.EXTENDED_START.minute);
|
|
379
|
+
let closeExt = buildNYTime(MARKET_CONFIG.TIMES.EXTENDED_END.hour, MARKET_CONFIG.TIMES.EXTENDED_END.minute);
|
|
380
|
+
if (calendar.isEarlyCloseDay(date)) {
|
|
381
|
+
close = buildNYTime(MARKET_CONFIG.TIMES.EARLY_CLOSE.hour, MARKET_CONFIG.TIMES.EARLY_CLOSE.minute);
|
|
382
|
+
closeExt = buildNYTime(MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour, MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute);
|
|
383
|
+
}
|
|
384
|
+
return {
|
|
385
|
+
marketOpen: true,
|
|
386
|
+
open,
|
|
387
|
+
close,
|
|
388
|
+
openExt,
|
|
389
|
+
closeExt,
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
// Is within market hours
|
|
393
|
+
/**
|
|
394
|
+
* Checks if a date/time is within market hours, extended hours, or continuous.
|
|
395
|
+
* @param date - Date object
|
|
396
|
+
* @param intradayReporting - 'market_hours', 'extended_hours', or 'continuous'
|
|
397
|
+
* @returns true if within hours, false otherwise
|
|
398
|
+
*/
|
|
399
|
+
function isWithinMarketHours(date, intradayReporting = 'market_hours') {
|
|
400
|
+
const calendar = new MarketCalendar();
|
|
401
|
+
if (!calendar.isMarketDay(date))
|
|
402
|
+
return false;
|
|
403
|
+
const nyDate = toNYTime(date);
|
|
404
|
+
const minutes = nyDate.getUTCHours() * 60 + nyDate.getUTCMinutes();
|
|
405
|
+
switch (intradayReporting) {
|
|
406
|
+
case 'extended_hours': {
|
|
407
|
+
let endMinutes = MARKET_CONFIG.TIMES.EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EXTENDED_END.minute;
|
|
408
|
+
if (calendar.isEarlyCloseDay(date)) {
|
|
409
|
+
endMinutes = MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute;
|
|
410
|
+
}
|
|
411
|
+
const startMinutes = MARKET_CONFIG.TIMES.EXTENDED_START.hour * 60 + MARKET_CONFIG.TIMES.EXTENDED_START.minute;
|
|
412
|
+
return minutes >= startMinutes && minutes <= endMinutes;
|
|
413
|
+
}
|
|
414
|
+
case 'continuous':
|
|
415
|
+
return true;
|
|
416
|
+
default: {
|
|
417
|
+
let endMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
|
|
418
|
+
if (calendar.isEarlyCloseDay(date)) {
|
|
419
|
+
endMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
|
|
420
|
+
}
|
|
421
|
+
const startMinutes = MARKET_CONFIG.TIMES.MARKET_OPEN.hour * 60 + MARKET_CONFIG.TIMES.MARKET_OPEN.minute;
|
|
422
|
+
return minutes >= startMinutes && minutes <= endMinutes;
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
317
426
|
// Get last full trading date
|
|
318
427
|
/**
|
|
319
428
|
* Returns the last full trading date (market close) for a given date.
|
|
@@ -353,6 +462,244 @@ function getLastFullTradingDateImpl(currentDate = new Date()) {
|
|
|
353
462
|
const closeMinute = marketCloseMinutes % 60;
|
|
354
463
|
return fromNYTime(new Date(Date.UTC(year, month, day, closeHour, closeMinute, 0, 0)));
|
|
355
464
|
}
|
|
465
|
+
// Get day boundaries
|
|
466
|
+
/**
|
|
467
|
+
* Returns the start and end boundaries for a market day, extended hours, or continuous.
|
|
468
|
+
* @param date - Date object
|
|
469
|
+
* @param intradayReporting - 'market_hours', 'extended_hours', or 'continuous'
|
|
470
|
+
* @returns Object with start and end Date
|
|
471
|
+
*/
|
|
472
|
+
function getDayBoundaries(date, intradayReporting = 'market_hours') {
|
|
473
|
+
const calendar = new MarketCalendar();
|
|
474
|
+
const nyDate = toNYTime(date);
|
|
475
|
+
const year = nyDate.getUTCFullYear();
|
|
476
|
+
const month = nyDate.getUTCMonth();
|
|
477
|
+
const day = nyDate.getUTCDate();
|
|
478
|
+
function buildNYTime(hour, minute, sec = 0, ms = 0) {
|
|
479
|
+
const d = new Date(Date.UTC(year, month, day, hour, minute, sec, ms));
|
|
480
|
+
return fromNYTime(d);
|
|
481
|
+
}
|
|
482
|
+
let start;
|
|
483
|
+
let end;
|
|
484
|
+
switch (intradayReporting) {
|
|
485
|
+
case 'extended_hours':
|
|
486
|
+
start = buildNYTime(MARKET_CONFIG.TIMES.EXTENDED_START.hour, MARKET_CONFIG.TIMES.EXTENDED_START.minute, 0, 0);
|
|
487
|
+
end = buildNYTime(MARKET_CONFIG.TIMES.EXTENDED_END.hour, MARKET_CONFIG.TIMES.EXTENDED_END.minute, 59, 999);
|
|
488
|
+
if (calendar.isEarlyCloseDay(date)) {
|
|
489
|
+
end = buildNYTime(MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour, MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute, 59, 999);
|
|
490
|
+
}
|
|
491
|
+
break;
|
|
492
|
+
case 'continuous':
|
|
493
|
+
start = new Date(Date.UTC(year, month, day, 0, 0, 0, 0));
|
|
494
|
+
end = new Date(Date.UTC(year, month, day, 23, 59, 59, 999));
|
|
495
|
+
break;
|
|
496
|
+
default:
|
|
497
|
+
start = buildNYTime(MARKET_CONFIG.TIMES.MARKET_OPEN.hour, MARKET_CONFIG.TIMES.MARKET_OPEN.minute, 0, 0);
|
|
498
|
+
end = buildNYTime(MARKET_CONFIG.TIMES.MARKET_CLOSE.hour, MARKET_CONFIG.TIMES.MARKET_CLOSE.minute, 59, 999);
|
|
499
|
+
if (calendar.isEarlyCloseDay(date)) {
|
|
500
|
+
end = buildNYTime(MARKET_CONFIG.TIMES.EARLY_CLOSE.hour, MARKET_CONFIG.TIMES.EARLY_CLOSE.minute, 59, 999);
|
|
501
|
+
}
|
|
502
|
+
break;
|
|
503
|
+
}
|
|
504
|
+
return { start, end };
|
|
505
|
+
}
|
|
506
|
+
// Period calculator
|
|
507
|
+
/**
|
|
508
|
+
* Calculates the start date for a given period ending at endDate.
|
|
509
|
+
* @param endDate - Date object
|
|
510
|
+
* @param period - Period string
|
|
511
|
+
* @returns Date object for period start
|
|
512
|
+
*/
|
|
513
|
+
function calculatePeriodStartDate(endDate, period) {
|
|
514
|
+
const calendar = new MarketCalendar();
|
|
515
|
+
let startDate;
|
|
516
|
+
switch (period) {
|
|
517
|
+
case 'YTD':
|
|
518
|
+
startDate = new Date(Date.UTC(endDate.getUTCFullYear(), 0, 1));
|
|
519
|
+
break;
|
|
520
|
+
case '1D':
|
|
521
|
+
startDate = calendar.getPreviousMarketDay(endDate);
|
|
522
|
+
break;
|
|
523
|
+
case '3D':
|
|
524
|
+
startDate = new Date(endDate.getTime() - 3 * 24 * 60 * 60 * 1000);
|
|
525
|
+
break;
|
|
526
|
+
case '1W':
|
|
527
|
+
startDate = new Date(endDate.getTime() - 7 * 24 * 60 * 60 * 1000);
|
|
528
|
+
break;
|
|
529
|
+
case '2W':
|
|
530
|
+
startDate = new Date(endDate.getTime() - 14 * 24 * 60 * 60 * 1000);
|
|
531
|
+
break;
|
|
532
|
+
case '1M':
|
|
533
|
+
startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth() - 1, endDate.getUTCDate()));
|
|
534
|
+
break;
|
|
535
|
+
case '3M':
|
|
536
|
+
startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth() - 3, endDate.getUTCDate()));
|
|
537
|
+
break;
|
|
538
|
+
case '6M':
|
|
539
|
+
startDate = new Date(Date.UTC(endDate.getUTCFullYear(), endDate.getUTCMonth() - 6, endDate.getUTCDate()));
|
|
540
|
+
break;
|
|
541
|
+
case '1Y':
|
|
542
|
+
startDate = new Date(Date.UTC(endDate.getUTCFullYear() - 1, endDate.getUTCMonth(), endDate.getUTCDate()));
|
|
543
|
+
break;
|
|
544
|
+
default:
|
|
545
|
+
throw new Error(`Invalid period: ${period}`);
|
|
546
|
+
}
|
|
547
|
+
// Ensure start date is a market day
|
|
548
|
+
while (!calendar.isMarketDay(startDate)) {
|
|
549
|
+
startDate = calendar.getNextMarketDay(startDate);
|
|
550
|
+
}
|
|
551
|
+
return startDate;
|
|
552
|
+
}
|
|
553
|
+
// Get market time period
|
|
554
|
+
/**
|
|
555
|
+
* Returns the start and end dates for a market time period.
|
|
556
|
+
* @param params - MarketTimeParams
|
|
557
|
+
* @returns PeriodDates object
|
|
558
|
+
*/
|
|
559
|
+
function getMarketTimePeriod(params) {
|
|
560
|
+
const { period, end = new Date(), intraday_reporting = 'market_hours', outputFormat = 'iso' } = params;
|
|
561
|
+
if (!period)
|
|
562
|
+
throw new Error('Period is required');
|
|
563
|
+
const calendar = new MarketCalendar();
|
|
564
|
+
const nyEndDate = toNYTime(end);
|
|
565
|
+
let endDate;
|
|
566
|
+
const isCurrentMarketDay = calendar.isMarketDay(end);
|
|
567
|
+
const isWithinHours = isWithinMarketHours(end, intraday_reporting);
|
|
568
|
+
const minutes = nyEndDate.getUTCHours() * 60 + nyEndDate.getUTCMinutes();
|
|
569
|
+
const marketStartMinutes = MARKET_CONFIG.TIMES.MARKET_OPEN.hour * 60 + MARKET_CONFIG.TIMES.MARKET_OPEN.minute;
|
|
570
|
+
if (isCurrentMarketDay) {
|
|
571
|
+
if (minutes < marketStartMinutes) {
|
|
572
|
+
// Before market open - use previous day's close
|
|
573
|
+
const lastMarketDay = calendar.getPreviousMarketDay(end);
|
|
574
|
+
const { end: dayEnd } = getDayBoundaries(lastMarketDay, intraday_reporting);
|
|
575
|
+
endDate = dayEnd;
|
|
576
|
+
}
|
|
577
|
+
else if (isWithinHours) {
|
|
578
|
+
// During market hours - use current time
|
|
579
|
+
endDate = end;
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
// After market close - use today's close
|
|
583
|
+
const { end: dayEnd } = getDayBoundaries(end, intraday_reporting);
|
|
584
|
+
endDate = dayEnd;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
// Not a market day - use previous market day's close
|
|
589
|
+
const lastMarketDay = calendar.getPreviousMarketDay(end);
|
|
590
|
+
const { end: dayEnd } = getDayBoundaries(lastMarketDay, intraday_reporting);
|
|
591
|
+
endDate = dayEnd;
|
|
592
|
+
}
|
|
593
|
+
// Calculate start date
|
|
594
|
+
const periodStartDate = calculatePeriodStartDate(endDate, period);
|
|
595
|
+
const { start: dayStart } = getDayBoundaries(periodStartDate, intraday_reporting);
|
|
596
|
+
if (endDate.getTime() < dayStart.getTime()) {
|
|
597
|
+
throw new Error('Start date cannot be after end date');
|
|
598
|
+
}
|
|
599
|
+
return {
|
|
600
|
+
start: formatDate(dayStart, outputFormat),
|
|
601
|
+
end: formatDate(endDate, outputFormat),
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
// Market status
|
|
605
|
+
/**
|
|
606
|
+
* Returns the current market status for a given date.
|
|
607
|
+
* @param date - Date object (default: now)
|
|
608
|
+
* @returns MarketStatus object
|
|
609
|
+
*/
|
|
610
|
+
function getMarketStatusImpl(date = new Date()) {
|
|
611
|
+
const calendar = new MarketCalendar();
|
|
612
|
+
const nyDate = toNYTime(date);
|
|
613
|
+
const minutes = nyDate.getUTCHours() * 60 + nyDate.getUTCMinutes();
|
|
614
|
+
const isMarketDay = calendar.isMarketDay(date);
|
|
615
|
+
const isEarlyCloseDay = calendar.isEarlyCloseDay(date);
|
|
616
|
+
const extendedStartMinutes = MARKET_CONFIG.TIMES.EXTENDED_START.hour * 60 + MARKET_CONFIG.TIMES.EXTENDED_START.minute;
|
|
617
|
+
const marketStartMinutes = MARKET_CONFIG.TIMES.MARKET_OPEN.hour * 60 + MARKET_CONFIG.TIMES.MARKET_OPEN.minute;
|
|
618
|
+
const earlyMarketEndMinutes = MARKET_CONFIG.TIMES.EARLY_MARKET_END.hour * 60 + MARKET_CONFIG.TIMES.EARLY_MARKET_END.minute;
|
|
619
|
+
let marketCloseMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
|
|
620
|
+
let extendedEndMinutes = MARKET_CONFIG.TIMES.EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EXTENDED_END.minute;
|
|
621
|
+
if (isEarlyCloseDay) {
|
|
622
|
+
marketCloseMinutes = MARKET_CONFIG.TIMES.EARLY_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.EARLY_CLOSE.minute;
|
|
623
|
+
extendedEndMinutes =
|
|
624
|
+
MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.hour * 60 + MARKET_CONFIG.TIMES.EARLY_EXTENDED_END.minute;
|
|
625
|
+
}
|
|
626
|
+
let status;
|
|
627
|
+
let nextStatus;
|
|
628
|
+
let nextStatusTime;
|
|
629
|
+
let marketPeriod;
|
|
630
|
+
if (!isMarketDay) {
|
|
631
|
+
status = 'closed';
|
|
632
|
+
nextStatus = 'extended hours';
|
|
633
|
+
marketPeriod = 'closed';
|
|
634
|
+
const nextMarketDay = calendar.getNextMarketDay(date);
|
|
635
|
+
nextStatusTime = getDayBoundaries(nextMarketDay, 'extended_hours').start;
|
|
636
|
+
}
|
|
637
|
+
else if (minutes < extendedStartMinutes) {
|
|
638
|
+
status = 'closed';
|
|
639
|
+
nextStatus = 'extended hours';
|
|
640
|
+
marketPeriod = 'closed';
|
|
641
|
+
nextStatusTime = getDayBoundaries(date, 'extended_hours').start;
|
|
642
|
+
}
|
|
643
|
+
else if (minutes < marketStartMinutes) {
|
|
644
|
+
status = 'extended hours';
|
|
645
|
+
nextStatus = 'open';
|
|
646
|
+
marketPeriod = 'preMarket';
|
|
647
|
+
nextStatusTime = getDayBoundaries(date, 'market_hours').start;
|
|
648
|
+
}
|
|
649
|
+
else if (minutes < marketCloseMinutes) {
|
|
650
|
+
status = 'open';
|
|
651
|
+
nextStatus = 'extended hours';
|
|
652
|
+
marketPeriod = minutes < earlyMarketEndMinutes ? 'earlyMarket' : 'regularMarket';
|
|
653
|
+
nextStatusTime = getDayBoundaries(date, 'market_hours').end;
|
|
654
|
+
}
|
|
655
|
+
else if (minutes < extendedEndMinutes) {
|
|
656
|
+
status = 'extended hours';
|
|
657
|
+
nextStatus = 'closed';
|
|
658
|
+
marketPeriod = 'afterMarket';
|
|
659
|
+
nextStatusTime = getDayBoundaries(date, 'extended_hours').end;
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
status = 'closed';
|
|
663
|
+
nextStatus = 'extended hours';
|
|
664
|
+
marketPeriod = 'closed';
|
|
665
|
+
const nextMarketDay = calendar.getNextMarketDay(date);
|
|
666
|
+
nextStatusTime = getDayBoundaries(nextMarketDay, 'extended_hours').start;
|
|
667
|
+
}
|
|
668
|
+
// I think using nyDate here may be wrong - should use current time? i.e. date.getTime()
|
|
669
|
+
const nextStatusTimeDifference = nextStatusTime.getTime() - date.getTime();
|
|
670
|
+
return {
|
|
671
|
+
time: date,
|
|
672
|
+
timeString: formatNYLocale(nyDate),
|
|
673
|
+
status,
|
|
674
|
+
nextStatus,
|
|
675
|
+
marketPeriod,
|
|
676
|
+
nextStatusTime,
|
|
677
|
+
nextStatusTimeDifference,
|
|
678
|
+
nextStatusTimeString: formatNYLocale(nextStatusTime),
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
// API exports
|
|
682
|
+
/**
|
|
683
|
+
* Returns market open/close times for a given date.
|
|
684
|
+
* @param options - { date?: Date }
|
|
685
|
+
* @returns MarketOpenCloseResult
|
|
686
|
+
*/
|
|
687
|
+
function getMarketOpenClose(options = {}) {
|
|
688
|
+
const { date = new Date() } = options;
|
|
689
|
+
return getMarketTimes(date);
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Returns the start and end dates for a market time period as Date objects.
|
|
693
|
+
* @param params - MarketTimeParams
|
|
694
|
+
* @returns Object with start and end Date
|
|
695
|
+
*/
|
|
696
|
+
function getStartAndEndDates(params = {}) {
|
|
697
|
+
const { start, end } = getMarketTimePeriod(params);
|
|
698
|
+
return {
|
|
699
|
+
start: typeof start === 'string' || typeof start === 'number' ? new Date(start) : start,
|
|
700
|
+
end: typeof end === 'string' || typeof end === 'number' ? new Date(end) : end,
|
|
701
|
+
};
|
|
702
|
+
}
|
|
356
703
|
/**
|
|
357
704
|
* Returns the last full trading date as a Date object.
|
|
358
705
|
*/
|
|
@@ -364,6 +711,230 @@ function getLastFullTradingDateImpl(currentDate = new Date()) {
|
|
|
364
711
|
function getLastFullTradingDate(currentDate = new Date()) {
|
|
365
712
|
return getLastFullTradingDateImpl(currentDate);
|
|
366
713
|
}
|
|
714
|
+
/**
|
|
715
|
+
* Returns the next market day after the reference date.
|
|
716
|
+
* @param referenceDate - Date object (default: now)
|
|
717
|
+
* @returns Object with date, yyyymmdd string, and ISO string
|
|
718
|
+
*/
|
|
719
|
+
function getNextMarketDay({ referenceDate } = {}) {
|
|
720
|
+
const calendar = new MarketCalendar();
|
|
721
|
+
const startDate = referenceDate ?? new Date();
|
|
722
|
+
// Find the next trading day (UTC Date object)
|
|
723
|
+
const nextDate = calendar.getNextMarketDay(startDate);
|
|
724
|
+
// Convert to NY time before extracting Y-M-D parts
|
|
725
|
+
const nyNext = toNYTime(nextDate);
|
|
726
|
+
const yyyymmdd = `${nyNext.getUTCFullYear()}-${String(nyNext.getUTCMonth() + 1).padStart(2, '0')}-${String(nyNext.getUTCDate()).padStart(2, '0')}`;
|
|
727
|
+
return {
|
|
728
|
+
date: nextDate, // raw Date, unchanged
|
|
729
|
+
yyyymmdd, // correct trading date string
|
|
730
|
+
dateISOString: nextDate.toISOString(),
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Returns the previous market day before the reference date.
|
|
735
|
+
* @param referenceDate - Date object (default: now)
|
|
736
|
+
* @returns Object with date, yyyymmdd string, and ISO string
|
|
737
|
+
*/
|
|
738
|
+
function getPreviousMarketDay({ referenceDate } = {}) {
|
|
739
|
+
const calendar = new MarketCalendar();
|
|
740
|
+
const startDate = referenceDate || new Date();
|
|
741
|
+
const prevDate = calendar.getPreviousMarketDay(startDate);
|
|
742
|
+
// convert to NY time first
|
|
743
|
+
const nyPrev = toNYTime(prevDate); // ← already in this file
|
|
744
|
+
const yyyymmdd = `${nyPrev.getUTCFullYear()}-${String(nyPrev.getUTCMonth() + 1).padStart(2, '0')}-${String(nyPrev.getUTCDate()).padStart(2, '0')}`;
|
|
745
|
+
return {
|
|
746
|
+
date: prevDate,
|
|
747
|
+
yyyymmdd,
|
|
748
|
+
dateISOString: prevDate.toISOString(),
|
|
749
|
+
};
|
|
750
|
+
}
|
|
751
|
+
/**
|
|
752
|
+
* Returns the trading date for a given time. Note: Just trims the date string; does not validate if the date is a market day.
|
|
753
|
+
* @param time - a string, number (unix timestamp), or Date object representing the time
|
|
754
|
+
* @returns the trading date as a string in YYYY-MM-DD format
|
|
755
|
+
*/
|
|
756
|
+
/**
|
|
757
|
+
* Returns the trading date for a given time in YYYY-MM-DD format (NY time).
|
|
758
|
+
* @param time - string, number, or Date
|
|
759
|
+
* @returns trading date string
|
|
760
|
+
*/
|
|
761
|
+
function getTradingDate(time) {
|
|
762
|
+
const date = typeof time === 'number' ? new Date(time) : typeof time === 'string' ? new Date(time) : time;
|
|
763
|
+
const nyDate = toNYTime(date);
|
|
764
|
+
return `${nyDate.getUTCFullYear()}-${String(nyDate.getUTCMonth() + 1).padStart(2, '0')}-${String(nyDate.getUTCDate()).padStart(2, '0')}`;
|
|
765
|
+
}
|
|
766
|
+
/**
|
|
767
|
+
* Returns the NY timezone offset string for a given date.
|
|
768
|
+
* @param date - Date object (default: now)
|
|
769
|
+
* @returns '-04:00' for EDT, '-05:00' for EST
|
|
770
|
+
*/
|
|
771
|
+
function getNYTimeZone(date) {
|
|
772
|
+
const offset = getNYOffset(date || new Date());
|
|
773
|
+
return offset === -4 ? '-04:00' : '-05:00';
|
|
774
|
+
}
|
|
775
|
+
/**
|
|
776
|
+
* Returns the current market status for a given date.
|
|
777
|
+
* @param options - { date?: Date }
|
|
778
|
+
* @returns MarketStatus object
|
|
779
|
+
*/
|
|
780
|
+
function getMarketStatus(options = {}) {
|
|
781
|
+
const { date = new Date() } = options;
|
|
782
|
+
return getMarketStatusImpl(date);
|
|
783
|
+
}
|
|
784
|
+
/**
|
|
785
|
+
* Checks if a date is a market day.
|
|
786
|
+
* @param date - Date object
|
|
787
|
+
* @returns true if market day, false otherwise
|
|
788
|
+
*/
|
|
789
|
+
function isMarketDay(date) {
|
|
790
|
+
const calendar = new MarketCalendar();
|
|
791
|
+
return calendar.isMarketDay(date);
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Returns full trading days from market open to market close.
|
|
795
|
+
* endDate is always the most recent market close (previous day's close if before open, today's close if after open).
|
|
796
|
+
* days: 1 or not specified = that day's open; 2 = previous market day's open, etc.
|
|
797
|
+
*/
|
|
798
|
+
/**
|
|
799
|
+
* Returns full trading days from market open to market close.
|
|
800
|
+
* @param options - { endDate?: Date, days?: number }
|
|
801
|
+
* @returns Object with startDate and endDate
|
|
802
|
+
*/
|
|
803
|
+
function getTradingStartAndEndDates(options = {}) {
|
|
804
|
+
const { endDate = new Date(), days = 1 } = options;
|
|
805
|
+
const calendar = new MarketCalendar();
|
|
806
|
+
// Find the most recent market close
|
|
807
|
+
let endMarketDay = endDate;
|
|
808
|
+
const nyEnd = toNYTime(endDate);
|
|
809
|
+
const marketOpenMinutes = MARKET_CONFIG.TIMES.MARKET_OPEN.hour * 60 + MARKET_CONFIG.TIMES.MARKET_OPEN.minute;
|
|
810
|
+
const marketCloseMinutes = MARKET_CONFIG.TIMES.MARKET_CLOSE.hour * 60 + MARKET_CONFIG.TIMES.MARKET_CLOSE.minute;
|
|
811
|
+
const minutes = nyEnd.getUTCHours() * 60 + nyEnd.getUTCMinutes();
|
|
812
|
+
if (!calendar.isMarketDay(endDate) ||
|
|
813
|
+
minutes < marketOpenMinutes ||
|
|
814
|
+
(minutes >= marketOpenMinutes && minutes < marketCloseMinutes)) {
|
|
815
|
+
// Before market open, not a market day, or during market hours: use previous market day
|
|
816
|
+
endMarketDay = calendar.getPreviousMarketDay(endDate);
|
|
817
|
+
}
|
|
818
|
+
else {
|
|
819
|
+
// After market close: use today
|
|
820
|
+
endMarketDay = endDate;
|
|
821
|
+
}
|
|
822
|
+
// Get market close for endMarketDay
|
|
823
|
+
const endClose = getMarketOpenClose({ date: endMarketDay }).close;
|
|
824
|
+
// Find start market day by iterating back over market days
|
|
825
|
+
let startMarketDay = endMarketDay;
|
|
826
|
+
let count = Math.max(1, days);
|
|
827
|
+
for (let i = 1; i < count; i++) {
|
|
828
|
+
startMarketDay = calendar.getPreviousMarketDay(startMarketDay);
|
|
829
|
+
}
|
|
830
|
+
// If days > 1, we need to go back (days-1) market days from endMarketDay
|
|
831
|
+
if (days > 1) {
|
|
832
|
+
startMarketDay = endMarketDay;
|
|
833
|
+
for (let i = 1; i < days; i++) {
|
|
834
|
+
startMarketDay = calendar.getPreviousMarketDay(startMarketDay);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
const startOpen = getMarketOpenClose({ date: startMarketDay }).open;
|
|
838
|
+
return { startDate: startOpen, endDate: endClose };
|
|
839
|
+
}
|
|
840
|
+
/**
|
|
841
|
+
* Counts trading time between two dates (passed as standard Date objects), excluding weekends and holidays, and closed market hours, using other functions in this library.
|
|
842
|
+
*
|
|
843
|
+
* This function calculates the actual trading time between two dates by:
|
|
844
|
+
* 1. Iterating through each calendar day between startDate and endDate (inclusive)
|
|
845
|
+
* 2. For each day that is a market day (not weekend/holiday), getting market open/close times
|
|
846
|
+
* 3. Calculating the overlap between the time range and market hours for that day
|
|
847
|
+
* 4. Summing up all the trading minutes across all days
|
|
848
|
+
*
|
|
849
|
+
* The function automatically handles:
|
|
850
|
+
* - Weekends (Saturday/Sunday) - skipped entirely
|
|
851
|
+
* - Market holidays - skipped entirely
|
|
852
|
+
* - Early close days (e.g. day before holidays) - uses early close time
|
|
853
|
+
* - Times outside market hours - only counts time within 9:30am-4pm ET (or early close)
|
|
854
|
+
*
|
|
855
|
+
* Examples:
|
|
856
|
+
* - 12pm to 3:30pm same day = 3.5 hours = 210 minutes = 0.54 days
|
|
857
|
+
* - 9:30am to 4pm same day = 6.5 hours = 390 minutes = 1 day
|
|
858
|
+
* - Friday 2pm to Monday 2pm = 6.5 hours (Friday 2pm-4pm + Monday 9:30am-2pm)
|
|
859
|
+
*
|
|
860
|
+
* @param startDate - Start date/time
|
|
861
|
+
* @param endDate - End date/time (default: now)
|
|
862
|
+
* @returns Object containing:
|
|
863
|
+
* - days: Trading time as fraction of full trading days (6.5 hours = 1 day)
|
|
864
|
+
* - hours: Trading time in hours
|
|
865
|
+
* - minutes: Trading time in minutes
|
|
866
|
+
*/
|
|
867
|
+
function countTradingDays(startDate, endDate = new Date()) {
|
|
868
|
+
const calendar = new MarketCalendar();
|
|
869
|
+
// Ensure start is before end
|
|
870
|
+
if (startDate.getTime() > endDate.getTime()) {
|
|
871
|
+
throw new Error('Start date must be before end date');
|
|
872
|
+
}
|
|
873
|
+
let totalMinutes = 0;
|
|
874
|
+
// Get the NY dates for iteration
|
|
875
|
+
const startNY = toNYTime(startDate);
|
|
876
|
+
const endNY = toNYTime(endDate);
|
|
877
|
+
// Create date at start of first day (in NY time)
|
|
878
|
+
const currentNY = new Date(Date.UTC(startNY.getUTCFullYear(), startNY.getUTCMonth(), startNY.getUTCDate(), 0, 0, 0, 0));
|
|
879
|
+
// Iterate through each calendar day
|
|
880
|
+
while (currentNY.getTime() <= endNY.getTime()) {
|
|
881
|
+
const currentUTC = fromNYTime(currentNY);
|
|
882
|
+
// Check if this is a market day
|
|
883
|
+
if (calendar.isMarketDay(currentUTC)) {
|
|
884
|
+
// Get market hours for this day
|
|
885
|
+
const marketTimes = getMarketTimes(currentUTC);
|
|
886
|
+
if (marketTimes.marketOpen && marketTimes.open && marketTimes.close) {
|
|
887
|
+
// Calculate the overlap between our time range and market hours
|
|
888
|
+
const dayStart = Math.max(startDate.getTime(), marketTimes.open.getTime());
|
|
889
|
+
const dayEnd = Math.min(endDate.getTime(), marketTimes.close.getTime());
|
|
890
|
+
// Only count if there's actual overlap
|
|
891
|
+
if (dayStart < dayEnd) {
|
|
892
|
+
totalMinutes += (dayEnd - dayStart) / (1000 * 60);
|
|
893
|
+
}
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
// Move to next day
|
|
897
|
+
currentNY.setUTCDate(currentNY.getUTCDate() + 1);
|
|
898
|
+
}
|
|
899
|
+
// Convert to days, hours, minutes
|
|
900
|
+
const MINUTES_PER_TRADING_DAY = 390; // 6.5 hours
|
|
901
|
+
const days = totalMinutes / MINUTES_PER_TRADING_DAY;
|
|
902
|
+
const hours = totalMinutes / 60;
|
|
903
|
+
const minutes = totalMinutes;
|
|
904
|
+
return {
|
|
905
|
+
days: Math.round(days * 1000) / 1000, // Round to 3 decimal places
|
|
906
|
+
hours: Math.round(hours * 100) / 100, // Round to 2 decimal places
|
|
907
|
+
minutes: Math.round(minutes),
|
|
908
|
+
};
|
|
909
|
+
}
|
|
910
|
+
// Export MARKET_TIMES for compatibility
|
|
911
|
+
const MARKET_TIMES = {
|
|
912
|
+
TIMEZONE: MARKET_CONFIG.TIMEZONE,
|
|
913
|
+
PRE: {
|
|
914
|
+
START: { HOUR: 4, MINUTE: 0, MINUTES: 240 },
|
|
915
|
+
END: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
916
|
+
},
|
|
917
|
+
EARLY_MORNING: {
|
|
918
|
+
START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
919
|
+
END: { HOUR: 10, MINUTE: 0, MINUTES: 600 },
|
|
920
|
+
},
|
|
921
|
+
EARLY_CLOSE_BEFORE_HOLIDAY: {
|
|
922
|
+
START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
923
|
+
END: { HOUR: 13, MINUTE: 0, MINUTES: 780 },
|
|
924
|
+
},
|
|
925
|
+
EARLY_EXTENDED_BEFORE_HOLIDAY: {
|
|
926
|
+
START: { HOUR: 13, MINUTE: 0, MINUTES: 780 },
|
|
927
|
+
END: { HOUR: 17, MINUTE: 0, MINUTES: 1020 },
|
|
928
|
+
},
|
|
929
|
+
REGULAR: {
|
|
930
|
+
START: { HOUR: 9, MINUTE: 30, MINUTES: 570 },
|
|
931
|
+
END: { HOUR: 16, MINUTE: 0, MINUTES: 960 },
|
|
932
|
+
},
|
|
933
|
+
EXTENDED: {
|
|
934
|
+
START: { HOUR: 4, MINUTE: 0, MINUTES: 240 },
|
|
935
|
+
END: { HOUR: 20, MINUTE: 0, MINUTES: 1200 },
|
|
936
|
+
},
|
|
937
|
+
};
|
|
367
938
|
|
|
368
939
|
/*
|
|
369
940
|
How it works:
|
|
@@ -533,7 +1104,7 @@ function pLimit(concurrency) {
|
|
|
533
1104
|
},
|
|
534
1105
|
map: {
|
|
535
1106
|
async value(array, function_) {
|
|
536
|
-
const promises = array.map(value => this(function_, value));
|
|
1107
|
+
const promises = array.map((value, index) => this(function_, value, index));
|
|
537
1108
|
return Promise.all(promises);
|
|
538
1109
|
},
|
|
539
1110
|
},
|
|
@@ -799,7 +1370,7 @@ const safeJSON = (text) => {
|
|
|
799
1370
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
800
1371
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
801
1372
|
|
|
802
|
-
const VERSION = '5.
|
|
1373
|
+
const VERSION = '5.16.0'; // x-release-please-version
|
|
803
1374
|
|
|
804
1375
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
805
1376
|
const isRunningInBrowser = () => {
|
|
@@ -2139,6 +2710,36 @@ class CursorPage extends AbstractPage {
|
|
|
2139
2710
|
};
|
|
2140
2711
|
}
|
|
2141
2712
|
}
|
|
2713
|
+
class ConversationCursorPage extends AbstractPage {
|
|
2714
|
+
constructor(client, response, body, options) {
|
|
2715
|
+
super(client, response, body, options);
|
|
2716
|
+
this.data = body.data || [];
|
|
2717
|
+
this.has_more = body.has_more || false;
|
|
2718
|
+
this.last_id = body.last_id || '';
|
|
2719
|
+
}
|
|
2720
|
+
getPaginatedItems() {
|
|
2721
|
+
return this.data ?? [];
|
|
2722
|
+
}
|
|
2723
|
+
hasNextPage() {
|
|
2724
|
+
if (this.has_more === false) {
|
|
2725
|
+
return false;
|
|
2726
|
+
}
|
|
2727
|
+
return super.hasNextPage();
|
|
2728
|
+
}
|
|
2729
|
+
nextPageRequestOptions() {
|
|
2730
|
+
const cursor = this.last_id;
|
|
2731
|
+
if (!cursor) {
|
|
2732
|
+
return null;
|
|
2733
|
+
}
|
|
2734
|
+
return {
|
|
2735
|
+
...this.options,
|
|
2736
|
+
query: {
|
|
2737
|
+
...maybeObj(this.options.query),
|
|
2738
|
+
after: cursor,
|
|
2739
|
+
},
|
|
2740
|
+
};
|
|
2741
|
+
}
|
|
2742
|
+
}
|
|
2142
2743
|
|
|
2143
2744
|
const checkFileSupport = () => {
|
|
2144
2745
|
if (typeof File === 'undefined') {
|
|
@@ -5229,6 +5830,74 @@ class Containers extends APIResource {
|
|
|
5229
5830
|
}
|
|
5230
5831
|
Containers.Files = Files$2;
|
|
5231
5832
|
|
|
5833
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
5834
|
+
class Items extends APIResource {
|
|
5835
|
+
/**
|
|
5836
|
+
* Create items in a conversation with the given ID.
|
|
5837
|
+
*/
|
|
5838
|
+
create(conversationID, params, options) {
|
|
5839
|
+
const { include, ...body } = params;
|
|
5840
|
+
return this._client.post(path `/conversations/${conversationID}/items`, {
|
|
5841
|
+
query: { include },
|
|
5842
|
+
body,
|
|
5843
|
+
...options,
|
|
5844
|
+
});
|
|
5845
|
+
}
|
|
5846
|
+
/**
|
|
5847
|
+
* Get a single item from a conversation with the given IDs.
|
|
5848
|
+
*/
|
|
5849
|
+
retrieve(itemID, params, options) {
|
|
5850
|
+
const { conversation_id, ...query } = params;
|
|
5851
|
+
return this._client.get(path `/conversations/${conversation_id}/items/${itemID}`, { query, ...options });
|
|
5852
|
+
}
|
|
5853
|
+
/**
|
|
5854
|
+
* List all items for a conversation with the given ID.
|
|
5855
|
+
*/
|
|
5856
|
+
list(conversationID, query = {}, options) {
|
|
5857
|
+
return this._client.getAPIList(path `/conversations/${conversationID}/items`, (ConversationCursorPage), { query, ...options });
|
|
5858
|
+
}
|
|
5859
|
+
/**
|
|
5860
|
+
* Delete an item from a conversation with the given IDs.
|
|
5861
|
+
*/
|
|
5862
|
+
delete(itemID, params, options) {
|
|
5863
|
+
const { conversation_id } = params;
|
|
5864
|
+
return this._client.delete(path `/conversations/${conversation_id}/items/${itemID}`, options);
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
|
|
5868
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
5869
|
+
class Conversations extends APIResource {
|
|
5870
|
+
constructor() {
|
|
5871
|
+
super(...arguments);
|
|
5872
|
+
this.items = new Items(this._client);
|
|
5873
|
+
}
|
|
5874
|
+
/**
|
|
5875
|
+
* Create a conversation.
|
|
5876
|
+
*/
|
|
5877
|
+
create(body, options) {
|
|
5878
|
+
return this._client.post('/conversations', { body, ...options });
|
|
5879
|
+
}
|
|
5880
|
+
/**
|
|
5881
|
+
* Get a conversation with the given ID.
|
|
5882
|
+
*/
|
|
5883
|
+
retrieve(conversationID, options) {
|
|
5884
|
+
return this._client.get(path `/conversations/${conversationID}`, options);
|
|
5885
|
+
}
|
|
5886
|
+
/**
|
|
5887
|
+
* Update a conversation's metadata with the given ID.
|
|
5888
|
+
*/
|
|
5889
|
+
update(conversationID, body, options) {
|
|
5890
|
+
return this._client.post(path `/conversations/${conversationID}`, { body, ...options });
|
|
5891
|
+
}
|
|
5892
|
+
/**
|
|
5893
|
+
* Delete a conversation with the given ID.
|
|
5894
|
+
*/
|
|
5895
|
+
delete(conversationID, options) {
|
|
5896
|
+
return this._client.delete(path `/conversations/${conversationID}`, options);
|
|
5897
|
+
}
|
|
5898
|
+
}
|
|
5899
|
+
Conversations.Items = Items;
|
|
5900
|
+
|
|
5232
5901
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
5233
5902
|
class Embeddings extends APIResource {
|
|
5234
5903
|
/**
|
|
@@ -5393,7 +6062,7 @@ let Files$1 = class Files extends APIResource {
|
|
|
5393
6062
|
/**
|
|
5394
6063
|
* Upload a file that can be used across various endpoints. Individual files can be
|
|
5395
6064
|
* up to 512 MB, and the size of all files uploaded by one organization can be up
|
|
5396
|
-
* to
|
|
6065
|
+
* to 1 TB.
|
|
5397
6066
|
*
|
|
5398
6067
|
* The Assistants API supports files up to 2 million tokens and of specific file
|
|
5399
6068
|
* types. See the
|
|
@@ -6822,6 +7491,7 @@ class OpenAI {
|
|
|
6822
7491
|
this.batches = new Batches(this);
|
|
6823
7492
|
this.uploads = new Uploads(this);
|
|
6824
7493
|
this.responses = new Responses(this);
|
|
7494
|
+
this.conversations = new Conversations(this);
|
|
6825
7495
|
this.evals = new Evals(this);
|
|
6826
7496
|
this.containers = new Containers(this);
|
|
6827
7497
|
if (apiKey === undefined) {
|
|
@@ -7212,7 +7882,7 @@ class OpenAI {
|
|
|
7212
7882
|
// Preserve legacy string encoding behavior for now
|
|
7213
7883
|
headers.values.has('content-type')) ||
|
|
7214
7884
|
// `Blob` is superset of `File`
|
|
7215
|
-
body instanceof Blob ||
|
|
7885
|
+
(globalThis.Blob && body instanceof globalThis.Blob) ||
|
|
7216
7886
|
// `FormData` -> `multipart/form-data`
|
|
7217
7887
|
body instanceof FormData ||
|
|
7218
7888
|
// `URLSearchParams` -> `application/x-www-form-urlencoded`
|
|
@@ -7267,6 +7937,7 @@ OpenAI.Beta = Beta;
|
|
|
7267
7937
|
OpenAI.Batches = Batches;
|
|
7268
7938
|
OpenAI.Uploads = Uploads;
|
|
7269
7939
|
OpenAI.Responses = Responses;
|
|
7940
|
+
OpenAI.Conversations = Conversations;
|
|
7270
7941
|
OpenAI.Evals = Evals;
|
|
7271
7942
|
OpenAI.Containers = Containers;
|
|
7272
7943
|
|
|
@@ -13675,87 +14346,124 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13675
14346
|
}
|
|
13676
14347
|
}
|
|
13677
14348
|
// Export the singleton instance
|
|
13678
|
-
|
|
14349
|
+
AlpacaMarketDataAPI.getInstance();
|
|
14350
|
+
|
|
14351
|
+
const disco = {
|
|
14352
|
+
time: {
|
|
14353
|
+
getStartAndEndDates: getStartAndEndDates,
|
|
14354
|
+
getMarketOpenClose: getMarketOpenClose,
|
|
14355
|
+
getLastFullTradingDate: getLastFullTradingDate,
|
|
14356
|
+
getNextMarketDay: getNextMarketDay,
|
|
14357
|
+
getPreviousMarketDay: getPreviousMarketDay,
|
|
14358
|
+
getMarketTimePeriod: getMarketTimePeriod,
|
|
14359
|
+
getMarketStatus: getMarketStatus,
|
|
14360
|
+
getNYTimeZone: getNYTimeZone,
|
|
14361
|
+
getTradingDate: getTradingDate,
|
|
14362
|
+
getTradingStartAndEndDates: getTradingStartAndEndDates,
|
|
14363
|
+
isMarketDay: isMarketDay,
|
|
14364
|
+
isWithinMarketHours: isWithinMarketHours,
|
|
14365
|
+
countTradingDays: countTradingDays,
|
|
14366
|
+
MARKET_TIMES: MARKET_TIMES,
|
|
14367
|
+
}};
|
|
13679
14368
|
|
|
13680
14369
|
// Test file for context functionality
|
|
13681
|
-
|
|
13682
|
-
|
|
13683
|
-
const
|
|
13684
|
-
|
|
13685
|
-
|
|
13686
|
-
|
|
13687
|
-
|
|
13688
|
-
|
|
13689
|
-
|
|
13690
|
-
|
|
13691
|
-
|
|
13692
|
-
|
|
13693
|
-
|
|
13694
|
-
|
|
13695
|
-
|
|
13696
|
-
|
|
13697
|
-
|
|
13698
|
-
|
|
13699
|
-
|
|
13700
|
-
|
|
13701
|
-
|
|
13702
|
-
|
|
13703
|
-
|
|
13704
|
-
|
|
13705
|
-
|
|
13706
|
-
|
|
13707
|
-
|
|
13708
|
-
|
|
13709
|
-
|
|
13710
|
-
|
|
13711
|
-
|
|
13712
|
-
|
|
13713
|
-
|
|
13714
|
-
|
|
13715
|
-
|
|
13716
|
-
|
|
13717
|
-
|
|
13718
|
-
|
|
13719
|
-
|
|
13720
|
-
|
|
13721
|
-
|
|
13722
|
-
|
|
13723
|
-
|
|
13724
|
-
|
|
13725
|
-
|
|
13726
|
-
|
|
13727
|
-
|
|
13728
|
-
|
|
13729
|
-
|
|
13730
|
-
|
|
13731
|
-
|
|
13732
|
-
|
|
13733
|
-
|
|
13734
|
-
|
|
13735
|
-
|
|
13736
|
-
|
|
13737
|
-
|
|
13738
|
-
|
|
13739
|
-
|
|
13740
|
-
|
|
13741
|
-
|
|
13742
|
-
|
|
13743
|
-
|
|
13744
|
-
|
|
13745
|
-
|
|
13746
|
-
|
|
13747
|
-
|
|
13748
|
-
|
|
13749
|
-
|
|
13750
|
-
|
|
13751
|
-
|
|
13752
|
-
|
|
13753
|
-
|
|
13754
|
-
|
|
13755
|
-
|
|
13756
|
-
}
|
|
13757
|
-
|
|
14370
|
+
// Test getMarketStatus with various scenarios
|
|
14371
|
+
function testGetMarketStatus() {
|
|
14372
|
+
const testCases = [
|
|
14373
|
+
{
|
|
14374
|
+
label: 'Weekend (Saturday, market closed)',
|
|
14375
|
+
date: '2025-07-12T12:00:00-04:00',
|
|
14376
|
+
expected: {
|
|
14377
|
+
status: 'closed',
|
|
14378
|
+
nextStatus: 'extended hours',
|
|
14379
|
+
marketPeriod: 'closed',
|
|
14380
|
+
},
|
|
14381
|
+
},
|
|
14382
|
+
// do before preMarket
|
|
14383
|
+
{
|
|
14384
|
+
label: 'Before pre-market (market closed)',
|
|
14385
|
+
date: '2025-07-10T03:00:00-04:00',
|
|
14386
|
+
expected: {
|
|
14387
|
+
status: 'closed',
|
|
14388
|
+
nextStatus: 'extended hours',
|
|
14389
|
+
marketPeriod: 'closed',
|
|
14390
|
+
},
|
|
14391
|
+
},
|
|
14392
|
+
{
|
|
14393
|
+
label: 'Pre-market (before open)',
|
|
14394
|
+
date: '2025-07-10T08:00:00-04:00', // 8am EDT
|
|
14395
|
+
expected: {
|
|
14396
|
+
status: 'extended hours',
|
|
14397
|
+
nextStatus: 'open',
|
|
14398
|
+
marketPeriod: 'preMarket',
|
|
14399
|
+
},
|
|
14400
|
+
},
|
|
14401
|
+
{
|
|
14402
|
+
label: 'Extended hours (pre-market)',
|
|
14403
|
+
date: '2025-07-10T05:00:00-04:00',
|
|
14404
|
+
expected: {
|
|
14405
|
+
status: 'extended hours',
|
|
14406
|
+
nextStatus: 'open',
|
|
14407
|
+
marketPeriod: 'preMarket',
|
|
14408
|
+
},
|
|
14409
|
+
},
|
|
14410
|
+
{
|
|
14411
|
+
label: 'Market open (regular)',
|
|
14412
|
+
date: '2025-07-10T10:00:00-04:00',
|
|
14413
|
+
expected: {
|
|
14414
|
+
status: 'open',
|
|
14415
|
+
nextStatus: 'extended hours',
|
|
14416
|
+
marketPeriod: 'regularMarket',
|
|
14417
|
+
},
|
|
14418
|
+
},
|
|
14419
|
+
{
|
|
14420
|
+
label: 'Market open (early market)',
|
|
14421
|
+
date: '2025-07-03T09:45:00-04:00', // Early close day
|
|
14422
|
+
expected: {
|
|
14423
|
+
status: 'open',
|
|
14424
|
+
nextStatus: 'extended hours',
|
|
14425
|
+
marketPeriod: 'earlyMarket',
|
|
14426
|
+
},
|
|
14427
|
+
},
|
|
14428
|
+
{
|
|
14429
|
+
label: 'After market close (extended hours)',
|
|
14430
|
+
date: '2025-07-10T17:00:00-04:00',
|
|
14431
|
+
expected: {
|
|
14432
|
+
status: 'extended hours',
|
|
14433
|
+
nextStatus: 'closed',
|
|
14434
|
+
marketPeriod: 'afterMarket',
|
|
14435
|
+
},
|
|
14436
|
+
},
|
|
14437
|
+
{
|
|
14438
|
+
label: 'After extended hours (market closed)',
|
|
14439
|
+
date: '2025-07-10T21:00:00-04:00',
|
|
14440
|
+
expected: {
|
|
14441
|
+
status: 'closed',
|
|
14442
|
+
nextStatus: 'extended hours',
|
|
14443
|
+
marketPeriod: 'closed',
|
|
14444
|
+
},
|
|
14445
|
+
},
|
|
14446
|
+
];
|
|
14447
|
+
for (const { label, date, expected } of testCases) {
|
|
14448
|
+
const result = disco.time.getMarketStatus({ date: new Date(date) });
|
|
14449
|
+
const pass = result.status === expected.status &&
|
|
14450
|
+
result.nextStatus === expected.nextStatus &&
|
|
14451
|
+
result.marketPeriod === expected.marketPeriod;
|
|
14452
|
+
console.log(`\nTest: ${label}`);
|
|
14453
|
+
console.log(` Input date: ${date}`);
|
|
14454
|
+
console.log(` Status: ${result.status} ${pass ? '✓' : `✗ (expected ${expected.status})`}`);
|
|
14455
|
+
console.log(` NextStatus: ${result.nextStatus} ${pass ? '✓' : `✗ (expected ${expected.nextStatus})`}`);
|
|
14456
|
+
console.log(` MarketPeriod: ${result.marketPeriod} ${pass ? '✓' : `✗ (expected ${expected.marketPeriod})`}`);
|
|
14457
|
+
const nextStatusTimeDifferenceMs = result.nextStatusTimeDifference;
|
|
14458
|
+
// convert that to a string in the form 'xxh xxm'
|
|
14459
|
+
const nextStatusTimeDifferenceStr = `${Math.floor(nextStatusTimeDifferenceMs / (1000 * 60 * 60))}h ${Math.floor((nextStatusTimeDifferenceMs % (1000 * 60 * 60)) / (1000 * 60))}m`;
|
|
14460
|
+
console.log(` Next market status: ${result.nextStatus} at ${result.nextStatusTime.toLocaleString('en-US', { timeZone: 'America/New_York' })} in ${nextStatusTimeDifferenceStr}`);
|
|
14461
|
+
if (!pass) {
|
|
14462
|
+
console.error(` FAILED: Expected status=${expected.status}, nextStatus=${expected.nextStatus}, marketPeriod=${expected.marketPeriod}, got status=${result.status}, nextStatus=${result.nextStatus}, marketPeriod=${result.marketPeriod}`);
|
|
14463
|
+
}
|
|
14464
|
+
}
|
|
14465
|
+
}
|
|
14466
|
+
//testGetPortfolioDailyHistory();
|
|
13758
14467
|
//testOpenRouter();
|
|
13759
|
-
|
|
13760
|
-
export { WebSocket as W, log$1 as l, marketDataAPI as m };
|
|
14468
|
+
testGetMarketStatus();
|
|
13761
14469
|
//# sourceMappingURL=test.js.map
|