Skip to content

Ibkr Ws Client

voyz edited this page Apr 26, 2024 · 21 revisions

IbkrWsClient

The IbkrWsClientclass provides an interface to the IBKR WebSocket API.

IbkrWsClient is a concrete implementation of the WsClient abstract base class, which is a collection of functionalities that facilitate connecting to a WebSocket API:

  • Threading - managing the lifecycle of the WebSocket processing thread.
  • Connection - taking care of establishing and re-establishing the WebSocket connection
  • Subscriptions - managing WebSocket channel subscriptions and distributing messages accordingly
  • Queues - providing an asynchronous interface to consume the data received

On top of these base functionalities, the IbkrWsClient implements message processing and connectivity handling specific to the IBKR WebSocket API.

Using IbkrWsClient

Using the IbkrWsClient involves handling three areas:

  • Managing its lifecycle. It is asynchronous and it will run on a separate thread, hence we need to construct it, start it and then manage its lifecycle on the originating thread.
  • Subscribing and unsubscribing. It is subscription-based, hence we need to specify which channels we want to subscribe to and remember to unsubscribe later.
  • Consuming data. It uses a queue system, hence we need to access these queues and consume their data.

Managing the Lifecycle

We construct the IbkrWsClient as follows:

from ibind import IbkrClient, IbkrWsClient, ibind_logs_initialize

ibind_logs_initialize()

client = IbkrClient()
ws_client = IbkrWsClient(ibkr_client=client)

Note that we pass an instance of IbkrClient class as an argument. This is due to the fact that IBKR WebSocket API requires us to utilise the tickle REST endpoint in order to authenticate when connecting. IbkrWsClient uses the IbkrClient to handle this automatically.

Having done that, we can manage the IbkrWsClient's lifecycle:

ws_client.start()
print(ws_client.running) # True

ws_client.shutdown()
print(ws_client.running) # False

Outputs:

2024-04-26 17:02:34,248|I| IbkrWsClient: Starting
2024-04-26 17:02:34,248|I| IbkrWsClient: Trying to connect
2024-04-26 17:02:36,344|I| IbkrWsClient: Connection open
True
2024-04-26 17:02:36,359|I| IbkrWsClient: Shutting down
2024-04-26 17:02:36,365|I| IbkrWsClient: on_close
2024-04-26 17:02:36,366|I| IbkrWsClient: Connection closed
2024-04-26 17:02:36,366|I| IbkrWsClient: Gracefully stopped
False

Subscribing and Unsubscribing

Interacting with the IBKR WebSocket channels involves sending an appropriate string payloads. These usually:

  • Start with s for subscription and u for unsubscription, eg. smd and umd.
  • Have a two-letter channel identifier, eg. md for market data.
  • Have additional arguments defined after a + plus symbol, eg. smd+conid+...

IbkrWsClient handles these three items distinctly when either subscribing or unsubscribing:

  • Adding the s and u prefix is handled automatically when either subscribe or unsubscribe methods are called.
  • The channel identifier - referred to as the channel - needs to be provided as the first argument.
  • Additional payload arguments - referred to as the data - can be passed as the second argument.

Live Order Updates example

For example, in order to subscribe to the Live Order Updates, the documentation indicates that we need to send the following message:

sor+{}

This translates to:

  • The 's' prefix is expected.
  • The channel is 'or'.
  • There is no additional arguments that we would provide through data.

We subscribe to this channel using IbkrWsClient in the following fashion:

ws_client.subscribe(channel='or', data=None, needs_confirmation=False)

Trades Data example

Let's look at another example, this time subscribing to the Trades Data channel which accepts additional arguments:

str+{
    "realtimeUpdatesOnly":realtimeUpdatesOnly, 
    "days":days
}

This translates to:

  • The 's' prefix is expected.
  • The channel is 'tr'.
  • We can pass data dictionary containing realtimeUpdatesOnly and days fields.

We subscribe to this channel using IbkrWsClient in the following fashion:

ws_client.subscribe(channel='or', data={'realtimeUpdatesOnly': True, 'days': 5}, needs_confirmation=False)

Note that the subscribe method accepts needs_confirmation parameter (True by default). It indicates whether the client should expect a confirmation from the API, which is used to aid the subscriptions' lifecycle management.

IBKR WebSocket API sends information back directly after subscribing - but only for some of its channels. Hence we can set needs_confirmation=False when subscribing to channels that don't send any confirmation.

Contrarily, for channels that do provide a confirmation, IbkrWsClient will expect that confirmation and attempt to re-subscribe if the confirmation is not received. Some channels in fact require two subscription requests to be sent before starting to send data, which is also facilitated by this confirmation and re-attempt functionality.

Consuming Data

Advanced WebSocket Functionalities

Advanced Lifecycle Management

Advanced Subscribing and Unsubscribing