Login

The smallest possible IBX program: connect, wait for next_valid_id, disconnect.

Two flavors are shown below — paper for everyday testing and live for read-only validation against your real account.

Per the project rules, never send orders from a live account. Use live only for read-only checks (login, contract details).

What this shows

  • Reading credentials from environment variables.
  • Calling EClient.connect(...) with paper=True (paper) or paper=False (live).
  • Receiving next_valid_id — the signal that the session is fully established and ready for requests.

Paper

Run it

IB_USERNAME=... IB_PASSWORD=... python examples/hello_login.py

Source

"""Hello-world recipe: connect, wait for next_valid_id, disconnect.

Usage:
    IB_USERNAME=... IB_PASSWORD=... python examples/hello_login.py
"""

import os
import threading

from ibx import EClient, EWrapper


class LoginWrapper(EWrapper):
    def __init__(self):
        self.ready = threading.Event()
        self.order_id = None

    def next_valid_id(self, order_id):
        self.order_id = order_id
        self.ready.set()


w = LoginWrapper()
c = EClient(w)
c.connect(
    username=os.environ["IB_USERNAME"],
    password=os.environ["IB_PASSWORD"],
    host="cdc1.ibllc.com",
    paper=True,
)
threading.Thread(target=c.run, daemon=True).start()

if not w.ready.wait(timeout=15):
    raise RuntimeError("did not receive next_valid_id")

print(f"logged in. next_valid_id = {w.order_id}")

c.disconnect()

Live

The live login may trigger a second-factor push. Approve it on your mobile authenticator when prompted — connect() blocks until the gate clears.

Run it

IB_LIVE_USERNAME=... IB_LIVE_PASSWORD=... python examples/hello_login_live.py

Source

"""Live-account login recipe: connect with paper=False, wait for next_valid_id,
disconnect. Read-only — no orders, no market data.

When the live login triggers a second-factor push, approve it on your mobile
authenticator. The connect call blocks until the gate clears.

Usage:
    IB_LIVE_USERNAME=... IB_LIVE_PASSWORD=... python examples/hello_login_live.py
"""

import os
import threading

from ibx import EClient, EWrapper


class LoginWrapper(EWrapper):
    def __init__(self):
        self.ready = threading.Event()
        self.order_id = None

    def next_valid_id(self, order_id):
        self.order_id = order_id
        self.ready.set()


w = LoginWrapper()
c = EClient(w)
c.connect(
    username=os.environ["IB_LIVE_USERNAME"],
    password=os.environ["IB_LIVE_PASSWORD"],
    host=os.environ.get("IB_HOST", "cdc1.ibllc.com"),
    paper=False,
)
threading.Thread(target=c.run, daemon=True).start()

if not w.ready.wait(timeout=60):
    raise RuntimeError("did not receive next_valid_id")

print(f"logged in LIVE. next_valid_id = {w.order_id}")

c.disconnect()