@discomedia/utils 1.0.43 → 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.cjs +13 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +13 -13
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +1 -1
- package/dist/test.js +311 -49
- package/dist/test.js.map +1 -1
- package/package.json +1 -1
package/dist/package.json
CHANGED
package/dist/test.js
CHANGED
|
@@ -13474,7 +13474,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13474
13474
|
*/
|
|
13475
13475
|
async getHistoricalBars(params) {
|
|
13476
13476
|
const symbols = params.symbols;
|
|
13477
|
-
|
|
13477
|
+
symbols.join(',');
|
|
13478
13478
|
let allBars = {};
|
|
13479
13479
|
let pageToken = null;
|
|
13480
13480
|
let hasMorePages = true;
|
|
@@ -13485,7 +13485,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13485
13485
|
symbols.forEach((symbol) => {
|
|
13486
13486
|
allBars[symbol] = [];
|
|
13487
13487
|
});
|
|
13488
|
-
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'})`);
|
|
13489
13489
|
while (hasMorePages) {
|
|
13490
13490
|
pageCount++;
|
|
13491
13491
|
const requestParams = {
|
|
@@ -13496,7 +13496,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13496
13496
|
};
|
|
13497
13497
|
const response = await this.makeRequest('/stocks/bars', 'GET', requestParams);
|
|
13498
13498
|
if (!response.bars) {
|
|
13499
|
-
log(`No bars data found in response for ${
|
|
13499
|
+
log(`No bars data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
13500
13500
|
break;
|
|
13501
13501
|
}
|
|
13502
13502
|
// Track currency from first response
|
|
@@ -13538,10 +13538,10 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13538
13538
|
}
|
|
13539
13539
|
}
|
|
13540
13540
|
// Final summary
|
|
13541
|
-
const
|
|
13541
|
+
const symbolCounts = Object.entries(allBars)
|
|
13542
13542
|
.map(([symbol, bars]) => `${symbol}: ${bars.length}`)
|
|
13543
13543
|
.join(', ');
|
|
13544
|
-
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})`);
|
|
13545
13545
|
return {
|
|
13546
13546
|
bars: allBars,
|
|
13547
13547
|
next_page_token: null, // Always null since we fetch all pages
|
|
@@ -13812,7 +13812,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13812
13812
|
*/
|
|
13813
13813
|
async getHistoricalOptionsBars(params) {
|
|
13814
13814
|
const symbols = params.symbols;
|
|
13815
|
-
|
|
13815
|
+
symbols.join(',');
|
|
13816
13816
|
let allBars = {};
|
|
13817
13817
|
let pageToken = null;
|
|
13818
13818
|
let hasMorePages = true;
|
|
@@ -13822,7 +13822,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13822
13822
|
symbols.forEach((symbol) => {
|
|
13823
13823
|
allBars[symbol] = [];
|
|
13824
13824
|
});
|
|
13825
|
-
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'})`);
|
|
13826
13826
|
while (hasMorePages) {
|
|
13827
13827
|
pageCount++;
|
|
13828
13828
|
const requestParams = {
|
|
@@ -13831,7 +13831,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13831
13831
|
};
|
|
13832
13832
|
const response = await this.makeRequest('/options/bars', 'GET', requestParams, 'v1beta1');
|
|
13833
13833
|
if (!response.bars) {
|
|
13834
|
-
log(`No options bars data found in response for ${
|
|
13834
|
+
log(`No options bars data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
13835
13835
|
break;
|
|
13836
13836
|
}
|
|
13837
13837
|
// Combine bars for each symbol
|
|
@@ -13861,7 +13861,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13861
13861
|
const dateRangeStr = earliestTimestamp && latestTimestamp
|
|
13862
13862
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
13863
13863
|
: 'unknown range';
|
|
13864
|
-
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'}`, {
|
|
13865
13865
|
type: 'debug',
|
|
13866
13866
|
});
|
|
13867
13867
|
// Prevent infinite loops
|
|
@@ -13890,7 +13890,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13890
13890
|
*/
|
|
13891
13891
|
async getHistoricalOptionsTrades(params) {
|
|
13892
13892
|
const symbols = params.symbols;
|
|
13893
|
-
|
|
13893
|
+
symbols.join(',');
|
|
13894
13894
|
let allTrades = {};
|
|
13895
13895
|
let pageToken = null;
|
|
13896
13896
|
let hasMorePages = true;
|
|
@@ -13900,7 +13900,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13900
13900
|
symbols.forEach((symbol) => {
|
|
13901
13901
|
allTrades[symbol] = [];
|
|
13902
13902
|
});
|
|
13903
|
-
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'})`);
|
|
13904
13904
|
while (hasMorePages) {
|
|
13905
13905
|
pageCount++;
|
|
13906
13906
|
const requestParams = {
|
|
@@ -13909,7 +13909,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13909
13909
|
};
|
|
13910
13910
|
const response = await this.makeRequest('/options/trades', 'GET', requestParams, 'v1beta1');
|
|
13911
13911
|
if (!response.trades) {
|
|
13912
|
-
log(`No options trades data found in response for ${
|
|
13912
|
+
log(`No options trades data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
13913
13913
|
break;
|
|
13914
13914
|
}
|
|
13915
13915
|
// Combine trades for each symbol
|
|
@@ -13939,7 +13939,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
13939
13939
|
const dateRangeStr = earliestTimestamp && latestTimestamp
|
|
13940
13940
|
? `${earliestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${latestTimestamp.toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
13941
13941
|
: 'unknown range';
|
|
13942
|
-
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'}`, {
|
|
13943
13943
|
type: 'debug',
|
|
13944
13944
|
});
|
|
13945
13945
|
// Prevent infinite loops
|
|
@@ -14399,57 +14399,318 @@ var alpacaMarketDataApi = /*#__PURE__*/Object.freeze({
|
|
|
14399
14399
|
});
|
|
14400
14400
|
|
|
14401
14401
|
// Test file for context functionality
|
|
14402
|
-
async function
|
|
14403
|
-
console.log('\n--- Testing
|
|
14404
|
-
const log = (message, options = { type: 'info' }) => {
|
|
14405
|
-
log$1(message, { ...options, source: 'Test' });
|
|
14406
|
-
};
|
|
14402
|
+
async function testMarketDataAPI() {
|
|
14403
|
+
console.log('\n--- Testing Market Data API ---');
|
|
14407
14404
|
if (!process.env.ALPACA_API_KEY || !process.env.ALPACA_SECRET_KEY) {
|
|
14408
|
-
console.log('Skipping
|
|
14405
|
+
console.log('Skipping Market Data API tests: Missing environment variables (ALPACA_API_KEY, ALPACA_SECRET_KEY)');
|
|
14409
14406
|
return;
|
|
14410
14407
|
}
|
|
14411
14408
|
try {
|
|
14412
14409
|
const { marketDataAPI } = await Promise.resolve().then(function () { return alpacaMarketDataApi; });
|
|
14413
|
-
// 1
|
|
14414
|
-
log('
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
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
|
+
}
|
|
14420
14436
|
}
|
|
14421
|
-
|
|
14422
|
-
console.
|
|
14437
|
+
catch (error) {
|
|
14438
|
+
console.error(' ✗ Test 1 failed:', error);
|
|
14423
14439
|
}
|
|
14424
|
-
// 2
|
|
14425
|
-
log('
|
|
14426
|
-
|
|
14427
|
-
|
|
14428
|
-
|
|
14429
|
-
|
|
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
|
+
});
|
|
14430
14477
|
}
|
|
14431
|
-
|
|
14432
|
-
console.
|
|
14478
|
+
catch (error) {
|
|
14479
|
+
console.error(' ✗ Test 2 failed:', error);
|
|
14433
14480
|
}
|
|
14434
|
-
// 3
|
|
14435
|
-
log(
|
|
14436
|
-
|
|
14437
|
-
|
|
14438
|
-
|
|
14439
|
-
const
|
|
14440
|
-
|
|
14441
|
-
|
|
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]}`);
|
|
14442
14494
|
}
|
|
14443
14495
|
else {
|
|
14444
|
-
console.log(
|
|
14496
|
+
console.log(` ✓ Latest bars correctly returned 1 symbol`);
|
|
14445
14497
|
}
|
|
14446
14498
|
}
|
|
14447
|
-
|
|
14448
|
-
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);
|
|
14449
14709
|
}
|
|
14710
|
+
console.log('\n✓ All Market Data API tests completed!');
|
|
14450
14711
|
}
|
|
14451
14712
|
catch (error) {
|
|
14452
|
-
console.error('✗
|
|
14713
|
+
console.error('✗ Market Data API test setup failed:', error);
|
|
14453
14714
|
if (error instanceof Error) {
|
|
14454
14715
|
console.error('Error message:', error.message);
|
|
14455
14716
|
console.error('Stack trace:', error.stack);
|
|
@@ -14469,5 +14730,6 @@ async function testGetAssetsShortableFilter() {
|
|
|
14469
14730
|
// testCryptoMarketData();
|
|
14470
14731
|
// testGetPortfolioDailyHistory();
|
|
14471
14732
|
// testWebSocketConnectAndDisconnect();
|
|
14472
|
-
testGetAssetsShortableFilter();
|
|
14733
|
+
// testGetAssetsShortableFilter();
|
|
14734
|
+
testMarketDataAPI();
|
|
14473
14735
|
//# sourceMappingURL=test.js.map
|