What drop-in means
The promise is the one an ib_async user would ask for: an existing program
changes its import and its connect line, and nothing else. The connect line
gains credentials, or, for a paper account, stays as it was where
IB_USERNAME and IB_PASSWORD are set, because nothing local is addressed:
then only the import changes, as a gateway keeps its login in its own
settings. A live account adds paper=False.
- from ib_async import IB, Stock
+ from ib_async_dx import IB, Stock
ib = IB()
- ib.connect("127.0.0.1", 4001, clientId=1) # a gateway on localhost
+ ib.connect(username="...", password="...") # a paper session; paper=False for live
What the import gives
ib_async_dx is ib_async. It exports ib_async’s __all__, all 103 names, and
every one of them is ib_async’s own object — the same class, the same function,
the same enum, the same __version__ — except two:
IB, a subclass ofib_async.IB. ItsconnectandconnectAsyncput the engine in place of ib_async’sClientand then run ib_async’s own connect. Everything else on it is ib_async’s, apart from the four bug fixes and the added calls.IBC, a subclass ofib_async.IBCwith no gateway to launch: starting it holds the login it names for the connects made in the same context, and terminating it ends every session that login opened. ib_async’s ownWatchdog, handed one, connects itsIBwith that login and connects it again when the session ends (Limits has the detail).
Client is ib_async’s own socket client, re-exported unchanged like every
other name: a program that builds one itself still addresses a gateway. IB
is what runs on the engine.
__version__ and __version_info__ are ib_async’s, so a program that checks
the API level it runs on reads what it always did. This package’s own version
is __ib_async_dx_version__.
ib_async’s submodules resolve here as themselves, so both import forms work:
import ib_async_dx.order and from ib_async_dx.util import df.
ib_async_dx.ib is ib_async’s ib module with IB replaced, and
ib_async_dx.ibcontroller its ibcontroller module with IB and IBC
replaced. Because the objects are ib_async’s own, isinstance checks, pickles
and a module that still imports Stock from ib_async all agree with the rest
of the program.
The connect line
connect is ib_async’s signature, with its parameters and defaults, and four
keyword-only parameters after them: username, password, paper and
sessionFile. Getting started
writes it out.
hostandportare accepted and not used. The port does not choose paper or live: the session is paper unlesspaper=False.clientIdis carried into the login, where it keys this session’s orders. One program per login: a second program on the same login takes the session from the first.usernameandpassword, left empty, are anIBC’s login where one was started in the same context, and otherwiseIB_USERNAMEandIB_PASSWORD.readonly=Truemakes a read-only session, which refuses to send anything that places, changes or withdraws an order, as a gateway set to read-only does.timeoutbounds each request ib_async makes as the session opens, as it does against a gateway. It does not bound the login, which a gateway also makes before a program connects, nor the engine’s wait of up to three seconds, inside the login, for the venue to name the working orders: a live login waits on its second factor for as long as the engine allows.
The rest is ib_async’s own connect: as it does against a gateway, it asks for
the account’s values, its positions, its open and completed orders and its
executions, as fetchFields says.
How it is proven
The package against ib_async, on every run.
test_the_package_is_ib_async.py checks that ib_async_dx.__all__ equals
ib_async’s and that every name in it is ib_async’s own object but IB and
IBC, __version__ among them; that all 13 of ib_async’s submodules resolve
under both import forms; that IB and IBC are subclasses of ib_async’s; and
that connect and connectAsync are ib_async’s parameters, defaults and kinds
with the four keyword-only ones after them. That is the parity check: a name ib_async adds
to __all__, or a change to its connect, fails here before it reaches a
program.
Against ib_async’s own source, on every run.
test_every_call_their_library_makes_is_carried reads every call ib_async’s
IB makes on its client out of ib_async’s installed source — 67 at 2.1.0 — and
fails if any one of them does not land on the engine. It is not a list kept by
hand, so a call ib_async adds is a failing test here rather than a program that
stops. And test_a_raw_message_is_the_request_it_names.py runs each of the 80
requests ib_async’s client writes as a message, through its own send, and
checks that each reads back into the message it was and reaches the engine
exactly as the same request made by name.
Against ib_async’s own tests. tests/ib_async_upstream/conftest.py runs
ib_async’s test suite against the engine instead of against a gateway: their
shared ib fixture is an ib_async_dx.IB, connected with the login in the
environment, and so is the ib_async.IB() a test builds for itself. The suite
is theirs, fetched from their repository rather than copied into this one. It
has not been run against the venue at this revision; what each of its three
tests asks, and how to run them, is in
Running ib_async itself.
Against the venue. Two tests take a live login, each with ib_async’s own
IB attached. One runs an unmodified ib_async program — connect, qualify,
bars, quotes through pendingTickersEvent. The other takes an order through
its whole life in ib_async’s objects: priced as a what-if, placed, changed and
withdrawn. Both are skipped where IB_USERNAME and IB_PASSWORD are not set,
and neither has been run against the venue at this revision. The scripts under
scripts/ do the same through ib_async_dx.IB against a paper account, and
the notebooks do it a cell at a time. Neither has been run
against the venue through ib_async_dx.IB yet, so Evidence
rates both paths ✅ Offline.
What crosses, offline. The other 316 tests need no session: that a
combination keeps its legs on every request path, that a fill’s cost reaches
ib_async as its own CommissionReport, that a refused order reaches its
Trade, that connect takes its login from the environment or an IBC and
is paper unless told otherwise, that a session opens and closes once, on the
program’s loop, however a connect is cancelled, overtaken or failed, and that
each bug fix answers what ib_async 2.1 does not.
Evidence lists what they cover.
In Rust
Coming: ib_async’s model and names, in Rust spelling, on the engine’s public API. It is not in this repository yet.