@adaptic/utils 0.0.380 → 0.0.382
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 +110 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +110 -31
- package/dist/index.mjs.map +1 -1
- package/dist/test.js +110 -31
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts +7 -7
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types/types/alpaca-types.d.ts +32 -37
- package/dist/types/types/alpaca-types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/index.mjs
CHANGED
|
@@ -11462,7 +11462,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11462
11462
|
cryptoWs = null;
|
|
11463
11463
|
stockSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
11464
11464
|
optionSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
11465
|
-
cryptoSubscriptions = { trades: [], quotes: [], bars: []
|
|
11465
|
+
cryptoSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
11466
11466
|
setMode(mode = 'production') {
|
|
11467
11467
|
if (mode === 'sandbox') { // sandbox mode
|
|
11468
11468
|
this.stockStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v2/sip';
|
|
@@ -11519,7 +11519,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11519
11519
|
return super.emit(event, ...args);
|
|
11520
11520
|
}
|
|
11521
11521
|
connect(streamType) {
|
|
11522
|
-
|
|
11522
|
+
let url;
|
|
11523
|
+
if (streamType === 'stock') {
|
|
11524
|
+
url = this.stockStreamUrl;
|
|
11525
|
+
}
|
|
11526
|
+
else if (streamType === 'option') {
|
|
11527
|
+
url = this.optionStreamUrl;
|
|
11528
|
+
}
|
|
11529
|
+
else {
|
|
11530
|
+
url = this.cryptoStreamUrl;
|
|
11531
|
+
}
|
|
11523
11532
|
const ws = new WebSocket(url);
|
|
11524
11533
|
if (streamType === 'stock') {
|
|
11525
11534
|
this.stockWs = ws;
|
|
@@ -11540,20 +11549,36 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11540
11549
|
ws.send(JSON.stringify(authMessage));
|
|
11541
11550
|
});
|
|
11542
11551
|
ws.on('message', (data) => {
|
|
11543
|
-
|
|
11544
|
-
|
|
11552
|
+
const rawData = data.toString();
|
|
11553
|
+
let messages;
|
|
11554
|
+
try {
|
|
11555
|
+
messages = JSON.parse(rawData);
|
|
11556
|
+
}
|
|
11557
|
+
catch (e) {
|
|
11558
|
+
log(`${streamType} stream received invalid JSON: ${rawData.substring(0, 200)}`, { type: 'error' });
|
|
11559
|
+
return;
|
|
11560
|
+
}
|
|
11545
11561
|
for (const message of messages) {
|
|
11546
11562
|
if (message.T === 'success' && message.msg === 'authenticated') {
|
|
11547
11563
|
log(`${streamType} stream authenticated`, { type: 'info' });
|
|
11548
11564
|
this.sendSubscription(streamType);
|
|
11549
11565
|
}
|
|
11566
|
+
else if (message.T === 'success' && message.msg === 'connected') {
|
|
11567
|
+
log(`${streamType} stream connected message received`, { type: 'debug' });
|
|
11568
|
+
}
|
|
11569
|
+
else if (message.T === 'subscription') {
|
|
11570
|
+
log(`${streamType} subscription confirmed: trades=${message.trades?.length || 0}, quotes=${message.quotes?.length || 0}, bars=${message.bars?.length || 0}`, { type: 'info' });
|
|
11571
|
+
}
|
|
11550
11572
|
else if (message.T === 'error') {
|
|
11551
|
-
log(`${streamType} stream error: ${message.msg}`, { type: 'error' });
|
|
11573
|
+
log(`${streamType} stream error: ${message.msg} (code: ${message.code}, raw: ${JSON.stringify(message)})`, { type: 'error' });
|
|
11552
11574
|
}
|
|
11553
11575
|
else if (message.S) {
|
|
11554
11576
|
super.emit(`${streamType}-${message.T}`, message);
|
|
11555
11577
|
super.emit(`${streamType}-data`, message);
|
|
11556
11578
|
}
|
|
11579
|
+
else {
|
|
11580
|
+
log(`${streamType} received unknown message type: ${JSON.stringify(message)}`, { type: 'debug' });
|
|
11581
|
+
}
|
|
11557
11582
|
}
|
|
11558
11583
|
});
|
|
11559
11584
|
ws.on('close', () => {
|
|
@@ -11574,38 +11599,49 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11574
11599
|
});
|
|
11575
11600
|
}
|
|
11576
11601
|
sendSubscription(streamType) {
|
|
11577
|
-
|
|
11578
|
-
|
|
11602
|
+
let ws;
|
|
11603
|
+
let subscriptions;
|
|
11604
|
+
if (streamType === 'stock') {
|
|
11605
|
+
ws = this.stockWs;
|
|
11606
|
+
subscriptions = this.stockSubscriptions;
|
|
11607
|
+
}
|
|
11608
|
+
else if (streamType === 'option') {
|
|
11609
|
+
ws = this.optionWs;
|
|
11610
|
+
subscriptions = this.optionSubscriptions;
|
|
11611
|
+
}
|
|
11612
|
+
else {
|
|
11613
|
+
ws = this.cryptoWs;
|
|
11614
|
+
subscriptions = this.cryptoSubscriptions;
|
|
11615
|
+
}
|
|
11616
|
+
log(`sendSubscription called for ${streamType} (wsReady=${ws?.readyState === WebSocket.OPEN}, trades=${subscriptions.trades?.length || 0}, quotes=${subscriptions.quotes?.length || 0}, bars=${subscriptions.bars?.length || 0})`, {
|
|
11617
|
+
type: 'debug',
|
|
11618
|
+
});
|
|
11579
11619
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
11580
11620
|
const subMessagePayload = {};
|
|
11581
|
-
if (subscriptions.trades
|
|
11621
|
+
if (subscriptions.trades.length > 0) {
|
|
11582
11622
|
subMessagePayload.trades = subscriptions.trades;
|
|
11583
11623
|
}
|
|
11584
|
-
if (subscriptions.quotes
|
|
11624
|
+
if (subscriptions.quotes.length > 0) {
|
|
11585
11625
|
subMessagePayload.quotes = subscriptions.quotes;
|
|
11586
11626
|
}
|
|
11587
|
-
if (subscriptions.bars
|
|
11627
|
+
if (subscriptions.bars.length > 0) {
|
|
11588
11628
|
subMessagePayload.bars = subscriptions.bars;
|
|
11589
11629
|
}
|
|
11590
|
-
// Crypto-specific subscription types
|
|
11591
|
-
if (streamType === 'crypto') {
|
|
11592
|
-
if (subscriptions.dailyBars && subscriptions.dailyBars.length > 0) {
|
|
11593
|
-
subMessagePayload.dailyBars = subscriptions.dailyBars;
|
|
11594
|
-
}
|
|
11595
|
-
if (subscriptions.updatedBars && subscriptions.updatedBars.length > 0) {
|
|
11596
|
-
subMessagePayload.updatedBars = subscriptions.updatedBars;
|
|
11597
|
-
}
|
|
11598
|
-
if (subscriptions.orderbooks && subscriptions.orderbooks.length > 0) {
|
|
11599
|
-
subMessagePayload.orderbooks = subscriptions.orderbooks;
|
|
11600
|
-
}
|
|
11601
|
-
}
|
|
11602
11630
|
if (Object.keys(subMessagePayload).length > 0) {
|
|
11603
11631
|
const subMessage = {
|
|
11604
11632
|
action: 'subscribe',
|
|
11605
11633
|
...subMessagePayload,
|
|
11606
11634
|
};
|
|
11607
|
-
|
|
11635
|
+
const messageJson = JSON.stringify(subMessage);
|
|
11636
|
+
log(`Sending ${streamType} subscription: ${messageJson}`, { type: 'info' });
|
|
11637
|
+
ws.send(messageJson);
|
|
11608
11638
|
}
|
|
11639
|
+
else {
|
|
11640
|
+
log(`No ${streamType} subscriptions to send (all arrays empty)`, { type: 'debug' });
|
|
11641
|
+
}
|
|
11642
|
+
}
|
|
11643
|
+
else {
|
|
11644
|
+
log(`Cannot send ${streamType} subscription: WebSocket not ready`, { type: 'warn' });
|
|
11609
11645
|
}
|
|
11610
11646
|
}
|
|
11611
11647
|
connectStockStream() {
|
|
@@ -11618,6 +11654,11 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11618
11654
|
this.connect('option');
|
|
11619
11655
|
}
|
|
11620
11656
|
}
|
|
11657
|
+
connectCryptoStream() {
|
|
11658
|
+
if (!this.cryptoWs) {
|
|
11659
|
+
this.connect('crypto');
|
|
11660
|
+
}
|
|
11661
|
+
}
|
|
11621
11662
|
disconnectStockStream() {
|
|
11622
11663
|
if (this.stockWs) {
|
|
11623
11664
|
this.stockWs.close();
|
|
@@ -11628,18 +11669,38 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11628
11669
|
this.optionWs.close();
|
|
11629
11670
|
}
|
|
11630
11671
|
}
|
|
11631
|
-
connectCryptoStream() {
|
|
11632
|
-
if (!this.cryptoWs) {
|
|
11633
|
-
this.connect('crypto');
|
|
11634
|
-
}
|
|
11635
|
-
}
|
|
11636
11672
|
disconnectCryptoStream() {
|
|
11637
11673
|
if (this.cryptoWs) {
|
|
11638
11674
|
this.cryptoWs.close();
|
|
11639
11675
|
}
|
|
11640
11676
|
}
|
|
11677
|
+
/**
|
|
11678
|
+
* Check if a specific stream is connected
|
|
11679
|
+
* @param streamType - The type of stream to check
|
|
11680
|
+
* @returns True if the stream is connected
|
|
11681
|
+
*/
|
|
11682
|
+
isStreamConnected(streamType) {
|
|
11683
|
+
if (streamType === 'stock') {
|
|
11684
|
+
return this.stockWs !== null && this.stockWs.readyState === WebSocket.OPEN;
|
|
11685
|
+
}
|
|
11686
|
+
else if (streamType === 'option') {
|
|
11687
|
+
return this.optionWs !== null && this.optionWs.readyState === WebSocket.OPEN;
|
|
11688
|
+
}
|
|
11689
|
+
else {
|
|
11690
|
+
return this.cryptoWs !== null && this.cryptoWs.readyState === WebSocket.OPEN;
|
|
11691
|
+
}
|
|
11692
|
+
}
|
|
11641
11693
|
subscribe(streamType, subscriptions) {
|
|
11642
|
-
|
|
11694
|
+
let currentSubscriptions;
|
|
11695
|
+
if (streamType === 'stock') {
|
|
11696
|
+
currentSubscriptions = this.stockSubscriptions;
|
|
11697
|
+
}
|
|
11698
|
+
else if (streamType === 'option') {
|
|
11699
|
+
currentSubscriptions = this.optionSubscriptions;
|
|
11700
|
+
}
|
|
11701
|
+
else {
|
|
11702
|
+
currentSubscriptions = this.cryptoSubscriptions;
|
|
11703
|
+
}
|
|
11643
11704
|
Object.entries(subscriptions).forEach(([key, value]) => {
|
|
11644
11705
|
if (value) {
|
|
11645
11706
|
currentSubscriptions[key] = [...new Set([...(currentSubscriptions[key] || []), ...value])];
|
|
@@ -11648,7 +11709,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11648
11709
|
this.sendSubscription(streamType);
|
|
11649
11710
|
}
|
|
11650
11711
|
unsubscribe(streamType, subscriptions) {
|
|
11651
|
-
|
|
11712
|
+
let currentSubscriptions;
|
|
11713
|
+
if (streamType === 'stock') {
|
|
11714
|
+
currentSubscriptions = this.stockSubscriptions;
|
|
11715
|
+
}
|
|
11716
|
+
else if (streamType === 'option') {
|
|
11717
|
+
currentSubscriptions = this.optionSubscriptions;
|
|
11718
|
+
}
|
|
11719
|
+
else {
|
|
11720
|
+
currentSubscriptions = this.cryptoSubscriptions;
|
|
11721
|
+
}
|
|
11652
11722
|
Object.entries(subscriptions).forEach(([key, value]) => {
|
|
11653
11723
|
if (value) {
|
|
11654
11724
|
currentSubscriptions[key] = (currentSubscriptions[key] || []).filter(s => !value.includes(s));
|
|
@@ -11658,7 +11728,16 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
11658
11728
|
action: 'unsubscribe',
|
|
11659
11729
|
...subscriptions,
|
|
11660
11730
|
};
|
|
11661
|
-
|
|
11731
|
+
let ws;
|
|
11732
|
+
if (streamType === 'stock') {
|
|
11733
|
+
ws = this.stockWs;
|
|
11734
|
+
}
|
|
11735
|
+
else if (streamType === 'option') {
|
|
11736
|
+
ws = this.optionWs;
|
|
11737
|
+
}
|
|
11738
|
+
else {
|
|
11739
|
+
ws = this.cryptoWs;
|
|
11740
|
+
}
|
|
11662
11741
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
11663
11742
|
ws.send(JSON.stringify(unsubMessage));
|
|
11664
11743
|
}
|