@discomedia/utils 1.0.42 → 1.0.44
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 +31 -15
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +31 -15
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +44 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +44 -28
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +4 -4
- package/dist/test.js +342 -64
- package/dist/test.js.map +1 -1
- package/dist/types/types/alpaca-types.d.ts +1 -1
- package/dist/types/types/alpaca-types.d.ts.map +1 -1
- package/dist/types-frontend/types/alpaca-types.d.ts +1 -1
- package/dist/types-frontend/types/alpaca-types.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.0.
|
|
6
|
+
"version": "1.0.44",
|
|
7
7
|
"author": "Disco Media",
|
|
8
8
|
"description": "Utility functions used in Disco Media apps",
|
|
9
9
|
"always-build-npm": true,
|
|
@@ -33,17 +33,17 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"dotenv": "^17.2.3",
|
|
36
|
-
"openai": "^6.
|
|
36
|
+
"openai": "^6.7.0",
|
|
37
37
|
"p-limit": "^7.2.0",
|
|
38
38
|
"tslib": "^2.8.1",
|
|
39
39
|
"ws": "^8.18.3"
|
|
40
40
|
},
|
|
41
41
|
"license": "ISC",
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@rollup/plugin-commonjs": "^28.0.
|
|
43
|
+
"@rollup/plugin-commonjs": "^28.0.9",
|
|
44
44
|
"@rollup/plugin-json": "^6.1.0",
|
|
45
45
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
46
|
-
"@rollup/plugin-typescript": "^12.
|
|
46
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
47
47
|
"@types/ws": "^8.18.1",
|
|
48
48
|
"lightweight-charts": "^5.0.9",
|
|
49
49
|
"rollup": "^4.52.5",
|
package/dist/test.js
CHANGED
|
@@ -799,7 +799,7 @@ const safeJSON = (text) => {
|
|
|
799
799
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
800
800
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
801
801
|
|
|
802
|
-
const VERSION = '6.
|
|
802
|
+
const VERSION = '6.7.0'; // x-release-please-version
|
|
803
803
|
|
|
804
804
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
805
805
|
const isRunningInBrowser = () => {
|
|
@@ -5641,20 +5641,19 @@ let Files$1 = class Files extends APIResource {
|
|
|
5641
5641
|
* up to 512 MB, and the size of all files uploaded by one organization can be up
|
|
5642
5642
|
* to 1 TB.
|
|
5643
5643
|
*
|
|
5644
|
-
* The Assistants API supports files up to 2 million tokens and of specific file
|
|
5645
|
-
*
|
|
5646
|
-
*
|
|
5647
|
-
* details.
|
|
5648
|
-
*
|
|
5649
|
-
*
|
|
5650
|
-
*
|
|
5651
|
-
*
|
|
5652
|
-
*
|
|
5653
|
-
*
|
|
5654
|
-
*
|
|
5655
|
-
*
|
|
5656
|
-
*
|
|
5657
|
-
* [format](https://platform.openai.com/docs/api-reference/batch/request-input).
|
|
5644
|
+
* - The Assistants API supports files up to 2 million tokens and of specific file
|
|
5645
|
+
* types. See the
|
|
5646
|
+
* [Assistants Tools guide](https://platform.openai.com/docs/assistants/tools)
|
|
5647
|
+
* for details.
|
|
5648
|
+
* - The Fine-tuning API only supports `.jsonl` files. The input also has certain
|
|
5649
|
+
* required formats for fine-tuning
|
|
5650
|
+
* [chat](https://platform.openai.com/docs/api-reference/fine-tuning/chat-input)
|
|
5651
|
+
* or
|
|
5652
|
+
* [completions](https://platform.openai.com/docs/api-reference/fine-tuning/completions-input)
|
|
5653
|
+
* models.
|
|
5654
|
+
* - The Batch API only supports `.jsonl` files up to 200 MB in size. The input
|
|
5655
|
+
* also has a specific required
|
|
5656
|
+
* [format](https://platform.openai.com/docs/api-reference/batch/request-input).
|
|
5658
5657
|
*
|
|
5659
5658
|
* Please [contact us](https://help.openai.com/) if you need to increase these
|
|
5660
5659
|
* storage limits.
|
|
@@ -6557,11 +6556,27 @@ class InputItems extends APIResource {
|
|
|
6557
6556
|
}
|
|
6558
6557
|
}
|
|
6559
6558
|
|
|
6559
|
+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6560
|
+
class InputTokens extends APIResource {
|
|
6561
|
+
/**
|
|
6562
|
+
* Get input token counts
|
|
6563
|
+
*
|
|
6564
|
+
* @example
|
|
6565
|
+
* ```ts
|
|
6566
|
+
* const response = await client.responses.inputTokens.count();
|
|
6567
|
+
* ```
|
|
6568
|
+
*/
|
|
6569
|
+
count(body = {}, options) {
|
|
6570
|
+
return this._client.post('/responses/input_tokens', { body, ...options });
|
|
6571
|
+
}
|
|
6572
|
+
}
|
|
6573
|
+
|
|
6560
6574
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6561
6575
|
class Responses extends APIResource {
|
|
6562
6576
|
constructor() {
|
|
6563
6577
|
super(...arguments);
|
|
6564
6578
|
this.inputItems = new InputItems(this._client);
|
|
6579
|
+
this.inputTokens = new InputTokens(this._client);
|
|
6565
6580
|
}
|
|
6566
6581
|
create(body, options) {
|
|
6567
6582
|
return this._client.post('/responses', { body, ...options, stream: body.stream ?? false })._thenUnwrap((rsp) => {
|
|
@@ -6627,6 +6642,7 @@ class Responses extends APIResource {
|
|
|
6627
6642
|
}
|
|
6628
6643
|
}
|
|
6629
6644
|
Responses.InputItems = InputItems;
|
|
6645
|
+
Responses.InputTokens = InputTokens;
|
|
6630
6646
|
|
|
6631
6647
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
6632
6648
|
class Parts extends APIResource {
|
|
@@ -13458,7 +13474,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13458
13474
|
*/
|
|
13459
13475
|
async getHistoricalBars(params) {
|
|
13460
13476
|
const symbols = params.symbols;
|
|
13461
|
-
|
|
13477
|
+
symbols.join(',');
|
|
13462
13478
|
let allBars = {};
|
|
13463
13479
|
let pageToken = null;
|
|
13464
13480
|
let hasMorePages = true;
|
|
@@ -13469,7 +13485,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13469
13485
|
symbols.forEach((symbol) => {
|
|
13470
13486
|
allBars[symbol] = [];
|
|
13471
13487
|
});
|
|
13472
|
-
log(`Starting historical bars fetch for ${
|
|
13488
|
+
log(`Starting historical bars fetch for ${symbols.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`);
|
|
13473
13489
|
while (hasMorePages) {
|
|
13474
13490
|
pageCount++;
|
|
13475
13491
|
const requestParams = {
|
|
@@ -13480,7 +13496,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13480
13496
|
};
|
|
13481
13497
|
const response = await this.makeRequest('/stocks/bars', 'GET', requestParams);
|
|
13482
13498
|
if (!response.bars) {
|
|
13483
|
-
log(`No bars data found in response for ${
|
|
13499
|
+
log(`No bars data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
13484
13500
|
break;
|
|
13485
13501
|
}
|
|
13486
13502
|
// Track currency from first response
|
|
@@ -13522,10 +13538,10 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13522
13538
|
}
|
|
13523
13539
|
}
|
|
13524
13540
|
// Final summary
|
|
13525
|
-
const
|
|
13541
|
+
const symbolCounts = Object.entries(allBars)
|
|
13526
13542
|
.map(([symbol, bars]) => `${symbol}: ${bars.length}`)
|
|
13527
13543
|
.join(', ');
|
|
13528
|
-
log(`Bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages for ${
|
|
13544
|
+
log(`Bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages for ${symbols.length} symbols (${symbolCounts})`);
|
|
13529
13545
|
return {
|
|
13530
13546
|
bars: allBars,
|
|
13531
13547
|
next_page_token: null, // Always null since we fetch all pages
|
|
@@ -13796,7 +13812,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13796
13812
|
*/
|
|
13797
13813
|
async getHistoricalOptionsBars(params) {
|
|
13798
13814
|
const symbols = params.symbols;
|
|
13799
|
-
|
|
13815
|
+
symbols.join(',');
|
|
13800
13816
|
let allBars = {};
|
|
13801
13817
|
let pageToken = null;
|
|
13802
13818
|
let hasMorePages = true;
|
|
@@ -13806,7 +13822,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13806
13822
|
symbols.forEach((symbol) => {
|
|
13807
13823
|
allBars[symbol] = [];
|
|
13808
13824
|
});
|
|
13809
|
-
log(`Starting historical options bars fetch for ${
|
|
13825
|
+
log(`Starting historical options bars fetch for ${symbols.length} symbols (${params.timeframe}, ${params.start || 'no start'} to ${params.end || 'no end'})`);
|
|
13810
13826
|
while (hasMorePages) {
|
|
13811
13827
|
pageCount++;
|
|
13812
13828
|
const requestParams = {
|
|
@@ -13815,7 +13831,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13815
13831
|
};
|
|
13816
13832
|
const response = await this.makeRequest('/options/bars', 'GET', requestParams, 'v1beta1');
|
|
13817
13833
|
if (!response.bars) {
|
|
13818
|
-
log(`No options bars data found in response for ${
|
|
13834
|
+
log(`No options bars data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
13819
13835
|
break;
|
|
13820
13836
|
}
|
|
13821
13837
|
// Combine bars for each symbol
|
|
@@ -13845,7 +13861,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13845
13861
|
const dateRangeStr = earliestTimestamp && latestTimestamp
|
|
13846
13862
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
13847
13863
|
: 'unknown range';
|
|
13848
|
-
log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} option bars (total: ${totalBarsCount.toLocaleString()}) for ${
|
|
13864
|
+
log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} option bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
|
|
13849
13865
|
type: 'debug',
|
|
13850
13866
|
});
|
|
13851
13867
|
// Prevent infinite loops
|
|
@@ -13874,7 +13890,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13874
13890
|
*/
|
|
13875
13891
|
async getHistoricalOptionsTrades(params) {
|
|
13876
13892
|
const symbols = params.symbols;
|
|
13877
|
-
|
|
13893
|
+
symbols.join(',');
|
|
13878
13894
|
let allTrades = {};
|
|
13879
13895
|
let pageToken = null;
|
|
13880
13896
|
let hasMorePages = true;
|
|
@@ -13884,7 +13900,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13884
13900
|
symbols.forEach((symbol) => {
|
|
13885
13901
|
allTrades[symbol] = [];
|
|
13886
13902
|
});
|
|
13887
|
-
log(`Starting historical options trades fetch for ${
|
|
13903
|
+
log(`Starting historical options trades fetch for ${symbols.length} symbols (${params.start || 'no start'} to ${params.end || 'no end'})`);
|
|
13888
13904
|
while (hasMorePages) {
|
|
13889
13905
|
pageCount++;
|
|
13890
13906
|
const requestParams = {
|
|
@@ -13893,7 +13909,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13893
13909
|
};
|
|
13894
13910
|
const response = await this.makeRequest('/options/trades', 'GET', requestParams, 'v1beta1');
|
|
13895
13911
|
if (!response.trades) {
|
|
13896
|
-
log(`No options trades data found in response for ${
|
|
13912
|
+
log(`No options trades data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
13897
13913
|
break;
|
|
13898
13914
|
}
|
|
13899
13915
|
// Combine trades for each symbol
|
|
@@ -13923,7 +13939,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13923
13939
|
const dateRangeStr = earliestTimestamp && latestTimestamp
|
|
13924
13940
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
13925
13941
|
: 'unknown range';
|
|
13926
|
-
log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} option trades (total: ${totalTradesCount.toLocaleString()}) for ${
|
|
13942
|
+
log(`Page ${pageCount}: Fetched ${pageTradesCount.toLocaleString()} option trades (total: ${totalTradesCount.toLocaleString()}) for ${symbols.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, {
|
|
13927
13943
|
type: 'debug',
|
|
13928
13944
|
});
|
|
13929
13945
|
// Prevent infinite loops
|
|
@@ -14383,57 +14399,318 @@ var alpacaMarketDataApi = /*#__PURE__*/Object.freeze({
|
|
|
14383
14399
|
});
|
|
14384
14400
|
|
|
14385
14401
|
// Test file for context functionality
|
|
14386
|
-
async function
|
|
14387
|
-
console.log('\n--- Testing
|
|
14388
|
-
const log = (message, options = { type: 'info' }) => {
|
|
14389
|
-
log$1(message, { ...options, source: 'Test' });
|
|
14390
|
-
};
|
|
14402
|
+
async function testMarketDataAPI() {
|
|
14403
|
+
console.log('\n--- Testing Market Data API ---');
|
|
14391
14404
|
if (!process.env.ALPACA_API_KEY || !process.env.ALPACA_SECRET_KEY) {
|
|
14392
|
-
console.log('Skipping
|
|
14405
|
+
console.log('Skipping Market Data API tests: Missing environment variables (ALPACA_API_KEY, ALPACA_SECRET_KEY)');
|
|
14393
14406
|
return;
|
|
14394
14407
|
}
|
|
14395
14408
|
try {
|
|
14396
14409
|
const { marketDataAPI } = await Promise.resolve().then(function () { return alpacaMarketDataApi; });
|
|
14397
|
-
// 1
|
|
14398
|
-
log('
|
|
14399
|
-
|
|
14400
|
-
|
|
14401
|
-
|
|
14402
|
-
|
|
14403
|
-
|
|
14410
|
+
// Test 1: Single symbol request - verify only 1 symbol is returned
|
|
14411
|
+
console.log('\n[Test 1] Single symbol historical bars');
|
|
14412
|
+
try {
|
|
14413
|
+
const testSymbol = 'AAPL';
|
|
14414
|
+
const endDate = new Date('2023-02-28T23:59:59.999Z');
|
|
14415
|
+
const startDate = new Date('2023-02-24T00:00:00.000Z');
|
|
14416
|
+
const response = await marketDataAPI.getHistoricalBars({
|
|
14417
|
+
symbols: [testSymbol],
|
|
14418
|
+
timeframe: '1Min',
|
|
14419
|
+
start: startDate.toISOString(),
|
|
14420
|
+
end: endDate.toISOString(),
|
|
14421
|
+
});
|
|
14422
|
+
const symbolsInResponse = Object.keys(response.bars);
|
|
14423
|
+
const barsCount = response.bars[testSymbol]?.length || 0;
|
|
14424
|
+
console.log(` Requested symbols: 1 (${testSymbol})`);
|
|
14425
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14426
|
+
console.log(` Bars for ${testSymbol}: ${barsCount}`);
|
|
14427
|
+
if (symbolsInResponse.length !== 1) {
|
|
14428
|
+
console.error(` ✗ FAILED: Expected 1 symbol in response, got ${symbolsInResponse.length}`);
|
|
14429
|
+
}
|
|
14430
|
+
else if (symbolsInResponse[0] !== testSymbol) {
|
|
14431
|
+
console.error(` ✗ FAILED: Expected symbol ${testSymbol}, got ${symbolsInResponse[0]}`);
|
|
14432
|
+
}
|
|
14433
|
+
else {
|
|
14434
|
+
console.log(` ✓ Single symbol request correctly returned 1 symbol`);
|
|
14435
|
+
}
|
|
14404
14436
|
}
|
|
14405
|
-
|
|
14406
|
-
console.
|
|
14437
|
+
catch (error) {
|
|
14438
|
+
console.error(' ✗ Test 1 failed:', error);
|
|
14407
14439
|
}
|
|
14408
|
-
// 2
|
|
14409
|
-
log('
|
|
14410
|
-
|
|
14411
|
-
|
|
14412
|
-
|
|
14413
|
-
|
|
14440
|
+
// Test 2: Multiple symbols request - verify correct count
|
|
14441
|
+
console.log('\n[Test 2] Multiple symbols (3) historical bars');
|
|
14442
|
+
try {
|
|
14443
|
+
const testSymbols = ['AAPL', 'MSFT', 'GOOGL'];
|
|
14444
|
+
const endDate = new Date('2023-02-28T23:59:59.999Z');
|
|
14445
|
+
const startDate = new Date('2023-02-24T00:00:00.000Z');
|
|
14446
|
+
const response = await marketDataAPI.getHistoricalBars({
|
|
14447
|
+
symbols: testSymbols,
|
|
14448
|
+
timeframe: '1Min',
|
|
14449
|
+
start: startDate.toISOString(),
|
|
14450
|
+
end: endDate.toISOString(),
|
|
14451
|
+
});
|
|
14452
|
+
const symbolsInResponse = Object.keys(response.bars);
|
|
14453
|
+
const totalBars = Object.values(response.bars).reduce((sum, bars) => sum + bars.length, 0);
|
|
14454
|
+
console.log(` Requested symbols: ${testSymbols.length} (${testSymbols.join(', ')})`);
|
|
14455
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14456
|
+
console.log(` Total bars: ${totalBars}`);
|
|
14457
|
+
// Check each requested symbol
|
|
14458
|
+
const missingSymbols = testSymbols.filter((s) => !symbolsInResponse.includes(s));
|
|
14459
|
+
const extraSymbols = symbolsInResponse.filter((s) => !testSymbols.includes(s));
|
|
14460
|
+
if (missingSymbols.length > 0) {
|
|
14461
|
+
console.error(` ✗ FAILED: Missing symbols: ${missingSymbols.join(', ')}`);
|
|
14462
|
+
}
|
|
14463
|
+
if (extraSymbols.length > 0) {
|
|
14464
|
+
console.error(` ✗ FAILED: Extra symbols not requested: ${extraSymbols.join(', ')}`);
|
|
14465
|
+
}
|
|
14466
|
+
if (symbolsInResponse.length !== testSymbols.length) {
|
|
14467
|
+
console.error(` ✗ FAILED: Expected ${testSymbols.length} symbols in response, got ${symbolsInResponse.length}`);
|
|
14468
|
+
}
|
|
14469
|
+
else if (missingSymbols.length === 0 && extraSymbols.length === 0) {
|
|
14470
|
+
console.log(` ✓ Multiple symbols request correctly returned ${testSymbols.length} symbols`);
|
|
14471
|
+
}
|
|
14472
|
+
// Show bars per symbol
|
|
14473
|
+
testSymbols.forEach((symbol) => {
|
|
14474
|
+
const count = response.bars[symbol]?.length || 0;
|
|
14475
|
+
console.log(` ${symbol}: ${count} bars`);
|
|
14476
|
+
});
|
|
14414
14477
|
}
|
|
14415
|
-
|
|
14416
|
-
console.
|
|
14478
|
+
catch (error) {
|
|
14479
|
+
console.error(' ✗ Test 2 failed:', error);
|
|
14417
14480
|
}
|
|
14418
|
-
// 3
|
|
14419
|
-
log(
|
|
14420
|
-
|
|
14421
|
-
|
|
14422
|
-
|
|
14423
|
-
const
|
|
14424
|
-
|
|
14425
|
-
|
|
14481
|
+
// Test 3: Latest bars - single symbol
|
|
14482
|
+
console.log('\n[Test 3] Latest bars for single symbol');
|
|
14483
|
+
try {
|
|
14484
|
+
const testSymbol = 'TSLA';
|
|
14485
|
+
const response = await marketDataAPI.getLatestBars([testSymbol]);
|
|
14486
|
+
const symbolsInResponse = Object.keys(response.bars);
|
|
14487
|
+
console.log(` Requested symbols: 1 (${testSymbol})`);
|
|
14488
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14489
|
+
if (symbolsInResponse.length !== 1) {
|
|
14490
|
+
console.error(` ✗ FAILED: Expected 1 symbol in response, got ${symbolsInResponse.length}`);
|
|
14491
|
+
}
|
|
14492
|
+
else if (symbolsInResponse[0] !== testSymbol) {
|
|
14493
|
+
console.error(` ✗ FAILED: Expected symbol ${testSymbol}, got ${symbolsInResponse[0]}`);
|
|
14426
14494
|
}
|
|
14427
14495
|
else {
|
|
14428
|
-
console.log(
|
|
14496
|
+
console.log(` ✓ Latest bars correctly returned 1 symbol`);
|
|
14429
14497
|
}
|
|
14430
14498
|
}
|
|
14431
|
-
|
|
14432
|
-
console.
|
|
14499
|
+
catch (error) {
|
|
14500
|
+
console.error(' ✗ Test 3 failed:', error);
|
|
14501
|
+
}
|
|
14502
|
+
// Test 4: Latest bars - multiple symbols
|
|
14503
|
+
console.log('\n[Test 4] Latest bars for multiple symbols');
|
|
14504
|
+
try {
|
|
14505
|
+
const testSymbols = ['SPY', 'QQQ', 'IWM', 'DIA'];
|
|
14506
|
+
const response = await marketDataAPI.getLatestBars(testSymbols);
|
|
14507
|
+
const symbolsInResponse = Object.keys(response.bars);
|
|
14508
|
+
console.log(` Requested symbols: ${testSymbols.length} (${testSymbols.join(', ')})`);
|
|
14509
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14510
|
+
const missingSymbols = testSymbols.filter((s) => !symbolsInResponse.includes(s));
|
|
14511
|
+
const extraSymbols = symbolsInResponse.filter((s) => !testSymbols.includes(s));
|
|
14512
|
+
if (missingSymbols.length > 0) {
|
|
14513
|
+
console.error(` ✗ FAILED: Missing symbols: ${missingSymbols.join(', ')}`);
|
|
14514
|
+
}
|
|
14515
|
+
if (extraSymbols.length > 0) {
|
|
14516
|
+
console.error(` ✗ FAILED: Extra symbols not requested: ${extraSymbols.join(', ')}`);
|
|
14517
|
+
}
|
|
14518
|
+
if (symbolsInResponse.length !== testSymbols.length) {
|
|
14519
|
+
console.error(` ✗ FAILED: Expected ${testSymbols.length} symbols in response, got ${symbolsInResponse.length}`);
|
|
14520
|
+
}
|
|
14521
|
+
else if (missingSymbols.length === 0 && extraSymbols.length === 0) {
|
|
14522
|
+
console.log(` ✓ Latest bars correctly returned ${testSymbols.length} symbols`);
|
|
14523
|
+
}
|
|
14524
|
+
}
|
|
14525
|
+
catch (error) {
|
|
14526
|
+
console.error(' ✗ Test 4 failed:', error);
|
|
14527
|
+
}
|
|
14528
|
+
// Test 5: Latest quotes - verify symbol count
|
|
14529
|
+
console.log('\n[Test 5] Latest quotes for multiple symbols');
|
|
14530
|
+
try {
|
|
14531
|
+
const testSymbols = ['AAPL', 'NVDA', 'AMD'];
|
|
14532
|
+
const response = await marketDataAPI.getLatestQuotes(testSymbols);
|
|
14533
|
+
const symbolsInResponse = Object.keys(response.quotes);
|
|
14534
|
+
console.log(` Requested symbols: ${testSymbols.length} (${testSymbols.join(', ')})`);
|
|
14535
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14536
|
+
const missingSymbols = testSymbols.filter((s) => !symbolsInResponse.includes(s));
|
|
14537
|
+
const extraSymbols = symbolsInResponse.filter((s) => !testSymbols.includes(s));
|
|
14538
|
+
if (missingSymbols.length > 0) {
|
|
14539
|
+
console.error(` ✗ FAILED: Missing symbols: ${missingSymbols.join(', ')}`);
|
|
14540
|
+
}
|
|
14541
|
+
if (extraSymbols.length > 0) {
|
|
14542
|
+
console.error(` ✗ FAILED: Extra symbols not requested: ${extraSymbols.join(', ')}`);
|
|
14543
|
+
}
|
|
14544
|
+
if (symbolsInResponse.length !== testSymbols.length) {
|
|
14545
|
+
console.error(` ✗ FAILED: Expected ${testSymbols.length} symbols in response, got ${symbolsInResponse.length}`);
|
|
14546
|
+
}
|
|
14547
|
+
else if (missingSymbols.length === 0 && extraSymbols.length === 0) {
|
|
14548
|
+
console.log(` ✓ Latest quotes correctly returned ${testSymbols.length} symbols`);
|
|
14549
|
+
}
|
|
14550
|
+
}
|
|
14551
|
+
catch (error) {
|
|
14552
|
+
console.error(' ✗ Test 5 failed:', error);
|
|
14553
|
+
}
|
|
14554
|
+
// Test 6: Latest trades - verify symbol count
|
|
14555
|
+
console.log('\n[Test 6] Latest trades for multiple symbols');
|
|
14556
|
+
try {
|
|
14557
|
+
const testSymbols = ['META', 'AMZN'];
|
|
14558
|
+
const response = await marketDataAPI.getLatestTrades(testSymbols);
|
|
14559
|
+
const symbolsInResponse = Object.keys(response.trades);
|
|
14560
|
+
console.log(` Requested symbols: ${testSymbols.length} (${testSymbols.join(', ')})`);
|
|
14561
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14562
|
+
const missingSymbols = testSymbols.filter((s) => !symbolsInResponse.includes(s));
|
|
14563
|
+
const extraSymbols = symbolsInResponse.filter((s) => !testSymbols.includes(s));
|
|
14564
|
+
if (missingSymbols.length > 0) {
|
|
14565
|
+
console.error(` ✗ FAILED: Missing symbols: ${missingSymbols.join(', ')}`);
|
|
14566
|
+
}
|
|
14567
|
+
if (extraSymbols.length > 0) {
|
|
14568
|
+
console.error(` ✗ FAILED: Extra symbols not requested: ${extraSymbols.join(', ')}`);
|
|
14569
|
+
}
|
|
14570
|
+
if (symbolsInResponse.length !== testSymbols.length) {
|
|
14571
|
+
console.error(` ✗ FAILED: Expected ${testSymbols.length} symbols in response, got ${symbolsInResponse.length}`);
|
|
14572
|
+
}
|
|
14573
|
+
else if (missingSymbols.length === 0 && extraSymbols.length === 0) {
|
|
14574
|
+
console.log(` ✓ Latest trades correctly returned ${testSymbols.length} symbols`);
|
|
14575
|
+
}
|
|
14576
|
+
}
|
|
14577
|
+
catch (error) {
|
|
14578
|
+
console.error(' ✗ Test 6 failed:', error);
|
|
14579
|
+
}
|
|
14580
|
+
// Test 7: Empty symbols array
|
|
14581
|
+
console.log('\n[Test 7] Empty symbols array handling');
|
|
14582
|
+
try {
|
|
14583
|
+
const response = await marketDataAPI.getLatestQuotes([]);
|
|
14584
|
+
const symbolsInResponse = Object.keys(response.quotes);
|
|
14585
|
+
console.log(` Requested symbols: 0 (empty array)`);
|
|
14586
|
+
console.log(` Symbols in response: ${symbolsInResponse.length}`);
|
|
14587
|
+
if (symbolsInResponse.length === 0) {
|
|
14588
|
+
console.log(` ✓ Empty symbols array correctly returned empty response`);
|
|
14589
|
+
}
|
|
14590
|
+
else {
|
|
14591
|
+
console.error(` ✗ FAILED: Expected 0 symbols in response, got ${symbolsInResponse.length}`);
|
|
14592
|
+
}
|
|
14593
|
+
}
|
|
14594
|
+
catch (error) {
|
|
14595
|
+
console.error(' ✗ Test 7 failed:', error);
|
|
14596
|
+
}
|
|
14597
|
+
// Test 8: Historical bars with date range that spans multiple pages
|
|
14598
|
+
console.log('\n[Test 8] Historical bars with pagination (longer date range)');
|
|
14599
|
+
try {
|
|
14600
|
+
const testSymbols = ['SPY'];
|
|
14601
|
+
const endDate = new Date('2023-03-15T23:59:59.999Z');
|
|
14602
|
+
const startDate = new Date('2023-03-01T01:00:00.000Z');
|
|
14603
|
+
const response = await marketDataAPI.getHistoricalBars({
|
|
14604
|
+
symbols: testSymbols,
|
|
14605
|
+
timeframe: '1Min',
|
|
14606
|
+
start: startDate.toISOString(),
|
|
14607
|
+
end: endDate.toISOString(),
|
|
14608
|
+
});
|
|
14609
|
+
const symbolsInResponse = Object.keys(response.bars);
|
|
14610
|
+
const totalBars = Object.values(response.bars).reduce((sum, bars) => sum + bars.length, 0);
|
|
14611
|
+
console.log(` Requested symbols: ${testSymbols.length} (${testSymbols.join(', ')})`);
|
|
14612
|
+
console.log(` Symbols in response: ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14613
|
+
console.log(` Total bars: ${totalBars}`);
|
|
14614
|
+
const missingSymbols = testSymbols.filter((s) => !symbolsInResponse.includes(s));
|
|
14615
|
+
const extraSymbols = symbolsInResponse.filter((s) => !testSymbols.includes(s));
|
|
14616
|
+
if (missingSymbols.length > 0) {
|
|
14617
|
+
console.error(` ✗ FAILED: Missing symbols: ${missingSymbols.join(', ')}`);
|
|
14618
|
+
}
|
|
14619
|
+
if (extraSymbols.length > 0) {
|
|
14620
|
+
console.error(` ✗ FAILED: Extra symbols not requested: ${extraSymbols.join(', ')}`);
|
|
14621
|
+
}
|
|
14622
|
+
if (symbolsInResponse.length !== testSymbols.length) {
|
|
14623
|
+
console.error(` ✗ FAILED: Expected ${testSymbols.length} symbols in response, got ${symbolsInResponse.length}`);
|
|
14624
|
+
}
|
|
14625
|
+
else if (missingSymbols.length === 0 && extraSymbols.length === 0) {
|
|
14626
|
+
console.log(` ✓ Paginated request correctly returned ${testSymbols.length} symbols`);
|
|
14627
|
+
}
|
|
14628
|
+
}
|
|
14629
|
+
catch (error) {
|
|
14630
|
+
console.error(' ✗ Test 8 failed:', error);
|
|
14631
|
+
}
|
|
14632
|
+
// Test 9: Check for duplicate bars across pagination
|
|
14633
|
+
console.log('\n[Test 9] Check for duplicate bars in paginated response');
|
|
14634
|
+
try {
|
|
14635
|
+
const testSymbol = 'AAPL';
|
|
14636
|
+
const endDate = new Date('2023-02-28T23:59:59.999Z');
|
|
14637
|
+
const startDate = new Date('2023-02-24T00:00:00.000Z');
|
|
14638
|
+
const response = await marketDataAPI.getHistoricalBars({
|
|
14639
|
+
symbols: [testSymbol],
|
|
14640
|
+
timeframe: '1Min',
|
|
14641
|
+
start: startDate.toISOString(),
|
|
14642
|
+
end: endDate.toISOString(),
|
|
14643
|
+
});
|
|
14644
|
+
const bars = response.bars[testSymbol] || [];
|
|
14645
|
+
const timestamps = bars.map((bar) => bar.t);
|
|
14646
|
+
const uniqueTimestamps = new Set(timestamps);
|
|
14647
|
+
console.log(` Total bars: ${bars.length}`);
|
|
14648
|
+
console.log(` Unique timestamps: ${uniqueTimestamps.size}`);
|
|
14649
|
+
if (bars.length !== uniqueTimestamps.size) {
|
|
14650
|
+
const duplicateCount = bars.length - uniqueTimestamps.size;
|
|
14651
|
+
console.error(` ✗ FAILED: Found ${duplicateCount} duplicate bars`);
|
|
14652
|
+
// Show some duplicate examples
|
|
14653
|
+
const timestampCounts = new Map();
|
|
14654
|
+
timestamps.forEach((ts) => {
|
|
14655
|
+
timestampCounts.set(ts, (timestampCounts.get(ts) || 0) + 1);
|
|
14656
|
+
});
|
|
14657
|
+
const duplicates = Array.from(timestampCounts.entries())
|
|
14658
|
+
.filter(([_, count]) => count > 1)
|
|
14659
|
+
.slice(0, 5);
|
|
14660
|
+
if (duplicates.length > 0) {
|
|
14661
|
+
console.error(` Examples of duplicates:`);
|
|
14662
|
+
duplicates.forEach(([ts, count]) => {
|
|
14663
|
+
console.error(` ${ts}: ${count} occurrences`);
|
|
14664
|
+
});
|
|
14665
|
+
}
|
|
14666
|
+
}
|
|
14667
|
+
else {
|
|
14668
|
+
console.log(` ✓ No duplicate bars found`);
|
|
14669
|
+
}
|
|
14670
|
+
}
|
|
14671
|
+
catch (error) {
|
|
14672
|
+
console.error(' ✗ Test 9 failed:', error);
|
|
14673
|
+
}
|
|
14674
|
+
// Test 10: Verify logging accuracy - track what logs say vs actual data
|
|
14675
|
+
console.log('\n[Test 10] Verify logging accuracy');
|
|
14676
|
+
try {
|
|
14677
|
+
const testSymbols = ['AAPL', 'MSFT', 'GOOGL'];
|
|
14678
|
+
// Capture logs
|
|
14679
|
+
const originalLog = console.log;
|
|
14680
|
+
const logs = [];
|
|
14681
|
+
console.log = (...args) => {
|
|
14682
|
+
logs.push(args.join(' '));
|
|
14683
|
+
originalLog(...args);
|
|
14684
|
+
};
|
|
14685
|
+
const response = await marketDataAPI.getHistoricalBars({
|
|
14686
|
+
symbols: testSymbols,
|
|
14687
|
+
timeframe: '5Min',
|
|
14688
|
+
start: new Date('2023-02-27T09:30:00.000Z').toISOString(),
|
|
14689
|
+
end: new Date('2023-02-27T16:00:00.000Z').toISOString(),
|
|
14690
|
+
});
|
|
14691
|
+
console.log = originalLog;
|
|
14692
|
+
const symbolsInResponse = Object.keys(response.bars);
|
|
14693
|
+
console.log(` Requested symbols: ${testSymbols.length}`);
|
|
14694
|
+
console.log(` Actual symbols in response: ${symbolsInResponse.length}`);
|
|
14695
|
+
// Check if any logs mention incorrect symbol counts
|
|
14696
|
+
const logLines = logs.filter((log) => log.includes('symbols') && (log.includes('Starting') || log.includes('complete')));
|
|
14697
|
+
logLines.forEach((line) => {
|
|
14698
|
+
console.log(` Log: ${line}`);
|
|
14699
|
+
});
|
|
14700
|
+
if (symbolsInResponse.length === testSymbols.length) {
|
|
14701
|
+
console.log(` ✓ Response contains correct number of symbols`);
|
|
14702
|
+
}
|
|
14703
|
+
else {
|
|
14704
|
+
console.error(` ✗ FAILED: Expected ${testSymbols.length} symbols, got ${symbolsInResponse.length} (${symbolsInResponse.join(', ')})`);
|
|
14705
|
+
}
|
|
14706
|
+
}
|
|
14707
|
+
catch (error) {
|
|
14708
|
+
console.error(' ✗ Test 10 failed:', error);
|
|
14433
14709
|
}
|
|
14710
|
+
console.log('\n✓ All Market Data API tests completed!');
|
|
14434
14711
|
}
|
|
14435
14712
|
catch (error) {
|
|
14436
|
-
console.error('✗
|
|
14713
|
+
console.error('✗ Market Data API test setup failed:', error);
|
|
14437
14714
|
if (error instanceof Error) {
|
|
14438
14715
|
console.error('Error message:', error.message);
|
|
14439
14716
|
console.error('Stack trace:', error.stack);
|
|
@@ -14453,5 +14730,6 @@ async function testGetAssetsShortableFilter() {
|
|
|
14453
14730
|
// testCryptoMarketData();
|
|
14454
14731
|
// testGetPortfolioDailyHistory();
|
|
14455
14732
|
// testWebSocketConnectAndDisconnect();
|
|
14456
|
-
testGetAssetsShortableFilter();
|
|
14733
|
+
// testGetAssetsShortableFilter();
|
|
14734
|
+
testMarketDataAPI();
|
|
14457
14735
|
//# sourceMappingURL=test.js.map
|