Skip to content

fix: IBKR contract identity + E2E improvements#82

Merged
luokerenx4 merged 6 commits intomasterfrom
dev
Mar 22, 2026
Merged

fix: IBKR contract identity + E2E improvements#82
luokerenx4 merged 6 commits intomasterfrom
dev

Conversation

@luokerenx4
Copy link
Contributor

Summary

  • Contract identity resolution moved to IBroker: Each broker now declares getNativeKey() and resolveNativeKey() — IBKR uses conId (globally unique), Alpaca uses ticker, CCXT uses unified symbol. UTA delegates to broker instead of guessing symbol/localSymbol.
  • IBKR contract defaults: placeOrder/getQuote/getContractDetails default to exchange=SMART, currency=USD when upstream layers omit them.
  • SDK fix: Clear handshake timeout on success to prevent uncaught TypeError crash.
  • E2E singleFork: All E2E files share a single process so IBKR TCP connections (clientId) don't collide.
  • getMarketClock fallback: Try TWS reqCurrentTime with 3s timeout, fall back to local time.
  • Order lifecycle tests: New limit-order place→query→cancel tests that run outside market hours for both IBKR and Alpaca.
  • conId-based aliceId: E2E tests use searchContracts + getNativeKey to build correct aliceId instead of hardcoding symbols.
  • Version bump: 0.9.0-beta.7

Test plan

  • pnpm build passes
  • pnpm test — 880 tests pass
  • pnpm test:e2e — 39 passed, 12 skipped (fill tests skip outside market hours)

🤖 Generated with Claude Code

Ame and others added 6 commits March 22, 2026 21:40
Upstream layers (staging, AI tools) construct thin contracts with only
symbol populated. TWS rejects orders/queries missing exchange and
currency. Default to SMART routing and USD — non-USD markets and forex
will need explicit currency from the caller.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
IBroker now declares getNativeKey(contract) and resolveNativeKey(key)
so each broker defines its own uniqueness semantics:
- Alpaca: ticker symbol
- CCXT: unified market symbol (ETH/USDT:USDT)
- IBKR: conId (globally unique numeric ID)

UTA's stampAliceId and stagePlaceOrder/stageClosePosition now delegate
to broker instead of guessing symbol/localSymbol. Fixes IBKR orders
being rejected due to missing secType/exchange/currency — conId alone
is sufficient for TWS to resolve the full contract.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… connections

- getMarketClock: try reqCurrentTime with 3s timeout, fallback to local
  time if TWS doesn't respond. TODO: per-contract tradingHours query.
- vitest.e2e.config: use pool=forks + singleFork so all E2E files share
  a single process. Module-level broker singletons (setup.ts) now actually
  share state — fixes IBKR clientId collision on second connection attempt.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add limit order place → query → cancel tests for IBKR and Alpaca
brokers, plus UTA-level limit order stage → push → cancel tests.
These run any time (exchanges accept limit orders outside trading
hours). Existing market order / fill tests remain under market hours
guard.

Three-tier E2E structure:
1. Connectivity — any time
2. Order lifecycle — any time (limit orders)
3. Fill + position — market hours only

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eKey

IBKR tests now discover contracts via searchContracts to get conId,
then build aliceId using broker.getNativeKey() — matching the real
AI workflow. Alpaca tests also unified to use getNativeKey for
consistency. resolveNativeKey string fallback adds secType='STK'
for legacy symbol-based aliceIds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@luokerenx4 luokerenx4 merged commit b9a2662 into master Mar 22, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant