piker/piker/brokers/ib
Gud Boi 456c6a5567 .ib.broker: lazily qualify contracts on order req
Post (datad|brokerd)-split the trading actor's
`Client._contracts` cache is never warmed by in-proc
feed setup (that now happens in the `datad.ib` sibling)
so ALL live submissions failed with "no live feed?" at
`Client.submit_limit()`; `brokerd` must be able to
submit orders without any feed registered in its own
subactor.

Deats,
- thread the acct `proxies` table into
  `handle_order_requests()` and, on a `_contracts`
  cache-miss for the req's fqme, lazily run the same
  `get_mkt_info(fqme, proxy=...)` symbology ep the
  feed-side uses; it writes the `mkt.bs_fqme` key
  `submit_limit()` looks up (and warms `_cons2mkts`
  which the position-audit path also needs) on exactly
  the same aio `Client` instance.
- guard `submit_limit()` w/ a try/except ->
  `BrokerdError` relay so a single bad submission
  degrades to an EMS error msg instead of crashing the
  dialog (and causing the `TrioTaskExited` teardown
  storm seen in testing).
- fix the (non-f-string..) raise msg in
  `Client.submit_limit()` and doc the new lazy-qualify
  contract; the bug was foretold by the TODO in
  `.symbols.get_mkt_info()` B)

(this patch was generated in some part by [`claude-code`][claude-code-gh])
[claude-code-gh]: https://github.com/anthropics/claude-code

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Prompt-IO: ai/prompt-io/claude/20260610T213549Z_f084e899_prompt_io.md
2026-06-10 17:36:51 -04:00
..
README.rst Port `.ib` backend from `ib_insync` to `ib_async` 2026-03-11 15:51:41 -04:00
__init__.py Declare per-daemon-kind backend mod groups 2026-06-10 13:11:42 -04:00
_flex_reports.py Port `.ib` backend from `ib_insync` to `ib_async` 2026-03-11 15:51:41 -04:00
_util.py Tweak y-move to `400` to align better with reset-dialog box 2026-03-11 15:51:41 -04:00
api.py .ib.broker: lazily qualify contracts on order req 2026-06-10 17:36:51 -04:00
broker.py .ib.broker: lazily qualify contracts on order req 2026-06-10 17:36:51 -04:00
feed.py Swap `open_channel_from()` yield-pair order 2026-03-17 15:06:30 -04:00
ledger.py Fall back to `con.exchange` in IB ledger fill loop 2026-04-16 13:30:00 -04:00
symbols.py Augment `.ib.symbols` search with more logging 2026-03-11 15:51:41 -04:00
venues.py Harden `.ib.venues` against unknown exchange cals 2026-03-24 20:21:29 -04:00

README.rst

ib backend

more or less the "everything broker" for traditional and international markets. they are the "go to" provider for automatic retail trading and we interface to their APIs using the ib_async project.

status

current support is production grade and both real-time data and order management should be correct and fast. this backend is used by core devs for live trading.

currently there is not yet full support for: - options charting and trading - paxos based crypto rt feeds and trading

config

In order to get order mode support your brokers.toml needs to have something like the following:

[ib]
hosts = [
 "127.0.0.1",
]
# TODO: when we eventually spawn gateways in our
# container, we can just dynamically allocate these
# using IBC.
ports = [
    4002,
    4003,
    4006,
    4001,
    7497,
]

# XXX: for a paper account the flex web query service
# is not supported so you have to manually download
# and XML report and put it in a location that can be
# accessed by the ``brokerd.ib`` backend code for parsing.
flex_token = '1111111111111111'
flex_trades_query_id = '6969696'  # live accounts only?

# 3rd party web-api token
# (XXX: not sure if this works yet)
trade_log_token = '111111111111111'

# when clients are being scanned this determines
# which clients are preferred to be used for data feeds
# based on account names which are detected as active
# on each client.
prefer_data_account = [
    # this has to be first in order to make data work with dual paper + live
    'main',
    'algopaper',
]

[ib.accounts]
main = 'U69696969'
algopaper = 'DU9696969'

If everything works correctly you should see any current positions loaded in the pps pane on chart load and you should also be able to check your trade records in the file:

<pikerk_conf_dir>/ledgers/trades_ib_algopaper.toml

An example ledger file will have entries written verbatim from the trade events schema:

["0000e1a7.630f5e5a.01.01"]
secType = "FUT"
conId = 515416577
symbol = "MNQ"
lastTradeDateOrContractMonth = "20221216"
strike = 0.0
right = ""
multiplier = "2"
exchange = "GLOBEX"
primaryExchange = ""
currency = "USD"
localSymbol = "MNQZ2"
tradingClass = "MNQ"
includeExpired = false
secIdType = ""
secId = ""
comboLegsDescrip = ""
comboLegs = []
execId = "0000e1a7.630f5e5a.01.01"
time = 1661972086.0
acctNumber = "DU69696969"
side = "BOT"
shares = 1.0
price = 12372.75
permId = 441472655
clientId = 6116
orderId = 985
liquidation = 0
cumQty = 1.0
avgPrice = 12372.75
orderRef = ""
evRule = ""
evMultiplier = 0.0
modelCode = ""
lastLiquidity = 1
broker_time = 1661972086.0
name = "ib"
commission = 0.57
realizedPNL = 243.41
yield_ = 0.0
yieldRedemptionDate = 0
listingExchange = "GLOBEX"
date = "2022-08-31T18:54:46+00:00"

your pps.toml file will have position entries like,

[ib.algopaper."mnq.globex.20221216"]
size = -1.0
ppu = 12423.630576923071
bs_mktid = 515416577
expiry = "2022-12-16T00:00:00+00:00"
clears = [
 { dt = "2022-08-31T18:54:46+00:00", ppu = 12423.630576923071, accum_size = -19.0, price = 12372.75, size = 1.0, cost = 0.57, tid = "0000e1a7.630f5e5a.01.01" },
]