alpacahq / alpaca-trade-api-go

Go client for Alpaca's trade API
Apache License 2.0
325 stars 91 forks source link

How `stream.WithProcessors()` works? #240

Closed smjure closed 1 year ago

smjure commented 1 year ago

Say we have a stock client streaming trades and quotes, i.e.

c := stream.NewStocksClient(
    "sip",
    stream.WithTrades(tradeHandler, symbols...),
    stream.WithQuotes(quoteHandler, symbols...),
    stream.WithCredentials(...),
    stream.WithProcessors(1), 
)

I wonder what happens if you set stream.WithProcessors(1)? Does all messages from trades and quotes are processed via single goroutine/CPU? And what happens if you set e.g. stream.WithProcessors(4) in this case? Would it be reasonable to do something like:

    stream.WithTrades(tradeHandler, **nbProcessors**, symbols...),
    stream.WithQuotes(quoteHandler, **nbProcessors**, symbols...),
    stream.WithBars(barHandler, **nbProcessors**, symbols...),

In this way if nbProcessors=1, it could be ensured same fly-in time for trades and quotes as it comes to the server. This is also performance wise better as we can separate scripts for trades and quotes. Perhaps I am wrong? 🙏🏻

gnvk commented 1 year ago

WithProcessors configures the number of goroutines processing the messages coming from the server. Note that you don't know what a message contains (trades or quotes or both) until you actually parse it! So no, it wouldn't make sense to have separate configurations for the message types.

Personally I found little to no performance gain by increasing the processor count, as long as your message handlers are fast enough. The message unmarshaler is actually pretty fast, the benchmark runs on my machine ~1300 ns! So if you have performance issues, it's most likely coming from your handler(s), and simply parallelising may or may not solve the problem.