feat(1.0): IBKR mock + IbTwsClient (ib_insync), tests#55
Conversation
- In-memory IBKR-style client: connect/disconnect, account summary tags, positions, MKT/LMT orders, optional market auto-fill, last-price test hooks - tests/brokers/test_ibkr_mock.py - trading_system.version and README/package.json bumped to 1.0.0 - Export __version__ from trading_system Made-with: Cursor
- IbTwsClient: connect to TWS (7496 paper / 7497 live), account values, positions, limit order, cancel by id - Event-loop bootstrap for ib_insync/eventkit on Python 3.10+ - Lazy-export IbTwsClient from brokers package to avoid import cost for mock-only - tests: unittest.mock for read/write; optional live tests (TWS_INTEGRATION, TWS_PLACE_ORDER) - requirements: ib_insync; pytest marker integration; README TWS section Made-with: Cursor
Made-with: Cursor
Code Review — PR #55Overall: Clean addition of an IBKR mock client and a live TWS client via Issues
Strengths
Generated by Claude Code |
Redundancy Review — PR #55Focused follow-up on redundant code patterns in this PR and across open branches. Within this PR
Cross-PR redundancy (branches #32, #53, #55)
RecommendationStart by extracting Generated by Claude Code |
|
Stale — 19 days, no commits since Apr 22. Two prior reviews identified a runtime bug ( Redundancy triage (this PR + open branches)The redundancy review from May 4 still stands — key items to resolve before merging:
Please fix the Generated by Claude Code |
IamJasonBian
left a comment
There was a problem hiding this comment.
Stale — clean broker adapters, minor code duplication to fix.
The MockIbkrClient and IbTwsClient are well-structured. The lazy import pattern in __init__.py is a nice touch. Two cleanup items:
- Shared
Actiontype alias — defined identically in both broker files. Extract to one place. - Simplify
_ensure_event_loop— the nested try/except is redundant (see inline). - Version bump to 1.0.0 is mixed into this broker PR (
version.py,package.json, README). Consider separating the version bump into its own commit or PR — it signals a release milestone that's broader than "added IBKR broker adapters."
The MockIbkrClient is 231 lines — consider whether place_market_order and _fill_market could share more logic with place_limit_order via a common _submit_order helper (saves ~20 lines of repeated dict construction).
Generated by Claude Code
|
|
||
|
|
||
| Action = Literal["BUY", "SELL"] | ||
|
|
There was a problem hiding this comment.
Duplicate type alias — share with ib_tws_client.py.
Action = Literal["BUY", "SELL"] is defined identically in both ibkr_mock.py and ib_tws_client.py. Move it to brokers/__init__.py (or a shared brokers/types.py) and import from there. One definition to maintain instead of two.
Generated by Claude Code
| # ib_insync / eventkit expect a main-thread event loop; Python 3.10+ may not | ||
| # create one on import, which breaks their module init. | ||
| def _ensure_event_loop() -> None: | ||
| try: |
There was a problem hiding this comment.
_ensure_event_loop has a redundant fallback path.
On Python 3.10+, get_event_loop() in a thread without a running loop raises RuntimeError (or emits a deprecation warning and creates one, depending on version). The inner try/except is effectively the same as the outer one. Simplify to:
def _ensure_event_loop() -> None:
try:
asyncio.get_running_loop()
except RuntimeError:
asyncio.set_event_loop(asyncio.new_event_loop())This is clearer and handles all Python versions correctly — if there's a running loop, do nothing; otherwise create one.
Generated by Claude Code
Context
allocation-engine 1.0.0 adds broker-style plumbing: an offline mock and a real TWS / IB Gateway client (paper or live socket).
What was added
Offline
trading_system/brokers/ibkr_mock.py—MockIbkrClient: in-memory account tags, positions, MKT/LMT/canceltests/brokers/test_ibkr_mock.pyLive TWS (
ib_insync)trading_system/brokers/ib_tws_client.py—IbTwsClient/TwsClientConfig: connect, account values, positions, limit order, cancel by idrequirements.txt:ib_insynctrading_system/brokers/__init__.pyso mock-only imports stay cheap; event-loop bootstrap for Python 3.10+ /eventkittests/brokers/test_ib_tws_client_mocked.py— mocked read/write (no TWS)tests/brokers/test_ib_tws_live.py— optional live tests (TWS_INTEGRATION=1, optionalTWS_PLACE_ORDER=1on paper 7496 only)Note:
IbTwsClientcurrently exposes limit orders only (noMarketOrderwrapper). To trigger an immediate-style buy you either use a limit near the last price, extend the client withib_insync.MarketOrder, or drive MockIbkrClient for simulation.Version
trading_system/version.py,package.json, README 1.0.0; README Interactive Brokers (TWS API) sectionpytest.ini:integrationmarkerVerified
pytest tests/brokers/test_ibkr_mock.py— passpytest tests/brokers/test_ib_tws_client_mocked.py— passTWS_INTEGRATION=1 pytest tests/brokers/test_ib_tws_live.pywith TWS API enabledNote: full repo
pytest tests/may still have unrelated failures; broker tests are isolated.If a buy order does not trigger or submit (TWS / API)
Work through these in order; the TWS log (View → Message Log or API messages) often states the exact rejection reason.
Read-Only mode: false— keep it that way for orders)client_idper concurrent connection. If a stale Python process holds the id, TWS can reject; pick another (e.g. setTWS_CLIENT_IDin the live test env) or close the other appplace_limit_ordermust qualify the contract (qualifyContracts). If the symbol fails, check SMART vs required primary exchange, USDcurrencyfor US equities, and that the symbol exists (no typo)MarketOrderpath in code or place a limit at/through the last price and watch for a fillOrderif you add market/limit with extended hoursIbTwsClientdoes not yet wire intoExecutor/SafeCashBot; production buy paths still go through Robinhood in the rest of the repo. To “trigger a buy” from the trading engine you need a follow-up: injectIbTwsClient(or a shared protocol) into execution and mapTradeTask→place_limit_order/MarketOrderScreenshots (last two, 2026-04-22)
On-disk copies are in
docs/pr-55-attachments/on this branch (filenames:ibkr-tws-1.png,ibkr-tws-2.png).1. Gateway / TWS startup (04:19) — usfarm connect thread,
ndc1.ibllc.com:4000, first hop64.190.197.40, SSL on.2. API stream (04:22) — market/HMDS/secdef farms OK;
AccountCodeU24673021,AccountReadytrue,AccountTypeINDIVIDUAL, accrued fields 0.00 (BASE/USD) at capture time.Debug
If anything above blocks you, paste the exact message from TWS (order rejection / API) on the next PR and we can map it to a code or config change.