Open ghost opened 1 year ago
Can you add a code snippet on how you connect the WebSocket and also when/how you subscribe to stuff ? It´s not intended to simply run the JS file with Node, this is not actually a binary or standalone application but rather a library which should be used in context of code. Also, the error indicates that you should only send subscriptions once the websocket is actually connected which can be determined by the "onConnect" function, eg:
function initAlpaca() {
// Setup alpaca
let alpaca = new Alpaca({
keyId: 'PK...',
secretKey: 'EQ...',
paper: true,
})
// Get websocket for stock data
const stockStream = alpaca.data_stream_v2;
// Log errors
stockStream.onError(e => console.log(e))
// Run this function to execute stuff once connected, for instance subscribe to bars etc.
stockStream.onConnect(() => {
console.log("Alpaca connected!")
stockStream.subscribeForBars(["TSLA"])
})
// Process streamed data
stockStream.onStockBar(bar => console.log(bar))
// Trigger the websocket to connect
stockStream.connect()
}
Also have the same error which is crash my application every day. Error log:
10:14:07.773 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42 Alpaca Status: connecting
Error: WebSocket is not open: readyState 0 (CONNECTING)
at WebSocket.ping (C:\www\fusion\node_modules\@alpacahq\alpaca-trade-api\node_modules\ws\lib\websocket.js:323:13)
at AlpacaStocksClient.ping (C:\www\fusion\node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\websocket.js:159:19)
at Timeout._onTimeout (C:\www\fusion\node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\websocket.js:128:18)
at listOnTimeout (node:internal/timers:559:17)
at processTimers (node:internal/timers:502:7)
10:14:19.608 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42 Alpaca Status: authenticating
10:14:19.612 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42 Alpaca Status: connected
10:14:19.819 DEBUG \fusion\libs\alpaca\src\lib\AlpacaService.ts:42 Alpaca Status: authenticated
10:14:19.821 INFO \fusion\libs\alpaca\src\lib\AlpacaService.ts:113 Alpaca Subscribe quotes
Exit...
My code:
this.alpacaClient = new Alpaca({
dataStreamUrl: 'wss://stream.data.alpaca.markets',
keyId: process.env.NX_APCA_API_KEY_ID,
secretKey: process.env.NX_APCA_API_SECRET_KEY,
paper: true,
feed: 'sip',
apiVersion: 2,
})
const websocket = this.alpacaClient.data_stream_v2
websocket.onStateChange((state) => {
this._alpacaState = state
alpacaLogger.debug('Status: ' + state)
if (state === STATE.AUTHENTICATED) {
this.subscribeQuotes()
this.subscribeTrades()
}
})
websocket.onError((err) => {
alpacaLogger.debug('Error:' + err, 'hidden')
})
websocket.onConnect(() => {
console.log('Alpaca connected!')
})
websocket.onStockQuote((quote) => {
....
})
websocket.onDisconnect(() => {
alpacaLogger.debug('Disconnected...')
})
websocket.connect()
I'm just messing around with the node_modules right now, it looks like changing this code (from "node_modules\@alpacahq\alpaca-trade-api\dist\resources\datav2\websocket.js"
in the following way resolves things. I say looks like because there are some other unchecked calls that I'm seeing, such as conn.ping()
, so probably a similar change needs to be made wherever the error comes up.
Old:
authenticate() {
const authMsg = {
action: "auth",
key: this.session.apiKey,
secret: this.session.secretKey,
};
this.conn.send(this.msgpack.encode(authMsg));
this.emit(STATE.AUTHENTICATING);
this.session.currentState = STATE.AUTHENTICATING;
}
New:
authenticate() {
const authMsg = {
action: "auth",
key: this.session.apiKey,
secret: this.session.secretKey,
};
if (this.conn.readyState == this.conn.OPEN){ // Check the socket state before calling send in case of a disconnect after the last 'open' emission
this.conn.send(this.msgpack.encode(authMsg));
this.emit(STATE.AUTHENTICATING);
this.session.currentState = STATE.AUTHENTICATING;
}
}
It seems like, somehow, the socket has disconnected between emission of the OPEN
state and the call to authenticate()
. An authenticate()
call is registered as a callback for the OPEN
state when you call connect()
.
I think there's a better way of doing this which doesn't involve constantly checking the websocket state, and instead just properly handling the disconnect instead by cancelling any pending authorization or pings or whatever else. However, I know next to nothing about this project's internals, so this is the best I have.
Is there an existing issue for this?
Current Behavior
when i run node datav2.js i got error C:\Users\User\alpaca-trade-api-js\node_modules\ws\lib\websocket.js:394
Expected Behavior
can get data stream
SDK Version I encountered this issue in
2.16.1
Steps To Reproduce
Filled out the Steps to Reproduce section?
Anything else?
No response