DocumentationUnder the hood

TWS wire protocol

Updated: 2026-07-25 09:45 CEST

pkg/ibkr is a clean-room Go implementation of the TWS wire protocol. It is not a full replacement for every TWS API method; it covers the broker reads and narrow order-wire operations used by the ibkr binary and daemon.

Order and exercise gates

Unrestricted SubmitOrder/CancelOrder, PlaceOrder/CancelOrder, and ExerciseOptions methods are present in every build, but their position-changing wire paths are enabled only in trading-capable builds; default builds return pkg/ibkr.ErrTradingDisabled before writing such a frame.

The narrower SubmitPaperOrder, PlacePaperOrder, and CancelPaperOrder methods are present in both builds and validate a concrete paper account plus matching connection coordinates. That library-level evidence is not submit authority. Broker WhatIf previews are also available in both builds, but they do not create working orders and never grant submit authority.

The daemon adds trading status, pinned account/mode, preview-token, freeze, journal, broker, and origin checks; the MCP server remains preview/read-oriented and exposes no place/modify/cancel tools.

Order caps bind every equity/ETF or single-leg option order, including an apparent close or reduction. reqAllOpenOrders covers API-created orders across clients but cannot prove that a manual TWS order has not already consumed exit capacity, so sell-side apparent exits also pass the short/sell-to-open gates under worst-case exposure. If that blocks a genuine exit, use TWS and then refresh and reconcile the daemon.

The account-base unit used by those caps is exact-session authority. A completed one-shot account-summary response must identify it through the explicit currency tag or one consistent suffix from the closed allowlist of ordinary aggregate value tags; $LEDGER:ALL rows and ExchangeRate=1 are ineligible. Preview and token redemption bind the value plus provenance to the same concrete broker session. A reconnect or redemption-time change rejects the token. The first-byte guard treats the redeemed value as immutable for that session and never issues a new broker request or reparses an unstamped cache.

Purge/restore preview and submission are unconditionally unavailable until the daemon has exact per-leg portfolio and account-global working-order authority. Option-exercise preview likewise returns the typed exercise_submission_unavailable blocker and mints no token because exact option-to-underlying risk policy and durable one-shot authority are not yet approved. These disabled daemon capabilities do not become available merely because the lower-level wire method or a platform workflow setting exists.

Semantic fingerprints

Monitor-facing decision surfaces expose a semantic fingerprint object:

{"version": "canary-fp-v2", "key": "sha256:..."}

The key is a SHA-256 hash of classified state rather than of the full JSON response. It deliberately excludes timestamps, raw prices, exact observed values inside the same threshold bucket, methodology prose, row guidance text, and rendering order. Monitors should use the key for dedupe, recovery, and repeat-alert TTL policy instead of recomputing their own hash.

regime.snapshot emits regime-fp-v2 from indicator bands/statuses, composite counts, lifecycle stage/severity/readiness buckets, warning codes/scopes/severities, high-level data quality, source-health buckets, and gamma/breadth semantic state. V2 adds the allowlisted failure code/stage when a source carries typed failure evidence.

market_events.snapshot emits market-events-fp-v3 from requested symbols, semantic flag categories/statuses/severities/roles/sources, source-health buckets, and the typed identity/status of borrow-fee coverage. It excludes timestamps, exact rates/share counts, retry timing, source prose, and rendering order. V3 retains the V2 typed failure code/stage projection and adds coverage scope, exact-contract identity, source/data type, entitlement, scale status, policy eligibility, and closed reason/status buckets.

canary emits canary-fp-v2 from policy, action, market confirmation, portfolio fit, input health, direction, severity, planner mode/readiness, primary drivers, signal semantics including held-underlying stress buckets, classified market state, source-health buckets, row titles/states, and source_fingerprints.account, source_fingerprints.positions, source_fingerprints.regime, and source_fingerprints.market_events. V2 includes typed source failure code/stage. The separate established_alert_projection intentionally retains its frozen canary-fp-v1 compatibility identity for delivery continuity.

rules.snapshot emits rulebook-fp-v3, a policy-identity fingerprint rather than a classified-state hash. The key is a SHA-256 of a JSON projection of the active Rulebook model (rule set, thresholds, regime-conditional sets), so it changes when the model changes, not when verdicts move. The rules-decisions journal records the same policy_fingerprint with every transition, naming the model identity that produced each journaled verdict.

Regime also exposes a nested lifecycle.fingerprint for consumers that dedupe by broad-market lifecycle transition rather than by the full regime snapshot. Canary is stateless and exposes no lifecycle fingerprint of its own. Source fingerprints and source-health entries use semantic buckets only; timestamps, tiny raw-value movement inside a bucket, and prose changes must not churn the hash.

Market events

market_events.snapshot returns MarketEventsResult for explicit symbols or, when symbols are omitted, held stock/ETF underlyings from the positions snapshot. The result contains flags[], by_symbol, source_health[], borrow_fee_coverage[], warning_details[], fingerprint, and not_execution.

MarketEventFlag.id is one of borrow_inventory_tight, borrow_fee_extreme, reg_sho_threshold, luld_pause, or halt_regulatory_or_news. Event status uses event terms such as active and recent; source freshness uses source_health[].status values such as ok, stale, unknown, or degraded.

source_health[] may also carry durable refresh_state, next_attempt, and redacted typed last_failure fields (code, stage, failed_at, retryable). Consumers must respect backoff/not-due state and use these typed fields instead of parsing provider or transport prose from notes.

Flag sources

Borrow inventory comes from IBKR shortable-share market data. The global FTP short-stock availability file remains the primary borrow-fee source and is the only source currently eligible to emit borrow_fee_extreme at or above 50% annualized. A stale FTP last-good never emits or clears that flag.

When a regular-session FTP refresh is due but fails, is backed off, or returns unusable evidence, the daemon may request historical FEE_RATE only for exact positive-ConID stock contracts that are currently held short in a complete, fresh, same-account portfolio stream. It never resolves a symbol, invents a route, or queries a long/non-held name. borrow_fee_coverage[] discloses coverage_scope (global or portfolio_only), optional contract_con_id/contract_fingerprint, source, data_type, nullable fee_rate, as_of, observed_at, status, reason, entitlement, scale_status, policy_eligible, and a redacted typed last_failure.

Historical FEE_RATE is portfolio-only context with scale_status=unverified and policy_eligible=false until a controlled broker fixture commissions its numeric scale. It therefore cannot emit or clear the 50% flag; missing, unentitled, malformed, paced, or unavailable evidence stays nullable and explicit rather than becoming zero. Outside the FTP publication window, refresh_state=not_due suppresses the fallback. Reg SHO V1 uses Nasdaq's threshold list, so non-Nasdaq listing-exchange absence remains outside coverage. LULD and halt context comes from Nasdaq trade-halt evidence. Runtime entitlement, failure, and backoff are not restored after a restart; only the exact identical-wire 15-second retry boundary is durable.

Flags are context and safety gates, not execution authority. Active halt/LULD can block proposal preview/submit; borrow flags modify existing short buy-to-cover reductions only; reg_sho_threshold is regulatory context unless paired with an existing reduce/cover proposal.

Capability coverage

Capability Wire opcodes Library entry point Status
Account summary reqAccountSummary (62), accountSummary (63), acctValue (6) Connector.RequestAccountSummary, GetAccountSummary ready
Positions + portfolio reqPositions (61), position (61), portfolioValue (7), $LEDGER:ALL Connector.CachedPositions ready
Snapshot quote reqMktData (1) snapshot=true, tickPrice (1), tickSnapshotEnd (57) Connector.FetchMarketSnapshot ready
Streaming quote reqMktData (1) snapshot=false, tickPrice / tickSize / tickGeneric / tickString Connector.SubscribeMarketData, MarketDataSnapshot ready
Generic-tick set gen-ticks 100,101,104,106,165,221,233,236 (option volume, open interest, historical and implied vol, misc stats, mark price, RTVolume, shortable) populated into MarketData automatically ready
Contract resolution reqContractData (9), contractData (10) Connector.FetchContractDetails ready
Option chains reqSecDefOptParams (78), tickOptionComputation (21) Connector.FetchOptionExpiries, FetchOptionExpiryStrikes, OptionGreeks, OptionIV ready
Daily historical bars reqHistoricalData (20), historicalData (17), historicalDataEnd (17) Connector.FetchHistoricalDailyBars, exact-contract Connector.FetchHistoricalDailyFeeRates ready; FEE_RATE is a held-short daemon fallback and remains policy-ineligible until its scale fixture is commissioned
Market scanner reqScannerSubscription (22), reqScannerParameters (24) Connector.RunScannerSubscription, RunScannerParameters ready
Market-data type switch reqMarketDataType (59), marketDataType (58) Connector.SetMarketDataType ready
Unrestricted order placement / cancel placeOrder (3), cancelOrder (4) Connector.SubmitOrder, CancelOrder; Connection.PlaceOrder, CancelOrder disabled by default (ErrTradingDisabled); -tags trading only
Paper-gated order placement / cancel placeOrder (3), cancelOrder (4) Connector.SubmitPaperOrder, CancelPaperOrder; Connection.PlacePaperOrder, CancelPaperOrder all builds; validates paper account and connection coordinates, but does not replace application authorization
Broker WhatIf preview placeOrder (3) with WhatIf Connector.PreviewOrderWhatIf, Connection.PreviewOrderWhatIf all builds; broker evaluation that does not create a working order, never submit authority
Option exercise / lapse exerciseOptions (21) Connector.ExerciseOptions, Connection.ExerciseOptions low-level wire disabled by default (ErrTradingDisabled) and -tags trading only; daemon preview/submission remains typed-disabled with no token
API open-order snapshot reqAllOpenOrders (5) Connector.SnapshotOpenOrders, Connection.RequestAllOpenOrders all builds; covers API-created orders across clients, not manual TWS orders by itself
Real-time bars reqRealTimeBars (50) - not implemented
Market depth (L2) reqMktDepth (10), reqMktDepthL2 (13) - not implemented
Fundamental data reqFundamentalData (52) - not implemented
Wall Street Horizon earnings dates reqWshMetaData (100), reqWshEventData (102) Connector.FetchWSHEarnings ready; read-only, subscription-gated
News bulletins reqNewsBulletins (12) - not implemented
Financial Advisor (FA) reqFA (18) - not implemented
IV / option-price calculators reqCalcImpliedVolatility (54), reqCalcOptionPrice (55) - not implemented

Tests exercise handshake and parser behavior across IB Gateway server versions 100 through 203. Runtime connections reject versions below 124 and negotiate the highest supported protocol version with newer gateways.