@adaptic/utils 0.0.379 → 0.0.381
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 +125 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +125 -12
- package/dist/index.mjs.map +1 -1
- package/dist/test.js +125 -12
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts +16 -3
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types/types/alpaca-types.d.ts +89 -0
- package/dist/types/types/alpaca-types.d.ts.map +1 -1
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -11478,22 +11478,28 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11478
11478
|
v1beta1url;
|
|
11479
11479
|
stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/sip'; // production values
|
|
11480
11480
|
optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options'; // production values
|
|
11481
|
+
cryptoStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/crypto/us'; // production values
|
|
11481
11482
|
stockWs = null;
|
|
11482
11483
|
optionWs = null;
|
|
11484
|
+
cryptoWs = null;
|
|
11483
11485
|
stockSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
11484
11486
|
optionSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
11487
|
+
cryptoSubscriptions = { trades: [], quotes: [], bars: [] };
|
|
11485
11488
|
setMode(mode = 'production') {
|
|
11486
11489
|
if (mode === 'sandbox') { // sandbox mode
|
|
11487
11490
|
this.stockStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v2/sip';
|
|
11488
11491
|
this.optionStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v1beta3/options';
|
|
11492
|
+
this.cryptoStreamUrl = 'wss://stream.data.sandbox.alpaca.markets/v1beta3/crypto/us';
|
|
11489
11493
|
}
|
|
11490
11494
|
else if (mode === 'test') { // test mode, can only use ticker FAKEPACA
|
|
11491
11495
|
this.stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/test';
|
|
11492
11496
|
this.optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options'; // there's no test mode for options
|
|
11497
|
+
this.cryptoStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/crypto/us'; // there's no test mode for crypto
|
|
11493
11498
|
}
|
|
11494
11499
|
else { // production
|
|
11495
11500
|
this.stockStreamUrl = 'wss://stream.data.alpaca.markets/v2/sip';
|
|
11496
11501
|
this.optionStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/options';
|
|
11502
|
+
this.cryptoStreamUrl = 'wss://stream.data.alpaca.markets/v1beta3/crypto/us';
|
|
11497
11503
|
}
|
|
11498
11504
|
}
|
|
11499
11505
|
getMode() {
|
|
@@ -11535,14 +11541,26 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11535
11541
|
return super.emit(event, ...args);
|
|
11536
11542
|
}
|
|
11537
11543
|
connect(streamType) {
|
|
11538
|
-
|
|
11544
|
+
let url;
|
|
11545
|
+
if (streamType === 'stock') {
|
|
11546
|
+
url = this.stockStreamUrl;
|
|
11547
|
+
}
|
|
11548
|
+
else if (streamType === 'option') {
|
|
11549
|
+
url = this.optionStreamUrl;
|
|
11550
|
+
}
|
|
11551
|
+
else {
|
|
11552
|
+
url = this.cryptoStreamUrl;
|
|
11553
|
+
}
|
|
11539
11554
|
const ws = new WebSocket(url);
|
|
11540
11555
|
if (streamType === 'stock') {
|
|
11541
11556
|
this.stockWs = ws;
|
|
11542
11557
|
}
|
|
11543
|
-
else {
|
|
11558
|
+
else if (streamType === 'option') {
|
|
11544
11559
|
this.optionWs = ws;
|
|
11545
11560
|
}
|
|
11561
|
+
else {
|
|
11562
|
+
this.cryptoWs = ws;
|
|
11563
|
+
}
|
|
11546
11564
|
ws.on('open', () => {
|
|
11547
11565
|
log(`${streamType} stream connected`, { type: 'info' });
|
|
11548
11566
|
const authMessage = {
|
|
@@ -11553,20 +11571,36 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11553
11571
|
ws.send(JSON.stringify(authMessage));
|
|
11554
11572
|
});
|
|
11555
11573
|
ws.on('message', (data) => {
|
|
11556
|
-
|
|
11557
|
-
|
|
11574
|
+
const rawData = data.toString();
|
|
11575
|
+
let messages;
|
|
11576
|
+
try {
|
|
11577
|
+
messages = JSON.parse(rawData);
|
|
11578
|
+
}
|
|
11579
|
+
catch (e) {
|
|
11580
|
+
log(`${streamType} stream received invalid JSON: ${rawData.substring(0, 200)}`, { type: 'error' });
|
|
11581
|
+
return;
|
|
11582
|
+
}
|
|
11558
11583
|
for (const message of messages) {
|
|
11559
11584
|
if (message.T === 'success' && message.msg === 'authenticated') {
|
|
11560
11585
|
log(`${streamType} stream authenticated`, { type: 'info' });
|
|
11561
11586
|
this.sendSubscription(streamType);
|
|
11562
11587
|
}
|
|
11588
|
+
else if (message.T === 'success' && message.msg === 'connected') {
|
|
11589
|
+
log(`${streamType} stream connected message received`, { type: 'debug' });
|
|
11590
|
+
}
|
|
11591
|
+
else if (message.T === 'subscription') {
|
|
11592
|
+
log(`${streamType} subscription confirmed: trades=${message.trades?.length || 0}, quotes=${message.quotes?.length || 0}, bars=${message.bars?.length || 0}`, { type: 'info' });
|
|
11593
|
+
}
|
|
11563
11594
|
else if (message.T === 'error') {
|
|
11564
|
-
log(`${streamType} stream error: ${message.msg}`, { type: 'error' });
|
|
11595
|
+
log(`${streamType} stream error: ${message.msg} (code: ${message.code}, raw: ${JSON.stringify(message)})`, { type: 'error' });
|
|
11565
11596
|
}
|
|
11566
11597
|
else if (message.S) {
|
|
11567
11598
|
super.emit(`${streamType}-${message.T}`, message);
|
|
11568
11599
|
super.emit(`${streamType}-data`, message);
|
|
11569
11600
|
}
|
|
11601
|
+
else {
|
|
11602
|
+
log(`${streamType} received unknown message type: ${JSON.stringify(message)}`, { type: 'debug' });
|
|
11603
|
+
}
|
|
11570
11604
|
}
|
|
11571
11605
|
});
|
|
11572
11606
|
ws.on('close', () => {
|
|
@@ -11574,9 +11608,12 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11574
11608
|
if (streamType === 'stock') {
|
|
11575
11609
|
this.stockWs = null;
|
|
11576
11610
|
}
|
|
11577
|
-
else {
|
|
11611
|
+
else if (streamType === 'option') {
|
|
11578
11612
|
this.optionWs = null;
|
|
11579
11613
|
}
|
|
11614
|
+
else {
|
|
11615
|
+
this.cryptoWs = null;
|
|
11616
|
+
}
|
|
11580
11617
|
// Optional: implement reconnect logic
|
|
11581
11618
|
});
|
|
11582
11619
|
ws.on('error', (error) => {
|
|
@@ -11584,8 +11621,23 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11584
11621
|
});
|
|
11585
11622
|
}
|
|
11586
11623
|
sendSubscription(streamType) {
|
|
11587
|
-
|
|
11588
|
-
|
|
11624
|
+
let ws;
|
|
11625
|
+
let subscriptions;
|
|
11626
|
+
if (streamType === 'stock') {
|
|
11627
|
+
ws = this.stockWs;
|
|
11628
|
+
subscriptions = this.stockSubscriptions;
|
|
11629
|
+
}
|
|
11630
|
+
else if (streamType === 'option') {
|
|
11631
|
+
ws = this.optionWs;
|
|
11632
|
+
subscriptions = this.optionSubscriptions;
|
|
11633
|
+
}
|
|
11634
|
+
else {
|
|
11635
|
+
ws = this.cryptoWs;
|
|
11636
|
+
subscriptions = this.cryptoSubscriptions;
|
|
11637
|
+
}
|
|
11638
|
+
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})`, {
|
|
11639
|
+
type: 'debug',
|
|
11640
|
+
});
|
|
11589
11641
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
11590
11642
|
const subMessagePayload = {};
|
|
11591
11643
|
if (subscriptions.trades.length > 0) {
|
|
@@ -11602,8 +11654,16 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11602
11654
|
action: 'subscribe',
|
|
11603
11655
|
...subMessagePayload,
|
|
11604
11656
|
};
|
|
11605
|
-
|
|
11657
|
+
const messageJson = JSON.stringify(subMessage);
|
|
11658
|
+
log(`Sending ${streamType} subscription: ${messageJson}`, { type: 'info' });
|
|
11659
|
+
ws.send(messageJson);
|
|
11606
11660
|
}
|
|
11661
|
+
else {
|
|
11662
|
+
log(`No ${streamType} subscriptions to send (all arrays empty)`, { type: 'debug' });
|
|
11663
|
+
}
|
|
11664
|
+
}
|
|
11665
|
+
else {
|
|
11666
|
+
log(`Cannot send ${streamType} subscription: WebSocket not ready`, { type: 'warn' });
|
|
11607
11667
|
}
|
|
11608
11668
|
}
|
|
11609
11669
|
connectStockStream() {
|
|
@@ -11616,6 +11676,11 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11616
11676
|
this.connect('option');
|
|
11617
11677
|
}
|
|
11618
11678
|
}
|
|
11679
|
+
connectCryptoStream() {
|
|
11680
|
+
if (!this.cryptoWs) {
|
|
11681
|
+
this.connect('crypto');
|
|
11682
|
+
}
|
|
11683
|
+
}
|
|
11619
11684
|
disconnectStockStream() {
|
|
11620
11685
|
if (this.stockWs) {
|
|
11621
11686
|
this.stockWs.close();
|
|
@@ -11626,8 +11691,38 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11626
11691
|
this.optionWs.close();
|
|
11627
11692
|
}
|
|
11628
11693
|
}
|
|
11694
|
+
disconnectCryptoStream() {
|
|
11695
|
+
if (this.cryptoWs) {
|
|
11696
|
+
this.cryptoWs.close();
|
|
11697
|
+
}
|
|
11698
|
+
}
|
|
11699
|
+
/**
|
|
11700
|
+
* Check if a specific stream is connected
|
|
11701
|
+
* @param streamType - The type of stream to check
|
|
11702
|
+
* @returns True if the stream is connected
|
|
11703
|
+
*/
|
|
11704
|
+
isStreamConnected(streamType) {
|
|
11705
|
+
if (streamType === 'stock') {
|
|
11706
|
+
return this.stockWs !== null && this.stockWs.readyState === WebSocket.OPEN;
|
|
11707
|
+
}
|
|
11708
|
+
else if (streamType === 'option') {
|
|
11709
|
+
return this.optionWs !== null && this.optionWs.readyState === WebSocket.OPEN;
|
|
11710
|
+
}
|
|
11711
|
+
else {
|
|
11712
|
+
return this.cryptoWs !== null && this.cryptoWs.readyState === WebSocket.OPEN;
|
|
11713
|
+
}
|
|
11714
|
+
}
|
|
11629
11715
|
subscribe(streamType, subscriptions) {
|
|
11630
|
-
|
|
11716
|
+
let currentSubscriptions;
|
|
11717
|
+
if (streamType === 'stock') {
|
|
11718
|
+
currentSubscriptions = this.stockSubscriptions;
|
|
11719
|
+
}
|
|
11720
|
+
else if (streamType === 'option') {
|
|
11721
|
+
currentSubscriptions = this.optionSubscriptions;
|
|
11722
|
+
}
|
|
11723
|
+
else {
|
|
11724
|
+
currentSubscriptions = this.cryptoSubscriptions;
|
|
11725
|
+
}
|
|
11631
11726
|
Object.entries(subscriptions).forEach(([key, value]) => {
|
|
11632
11727
|
if (value) {
|
|
11633
11728
|
currentSubscriptions[key] = [...new Set([...(currentSubscriptions[key] || []), ...value])];
|
|
@@ -11636,7 +11731,16 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11636
11731
|
this.sendSubscription(streamType);
|
|
11637
11732
|
}
|
|
11638
11733
|
unsubscribe(streamType, subscriptions) {
|
|
11639
|
-
|
|
11734
|
+
let currentSubscriptions;
|
|
11735
|
+
if (streamType === 'stock') {
|
|
11736
|
+
currentSubscriptions = this.stockSubscriptions;
|
|
11737
|
+
}
|
|
11738
|
+
else if (streamType === 'option') {
|
|
11739
|
+
currentSubscriptions = this.optionSubscriptions;
|
|
11740
|
+
}
|
|
11741
|
+
else {
|
|
11742
|
+
currentSubscriptions = this.cryptoSubscriptions;
|
|
11743
|
+
}
|
|
11640
11744
|
Object.entries(subscriptions).forEach(([key, value]) => {
|
|
11641
11745
|
if (value) {
|
|
11642
11746
|
currentSubscriptions[key] = (currentSubscriptions[key] || []).filter(s => !value.includes(s));
|
|
@@ -11646,7 +11750,16 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
11646
11750
|
action: 'unsubscribe',
|
|
11647
11751
|
...subscriptions,
|
|
11648
11752
|
};
|
|
11649
|
-
|
|
11753
|
+
let ws;
|
|
11754
|
+
if (streamType === 'stock') {
|
|
11755
|
+
ws = this.stockWs;
|
|
11756
|
+
}
|
|
11757
|
+
else if (streamType === 'option') {
|
|
11758
|
+
ws = this.optionWs;
|
|
11759
|
+
}
|
|
11760
|
+
else {
|
|
11761
|
+
ws = this.cryptoWs;
|
|
11762
|
+
}
|
|
11650
11763
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
11651
11764
|
ws.send(JSON.stringify(unsubMessage));
|
|
11652
11765
|
}
|