ib_async: port to the new fork of ib_insync #77

Merged
goodboy merged 16 commits from ib_async into main 2026-03-11 21:04:54 +00:00

Finally putting this up 😎

Should mostly resolve, #68


Still todo,

Any lingering todos from #68,

  • (fe207a69) move to aeventkit from the same forked lib set.
  • (f78362b2) the IB.qualifyContractsAsync() method now offers a returnAll: bool which solves an issue i’ve seen with various so called “ambiguous” contract queries,
    • (6834dd4c) started expecting a cons: list[Contract].
    • (f78362b2) specifically is tested to handle futes contracts!
  • (adf1b18d) handles str-errors that they’ll sometimes oddly send now??
  • (6f828ca3) better handle unknown order statuses..
  • (ca9b1f80) remapping non-std exchange names/keys.
    • (5ff1a9ca) also ensures we use both Contract.exchange/.primaryExchange when one is null..
  • improvements to the “data reset hack” stuff in .ib._util namely handling what appears to be a more reliably popping up “Are you sure you want to??” dialog box which i’ve now handled with tweaks to,
    • (8620c0fd) keyboard inputs to tab to the OK button and hit Enter
    • (d5da993b) slightly diff y-dim placement to hopefully mouse over the box when it appears.
  • there’s an outstanding symbol search issue (which i discovered was still there when we were on ib_insync that i’ve deferred to,

Additional improvements,

  • (e3052ad3) uses platformdirs (introed for macos_support in tractor anyway) to re-implement piker.config.get_app_dir(), removing our janky original copy of the click helper.
  • various backfiller related edge case handlings,
    • (025d3573) Handle valid null frames and 0-bar cases in backfill
    • (1fa68181) Warn instead of raise on start_dt-trimmed frames
    • (4d394a18) Drop bp from duration mismatch branch in .ib.api.Client.bars()
  • (bfe349f8) Use ppfmt() in order_mode since it’s provided by tractor now!
Finally putting this up 😎 Should mostly resolve, https://pikers.dev/pikers/piker/issues/68 --- ### Still todo, Any lingering todos from #68, - [x] (fe207a69) move to `aeventkit` from the same forked lib set. - [x] (f78362b2) the `IB.qualifyContractsAsync()` method now offers a `returnAll: bool` which solves an issue i've seen with various so called "ambiguous" contract queries, * (6834dd4c) started expecting a `cons: list[Contract]`. * (f78362b2) specifically is tested to handle futes contracts! - [x] (adf1b18d) handles `str`-errors that they'll sometimes oddly send now?? - [x] (6f828ca3) better handle unknown order statuses.. - [x] (ca9b1f80) remapping non-std exchange names/keys. * (5ff1a9ca) also ensures we use both `Contract.exchange/.primaryExchange` when one is null.. - [x] improvements to the "data reset hack" stuff in `.ib._util` namely handling what appears to be a more reliably popping up "Are you sure you want to??" dialog box which i've now handled with tweaks to, - (8620c0fd) keyboard inputs to tab to the `OK` button and hit `Enter` - (d5da993b) slightly diff y-dim placement to hopefully mouse over the box when it appears. - [x] there's an outstanding symbol search issue (which i discovered was still there when we were on `ib_insync` that i've deferred to, * https://www.pikers.dev/pikers/piker/issues/85 * (31bf5f55) adds better server-side logging for tracing the results for the search query, though we need to do this inside `.ib.api.Client` meths next to figure out wtf is up.. --- ### Additional improvements, - [x] (e3052ad3) uses `platformdirs` (introed for `macos_support` in `tractor` anyway) to re-implement `piker.config.get_app_dir()`, removing our janky original copy of the `click` helper. - [x] various backfiller related edge case handlings, * (025d3573) Handle valid null frames and 0-bar cases in backfill * (1fa68181) Warn instead of raise on `start_dt`-trimmed frames * (4d394a18) Drop bp from duration mismatch branch in `.ib.api.Client.bars()` - [x] (bfe349f8) Use `ppfmt()` in `order_mode` since it's provided by `tractor` now!
goodboy added 2 commits 2026-02-24 20:47:35 +00:00
196422433c Capture `cons` in `Client.get_fute()`
That is to be able to (eventually) introspect "ambiguous" contract sets
once we move to `ib_async` and its `returnAll: bool` now offered by
`IB.qualifyContractsAsync()`,

https://github.com/ib-api-reloaded/ib_async/blob/main/ib_async/ib.py#L2115

Also, tweak some type type annots to multline style in sibling mods.
b1cb67d1bd Port `.ib` backend from `ib_insync` to `ib_async`
Migrate the IB broker backend to use `ib_async` (the actively maintained
fork) instead of the now stale, original `ib_insync` lib.

Deats,
- update `pyproject.toml` dep: drop `ib-insync` pin, add
  `ib-async>=2.1.0`.
- update lock file with `ib-async` and its new `aeventkit` dep (which
  i guess replaces `eventkit`).
- obvi, change all `ib_insync` imports to `ib_async` across `.ib.*`.
- update docs and select internal comments referencing the original lib.

Also,
- drop unused `ledger_dict` init in `_flex_reports.load_flex_trades()`.
- fix union type annot style: `dict | None` -> `dict|None`.
- strip `.tzinfo` from `lastTimeStamp` in `normalize()` to avoid
  IPC codec issues with `ib_async`'s `timezone.utc` injection.
- pop `'defaults'` from ticker data dict in `normalize()` to avoid
  non-serializable `timezone` objects and warning-log in such
  cases.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
goodboy added 1 commit 2026-02-24 21:06:48 +00:00
goodboy added 2 commits 2026-02-26 23:01:39 +00:00
9247746a79 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
32786c5894 Remap non-std IB exhcange values
Add exchange name translation in `.ib.venues.has_holiday()` to handle
non-standard exchange codes when looking up holiday gaps..

Deats,
- add an ad-hoc lookup dict to remap an IB `Contract.primaryExchange` val
  which doesn't exist in the `exchange_calendars`'s alias set.
- use `.get()` with fallback to map `exch` to new `std_exch` and pass
  that to `xcals.get_calendar()`.
- add the case i just caught, `'ARCA'` -> `'ARCX'` to the table when i loaded
  the `gld.arca.ib` market..

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
goodboy force-pushed ib_async from 32786c5894 to ee09f519a9 2026-02-26 23:02:52 +00:00 Compare
goodboy added 7 commits 2026-03-06 14:23:10 +00:00
3adb0d8b9d Fall back to `Contract.exchange` in `has_holiday()`
Use `con.exchange` as fallback when `con.primaryExchange` is empty
in `has_holiday()` to handle contracts like futures that don't
always set a `primaryExchange`.

Deats,
- extract `con: Contract` from `con_deats.contract` for reuse.
- use `con.primaryExchange or con.exchange` to ensure a valid
  exchange code is always passed to the calendar lookup.
- add `Contract` to `TYPE_CHECKING` imports.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
19f16e1df3 Handle ambiguous futes contracts in `get_fute()`
Use (the only available in `ib_async`) `returnAll=True` in
`qualifyContractsAsync()` calls within `get_fute()` and handle the case
where IB returns a list of ambiguous contract matches instead of
a single result.

Deats,
- add `returnAll=True` to both `ContFuture` and `Future`
  qualification calls.
- add `isinstance(con, list)` check after unpacking first result
  to detect ambiguous contract sets.
- log warning with input params and matched contracts when
  ambiguous.
- update return type annot to `Contract|list[Contract]`.

Also,
- handle list-of-contracts case in `find_contracts()` by unpacking
  `*contracts` into the `qualifyContractsAsync()` call.
- reformat `qualifyContractsAsync()` calls to multiline style.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
2a394dba03 Warn instead of raise on `start_dt`-trimmed frames
Downgrade the `start_dt`-trimming check in `open_history_client()`
from a `RuntimeError` raise to a warning log, allowing the caller
to still receive a (shorter) frame of bars (though we may need to still
specially handle such cases in the backfiller's biz logic layer).

Deats,
- add `trimmed_bars.size` guard to skip check on empty results.
- change condition to `>=` and log a warning with the short-frame
  size instead of raising.
- comment-out `raise RuntimeError` and breakpoint for future
  removal once confident.
- add docstring-style comment on `start_dt=` kwarg noting that
  `Client.bars()` doesn't truly support it (uses duration-style
  queries internally).

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
ec4db30cdc Handle valid null frames and 0-bar cases in backfill
Add guards for empty-array and zero-bar-diff cases in the TSP backfill
loops to avoid crashes and allow graceful loop termination.

In `maybe_fill_null_segments()`,
- add `array.size == 0` guard in `maybe_fill_null_segments()` to detect
  valid (venue closure) gaps from the backend; add a warning + bp
  + break for this case.
- add TODO that we should likely be filling nulls with the close price
  for the gap's duration.

In `start_backfill()`,
- expand the "0 bars after diff" warning msg with
  `backfill_until_dt` and `end_dt_param` context.
- mask the  `await tractor.pause()` and add a `break` to avoid blocking
  the backfill loop.

(this commit msg was generated in some part by
[`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
89a145113c Handle `str`-errors in `.ib.broker` trade events
Add `isinstance()` dispatch for the `'error'` event case in
`deliver_trade_events()` to handle `ib_async` sometimes emitting plain
`str` error items instead of the previously expected `dict`.

Deats,
- add `isinstance(err, dict)` branch for the standard case with
  `error_code`, `reason`, and `reqid` fields.
- add `isinstance(err, str)` branch to parse error strings of the
  form `'[code 104] connection failed'` into `code` and `reason`.
- set `reqid: str = '<unknown>'` for string-form errors since
  there's no request ID available.
- update `err` type annot to `dict|str`.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
9010f9c7ab Augment `.ib.symbols` search with more logging
Refactor `open_symbol_search()` to use `partial()` for nursery task
spawning and add detailed query->results logging via `ppfmt()`.

Deats,
- change `extend_results()` to accept `target` callable +
  `pattern` + `**kwargs` and invoke inside, instead of receiving
  a pre-called awaitable; use `partial()` to pass args.
- add `ppfmt()` formatted logging of search query params and
  results including client class + method repr.
- change `print()` -> `log.exception()` for `Lagged` overrun.
- bump `upto=5` -> `upto=10` for `search_symbols()` call.

Also for styling,
- add type some missing type annots.
- add multiline style to `or` conditionals in pattern check.
- reformat log msgs to multiline style throughout.
- use `ppfmt()` for fuzzy match debug log.
- rename nursery `sn` -> `tn`.
- add TODO comment about `assert 0` hang.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
goodboy added 4 commits 2026-03-11 14:02:11 +00:00
9405d88234 Handle VNC reset-dialog in `vnc_click_hack()`
Add TAB + ENTER key presses after the `Ctrl+Alt+<key>` hotkey
combo to auto-confirm the "simulate a reset?" dialog that IB
gateway sometimes shows.

Deats,
- press `ISO_Enter` before click to dismiss any prior active
  dialog window.
- add post-hotkey loop sending `Tab` then `KP_Enter` with
  `asyncio.sleep()` delays to handle the confirmation dialog.
- add `asyncio` import.

Also,
- capture VNC connect error as `vnc_err` and log it instead of
  falling through to `try_xdo_manual()`.
- comment-out `try_xdo_manual()` fallback in VNC error path.
- reformat `client.press()` call to multiline style.
- reformat `RuntimeError` raise to multiline style with `!r`.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
e591b63985 Use `platformdirs` for `.config.get_app_dir()`
Replace hand-rolled `click`-based platform branching using
the much saner `platformdirs.user_config_path()`.

Deats,
- remove Windows/macOS/Unix `if/elif` platform dispatch
  (~25 lines) in favour of single `user_config_path()` call.
- move `_posixify()` inside `force_posix` branch since it's
  only used there.
- add `log.info()` reporting platform name and resolved dirs.

Also,
- drop now unneeded `sys` import.
- reformat `assert` in `repodir()` to multiline style.
- convert docstring from `r"""..."""` to `'''...'''` style.

(this commit msg was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code
goodboy force-pushed ib_async from e2cbc4ac27 to 0d3dbe8142 2026-03-11 19:46:12 +00:00 Compare
goodboy force-pushed ib_async from 0d3dbe8142 to d5da993b0a 2026-03-11 20:01:18 +00:00 Compare
Poster
Owner

Tested on macos as well in single-prog and daemon modes. Seems good 😎

Tested on macos as well in single-prog and daemon modes. Seems good 😎
goodboy merged commit e9879fe531 into main 2026-03-11 21:04:54 +00:00
Sign in to join this conversation.
No reviewers
No Label
No Milestone
No project
No Assignees
1 Participants
Notifications
Due Date
The due date is invalid or out of range. Please use the format 'yyyy-mm-dd'.

No due date set.

Dependencies

No dependencies set.

Reference: pikers/piker#77
There is no content yet.