Merge pull request #151 from Voyz/feat/ws_v2
feat: WebSocket client v2 (ws_v2) BREAKING CHANGE: - Subscription API no longer accepts `channel` and `data` in favour of new Pydantic `Subscription` classes which encapsulate necessary parameters for each topic, reducing ambiguity and necessity to depend on IBKR docs (as discussed in #18) - Event consumption implemented using `EventSink` protocol instead of depending on the `QueueAccessor` API. Currently implemented are `CallbackSink` (propagating events into user-specified callbacks), `QueueSink` (supporting the QueueAccessor API), `CompositeSink` (allowing to mix multiple sinks together) and `LogSink` (logging all events, useful for debugging). Custom sinks that implement `EventSink` protocal are accepted. - Events are now represented as Pydantic `WsEvent` class events, replacing propagating `dict` objects - Subscription API is now idempotent, expressing an intent that is later carried out by the client asynchronously. Behind the scenes, subscriptions are internally represented as `Binding` objects, used for managing the lifecycle of each subscription. As a result, `IbkrWsClient.subscribe()` and `IbkrWsClient.unsubscribe()` are no longer blocking and instead they return a `SubscriptionHandle` that can be waited on using `.wait()` - New threading model implemented from scratch, changing the WebSocket health and lifecycle handling - Removed `SubscriptionProcessor` class - instead `Subscription` objects define the subscribe and unsubscribe payload generation - Removed `restart_on_close` and `restart_on_critical` parameters - both are now fixed as true: the WebSocketApp will always reconnect on close, and the transport thread will always recreate a new WebSocketApp on critical. - Removed `connected`, `ready` and `running` properties - now replaced by `is_running()` and `get_state()` - Removed `IbkrWsKey` - identifying subscriptions and events now uses concrete `WsEvent` class types instead of the enum - Deprecated the `QueueAccessor` - currently still available through `QueueSink.new_queue_accessor()` for backwards compatibility. Instead `QueueSink` serves as a 1-1 replacement for `QueueAccessor`, passing appropriate queue-identifying key to its `get()` and `empty()` methods. - Minimum required Python is now 3.10 (up from 3.8) - Added `pydantic>=2.13` as a new required dependency. Also bumped `requests` from 2.31 to 2.33, `websocket-client` from 1.7 to 1.9 and (in the `oauth` extra) `urllib3` from 2.3 to 2.7 - Removed `make_order_request` - deprecated since v0.1.14 in favour of `OrderRequest` - Removed `IbkrSubscriptionProcessor` along with the base `SubscriptionProcessor` - Defaults of several WebSocket configuration variables were adjusted to the new threading model: `IBIND_WS_PING_INTERVAL` (45 -> 10), `IBIND_WS_MAX_PING_INTERVAL` (300 -> 20), `IBIND_WS_SUBSCRIPTION_RETRIES` (5 -> 20) and `IBIND_WS_SUBSCRIPTION_TIMEOUT` (2 -> 5, now denoting the interval between subsequent subscription attempts)
V
voyz committed
be892152a19fa55fdc68cf9a773dd73ebebd243b
Committed by GitHub <noreply@github.com>
on 8/30/2026, 7:36:06 AM