Handle unknown order statuses in `.ib.broker`

Add fallback handling for unknown IB order status strings to
avoid crashes when IB returns unexpected status values.

Deats,
- add `'ValidationError': 'error'` mapping to `_statuses` dict.
- use `.get()` with `'error'` default instead of direct dict
  lookup for `status.status`.
- add `elif status_str == 'error'` block to log unknown status
  values.
- add type annots to `event_name` and `item` in
  `deliver_trade_events()` loop.

Also,
- reformat log msg in `deliver_trade_events()` to multiline.
- drop extra conditional in `if status_str == 'filled'` check.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
ib_async
Gud Boi 2026-02-26 17:46:54 -05:00
parent 9e2af2838f
commit 9247746a79
1 changed files with 26 additions and 5 deletions

View File

@ -991,6 +991,9 @@ _statuses: dict[str, str] = {
# TODO: see a current ``ib_insync`` issue around this:
# https://github.com/erdewit/ib_insync/issues/363
'Inactive': 'pending',
# XXX, uhh wut the heck is this?
'ValidationError': 'error',
}
_action_map = {
@ -1063,8 +1066,19 @@ async def deliver_trade_events(
# TODO: for some reason we can receive a ``None`` here when the
# ib-gw goes down? Not sure exactly how that's happening looking
# at the eventkit code above but we should probably handle it...
event_name: str
item: (
Trade
|tuple[Trade, Fill]
|CommissionReport
|IbPosition
|dict
)
async for event_name, item in trade_event_stream:
log.info(f'Relaying `{event_name}`:\n{pformat(item)}')
log.info(
f'Relaying {event_name!r}:\n'
f'{pformat(item)}\n'
)
match event_name:
case 'orderStatusEvent':
@ -1075,11 +1089,12 @@ async def deliver_trade_events(
trade: Trade = item
reqid: str = str(trade.order.orderId)
status: OrderStatus = trade.orderStatus
status_str: str = _statuses[status.status]
status_str: str = _statuses.get(
status.status,
'error',
)
remaining: float = status.remaining
if (
status_str == 'filled'
):
if status_str == 'filled':
fill: Fill = trade.fills[-1]
execu: Execution = fill.execution
@ -1110,6 +1125,12 @@ async def deliver_trade_events(
# all units were cleared.
status_str = 'closed'
elif status_str == 'error':
log.error(
f'IB reported error status for order ??\n'
f'{status.status!r}\n'
)
# skip duplicate filled updates - we get the deats
# from the execution details event
msg = BrokerdStatus(