Request Contract Details

Resolve a symbol on a paper session: connect, call req_contract_details for AAPL, collect every matching contract, then disconnect when contract_details_end lands.

What this shows

  • Building a partial Contract (symbol + sec_type + exchange + currency).
  • Driving the callback loop on a daemon thread with EClient.run.
  • Reading con_id, primary exchange, and trading class out of the returned ContractDetails.

Run it

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

Source

"""Recipe: req_contract_details for AAPL on paper, print con_id and primary exchange.

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

import os
import threading

from ibx import EClient, EWrapper, Contract


class DetailsWrapper(EWrapper):
    def __init__(self):
        self.connected = threading.Event()
        self.rows = []
        self.done = threading.Event()

    def next_valid_id(self, order_id):
        self.connected.set()

    def contract_details(self, req_id, details):
        self.rows.append(details)

    def contract_details_end(self, req_id):
        self.done.set()

    def error(self, req_id, code, msg, advanced=""):
        if code not in (2104, 2106, 2158):
            print(f"[error] {code}: {msg}")


w = DetailsWrapper()
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.connected.wait(timeout=15):
    raise RuntimeError("connect failed")

aapl = Contract()
aapl.symbol = "AAPL"
aapl.sec_type = "STK"
aapl.exchange = "SMART"
aapl.currency = "USD"
c.req_contract_details(1, aapl)

if not w.done.wait(timeout=15):
    raise RuntimeError("contract_details_end not received")

print(f"matches: {len(w.rows)}")
for d in w.rows:
    print(f"  con_id={d.contract.con_id:>8}  "
          f"primary={d.contract.primary_exchange:<10}  "
          f"trading_class={d.contract.trading_class}")

c.disconnect()