ibkr

package
v2.8.5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 9, 2026 License: MIT Imports: 32 Imported by: 0

Documentation

Overview

Package ibkr implements a clean-room Go client for the Interactive Brokers TWS wire protocol. It connects directly to TWS or IB Gateway and does not depend on Interactive Brokers client libraries.

The low-level Connection type owns one protocol session, including the socket, handshake, request identifiers, framing, and message handlers. Most callers should use Connector, which builds on one Connection and provides lifecycle management, subscriptions, request/response helpers, and in-memory observations. Construct a Connector with NewConnector and start it with Connector.Start. Protocol coverage is purpose-driven rather than a complete implementation of every TWS API operation.

Order writes

This package transports broker requests; it does not grant trading authority. In the default build, the unrestricted Connector.SubmitOrder, Connector.CancelOrder, Connection.PlaceOrder, and Connection.CancelOrder methods, plus Connector.ExerciseOptions and Connection.ExerciseOptions, return ErrTradingDisabled before sending a position-changing frame. Building with the "trading" tag enables those raw methods.

The narrower paper-order methods are present in both build modes. They validate a caller-supplied PaperOrderGate for a concrete paper account and matching connection coordinates before writing. That validation is not a substitute for application-level authorization, preview, policy, freeze, journaling, or reconciliation controls. The Canary daemon invokes broker-write paths only in trading-capable builds and owns those additional controls; direct library users must provide an equivalent authority boundary.

Broker WhatIf previews are present in both build modes. They send a broker evaluation request that does not create a working order and report accepted, rejected, or unavailable status; a preview result never grants submit authority. Open-order snapshots are likewise reads, but cover API-created orders and do not by themselves bind manual TWS orders.

Logging

The package is silent by default. Use SetLogger to install a log/slog sink and SetLogLevel to select the minimum emitted level.

Trademark

"Interactive Brokers", "IBKR", "TWS", and "IB Gateway" are trademarks of Interactive Brokers Group, Inc. or its affiliates. They are used here only to identify the protocol. This package is not built, endorsed, or supported by Interactive Brokers.

Index

Examples

Constants

View Source
const (
	// OptionModelDataTypeLive identifies live/frozen model tick 13.
	OptionModelDataTypeLive = 1
	// OptionModelDataTypeDelayed identifies delayed model tick 83.
	OptionModelDataTypeDelayed = 3
)
View Source
const (
	HistoricalFailureNotEntitled         = "not_entitled"
	HistoricalFailureNoData              = "no_data"
	HistoricalFailurePacing              = "pacing"
	HistoricalFailureGatewayUnavailable  = "gateway_unavailable"
	HistoricalFailureContractUnavailable = "contract_unavailable"
	HistoricalFailureProtocolRejected    = "protocol_rejected"
	HistoricalFailureInvalidPayload      = "invalid_payload"
)

Historical failure categories are connector-authored classifications. They intentionally contain no broker prose and let daemon callers map failures onto their typed cross-surface contract without stringifying an error.

View Source
const (
	// OptionExerciseActionExercise asks IBKR to exercise the specified quantity.
	OptionExerciseActionExercise = 1
	// OptionExerciseActionLapse asks IBKR to let the specified quantity lapse.
	OptionExerciseActionLapse = 2
)
View Source
const (
	// OrderLifecycleEventOpenOrder identifies an openOrder callback.
	OrderLifecycleEventOpenOrder = "openOrder"
	// OrderLifecycleEventStatus identifies an orderStatus callback.
	OrderLifecycleEventStatus = "orderStatus"
	// OrderLifecycleEventExecDetails identifies an execDetails callback.
	OrderLifecycleEventExecDetails = "execDetails"
	// OrderLifecycleEventError identifies a correlated broker error synthesized by Connector.
	OrderLifecycleEventError = "error"
)
View Source
const (
	// OrderWhatIfStatusUnavailable means no broker decision was obtained.
	OrderWhatIfStatusUnavailable = "unavailable"
	// OrderWhatIfStatusAccepted means the matching callback was not classified as rejected.
	// It is preview evidence, not order acceptance, submit authority, or a working order.
	OrderWhatIfStatusAccepted = "accepted"
	// OrderWhatIfStatusRejected means the broker callback or error rejected the preview.
	OrderWhatIfStatusRejected = "rejected"
)
View Source
const OptionOpenInterestGenericTick = "101"

OptionOpenInterestGenericTick is IBKR's open-interest generic tick for option market-data subscriptions.

View Source
const OptionSubscriptionGenericTicks = "100,101,104,106"

OptionSubscriptionGenericTicks is the generic-tick list used by SubscribeOption for per-contract option market data.

Variables

View Source
var ErrAccountSummaryScopeConflict = errors.New("account summary account scope conflict")

ErrAccountSummaryScopeConflict means a one-shot account-summary request observed a row outside its expected single-account scope. The only aggregate rows admitted are the modeled per-currency fields emitted by $LEDGER:ALL. Every other blank, aggregate, or foreign row rejects the whole snapshot.

View Source
var ErrBrokerIDNamespaceConflict = errors.New("broker id namespace conflict")

ErrBrokerIDNamespaceConflict reports that an explicit broker order/WhatIf ID is still owned by an open read-only request. The broker-adjacent operation is refused before local indexing or wire send and may be retried with a newly reserved ID.

View Source
var ErrContractDetailsTimeout = errors.New("timeout waiting for contract details")

ErrContractDetailsTimeout indicates that a contract-details request did not receive its end marker before the caller's timeout. A returned result slice may still contain details received before the timeout.

View Source
var ErrContractNoDefinition = errors.New("no security definition for contract")

ErrContractNoDefinition reports that IBKR answered a contract-details request with a definition rejection rather than falling silent. It is the broker's own verdict and must stay distinguishable from ErrContractDetailsTimeout: a timeout is "no answer yet", this is "there is no such contract". It alone is not proof a contract is dead — a wedged gateway answers this for everything — so it feeds the guarded inactive candidate rather than marking directly.

View Source
var ErrIBKRUnavailable = errors.New("IBKR connection unavailable")

ErrIBKRUnavailable is returned by request methods when the connector cannot reach IBKR (gateway disconnected, connector not started). Callers serving trading-critical reads (account values, fresh quotes) should refuse rather than fall back to stale data.

View Source
var ErrOpenOrderSnapshotPoisoned = errors.New("open-order snapshot socket generation poisoned")

ErrOpenOrderSnapshotPoisoned means a reqAllOpenOrders request was sent but its uncorrelated openOrderEnd terminator was not proven on the same socket. No second request is safe on that socket generation because late callbacks could otherwise complete the wrong snapshot.

View Source
var ErrOrderWhatIfUnavailable = errors.New("order whatif unavailable")

ErrOrderWhatIfUnavailable is the package sentinel for unavailable WhatIf evaluation. PreviewOrderWhatIf currently reports this condition through an OrderWhatIfResult with Status set to OrderWhatIfStatusUnavailable and a nil error; validation failures still return non-nil errors.

View Source
var ErrSymbolInactive = errors.New("symbol marked inactive")

ErrSymbolInactive indicates IBKR has reported the contract is unavailable (e.g., delisted).

View Source
var ErrTradingDisabled = errors.New("trading disabled (pkg/ibkr is read-only by default; rebuild with -tags trading to enable order wire methods)")

ErrTradingDisabled is returned by unrestricted order-writing methods in the default build before an order frame is sent. Building with the "trading" tag enables those raw methods. The narrower paper-gated methods remain available in either build and require their separate PaperOrderGate evidence; neither build mode nor that evidence grants application-level submit authority.

Functions

func DefaultContractStoreDir

func DefaultContractStoreDir() (string, error)

DefaultContractStoreDir returns the root for the retired legacy JSON codec: $XDG_CACHE_HOME/ibkr when XDG_CACHE_HOME is set, otherwise $HOME/.cache/ibkr as resolved by os.UserHomeDir. It does not create the directory. Authority-backed stores do not use this path.

func DefaultMarketDataKeyForSymbol

func DefaultMarketDataKeyForSymbol(symbol string) string

DefaultMarketDataKeyForSymbol returns the same normalized route key used by the symbol-only subscription path after applying package routing defaults. It returns an empty string for a blank symbol.

func FxPair

func FxPair(symbol string) (base, quote string, ok bool)

FxPair parses an FX-pair symbol in either dotted (USD.JPY) or slash (USD/JPY) form. Returns the base currency, quote currency, and ok=true only when both legs are in fxMajors. Case-insensitive; trims whitespace.

Example
base, quote, ok := FxPair(" usd/jpy ")
fmt.Println(base, quote, ok)
Output:
USD JPY true

func HistoricalFeeRateUSRouteSupported

func HistoricalFeeRateUSRouteSupported(contract Contract, requireExchange bool) bool

HistoricalFeeRateUSRouteSupported restricts FEE_RATE to the embedded U.S. cash-equity calendar and a closed set of exact IBKR stock routes. When requireExchange is false, an allowlisted primary exchange may be used only as a route-resolution hint; the resolved executable exchange is validated again before HMDS admission.

func MarketDataKeyForContract

func MarketDataKeyForContract(contract Contract) string

MarketDataKeyForContract returns the normalized cache and subscription key for an explicitly routed market-data contract. An unrouted stock uses its upper-case symbol only when it has no positive ConID; routed or exact contracts join symbol, security type, exchange, primary exchange, currency, local symbol, and trading class with "|", followed by CONID for exact identities. It returns an empty string when Symbol is empty.

Example
key := MarketDataKeyForContract(Contract{
	Symbol:   "spy",
	SecType:  "STK",
	Exchange: "SMART",
	Currency: "USD",
})
fmt.Println(key)
Output:
SPY|STK|SMART||USD||

func MembersHash

func MembersHash(members []string) string

MembersHash returns the first 16 lowercase hexadecimal characters of a SHA-256 hash of members. It trims and uppercases each element before sorting, so input order, case, and surrounding whitespace do not affect the result. Duplicate elements remain significant.

func OptionMarketDataKey

func OptionMarketDataKey(underlying, expiryYMD, right string, strike float64) string

OptionMarketDataKey returns the normalized in-memory cache key used for an option contract, formatted as UNDERLYING_YYMMDDC100. Hyphens are removed from expiryYMD, only its last six digits are retained, and strike is formatted with no fractional digits.

func SetLogLevel

func SetLogLevel(level string)

SetLogLevel adjusts the active level by string ("debug"|"info"|"warn"|"error"). Unknown values default to "info".

func SetLogger

func SetLogger(l *slog.Logger)

SetLogger installs a custom slog.Logger as the sink for all messages produced by the IBKR library. Pass nil to discard output entirely.

Daemons and command-line tools should call this once at startup so library output funnels through the same handler the rest of the application uses.

func ValidateOrder

func ValidateOrder(order *IBKROrder) error

ValidateOrder performs local, basic validation of order. It requires a non-nil order, symbol, positive quantity, BUY or SELL action, and an order type, and validates the price combinations used by LMT, STP, STP LMT, TRAIL, and TRAIL LIMIT orders. If TIF is empty, ValidateOrder mutates it to "DAY".

A nil result does not mean the broker will accept the order and does not provide submit authority. Connection state, account and contract details, encoder support, application policy, and broker eligibility are checked elsewhere.

Example
order := &IBKROrder{
	Symbol:    "SPY",
	SecType:   "STK",
	Exchange:  "SMART",
	Currency:  "USD",
	Account:   "DU123456",
	Action:    "BUY",
	TotalQty:  1,
	OrderType: "LMT",
	LmtPrice:  500,
}

// ValidateOrder is local shape validation, not a broker preview and not
// submit authority.
err := ValidateOrder(order)
fmt.Println(err, order.TIF)
Output:
<nil> DAY

func WithRequestPriority added in v2.7.0

func WithRequestPriority(ctx context.Context, p RequestPriority) context.Context

WithRequestPriority returns a context whose connector requests submit on the given pacing lane. The priority travels with ctx through the connector's send paths; contexts without it submit as PriorityInteractive.

func WithSendDisposition

func WithSendDisposition(err error, disposition SendDisposition) error

WithSendDisposition attaches disposition to err without hiding its error chain. An existing typed disposition is retained because the innermost transport boundary has the most precise knowledge. Nil stays nil.

Types

type AccountBaseCurrencyProvenance

type AccountBaseCurrencyProvenance string

AccountBaseCurrencyProvenance identifies the broker evidence used to prove an account summary's base currency.

const (
	// AccountBaseCurrencyUnknown means no eligible broker field proved the base currency.
	AccountBaseCurrencyUnknown AccountBaseCurrencyProvenance = "unknown"
	// AccountBaseCurrencyExplicitTag means the dedicated Currency field supplied the value.
	AccountBaseCurrencyExplicitTag AccountBaseCurrencyProvenance = "explicit_currency_tag"
	// AccountBaseCurrencyValueSuffix means an allowlisted aggregate value suffix supplied it.
	AccountBaseCurrencyValueSuffix AccountBaseCurrencyProvenance = "account_value_suffix"
	// AccountBaseCurrencyUnitExchangeRate remains for wire/read-model
	// compatibility only. A unit exchange rate is not proof of the account's
	// base currency and accountBaseCurrencyEvidence never emits it.
	AccountBaseCurrencyUnitExchangeRate AccountBaseCurrencyProvenance = "unit_exchange_rate"
)

func (AccountBaseCurrencyProvenance) Proven added in v2.7.0

Proven reports whether a broker field established the base currency. Only these two provenances stand as evidence. Any consumer that publishes, stores, or trades on a base-currency label must gate on this rather than on a non-empty currency string: RawAccountSummary.Currency is the legacy numeric-row fallback and can name a currency nothing established.

type AccountDailyPnL

type AccountDailyPnL struct {
	DailyPnL           *float64
	UnrealizedTotalPnL *float64
	RealizedTotalPnL   *float64
	AsOf               time.Time
	DailyPnLStatus     DailyPnLFrameStatus
}

AccountDailyPnL is the most recent account-level frame from an IBKR reqPnL subscription. Monetary values are expressed in the account's base currency, and AsOf is the UTC time at which this process received the frame.

DailyPnL covers the current trading day. UnrealizedTotalPnL and RealizedTotalPnL are lifetime totals carried on the same frame, not components of DailyPnL, and therefore do not sum to it. Pointer fields distinguish an observed zero from a missing, unavailable, or IBKR sentinel value.

type AccountSummaryProvenance

type AccountSummaryProvenance string

AccountSummaryProvenance identifies whether a returned account snapshot was completed by the one-shot request or reparsed from the unstamped streaming cache. Callers that require current evidence must accept only Request.

const (
	// AccountSummaryProvenanceRequest means the one-shot request supplied a
	// complete row set and matching end marker.
	AccountSummaryProvenanceRequest AccountSummaryProvenance = "request"
	// AccountSummaryProvenanceCachedFallback means an unstamped streaming
	// cache was reparsed after the one-shot request ended without rows.
	AccountSummaryProvenanceCachedFallback AccountSummaryProvenance = "cached_fallback"
)

type BrokerEvidenceBinding

type BrokerEvidenceBinding struct {
	Session                       ConnectorSessionBinding
	OrderLifecycleGeneration      uint64
	PortfolioProjectionGeneration uint64
}

BrokerEvidenceBinding is a point-in-time identity for the Connector session, order callback frontier, and structural portfolio projection.

type Connection

type Connection struct {
	// contains filtered or unexported fields
}

Connection owns one TWS protocol session and its request, handler, and observation state. Construct one with NewConnection.

func NewConnection

func NewConnection(config *ConnectionConfig) *Connection

NewConnection constructs a disconnected protocol session. A nil config uses DefaultConfig; a non-nil config is copied before defaults are filled in.

func (*Connection) BrokerIDNamespaceReady

func (c *Connection) BrokerIDNamespaceReady() bool

BrokerIDNamespaceReady reports whether nextValidId established the shared request/order correlation frontier for the current socket.

func (*Connection) BrokerSessionEpoch

func (c *Connection) BrokerSessionEpoch() uint64

BrokerSessionEpoch identifies the current socket generation. It advances before each connection attempt so request collectors can reject callbacks from an older socket even when the Connection object itself is reused.

func (*Connection) CancelAccountSummary

func (c *Connection) CancelAccountSummary(reqID int) error

CancelAccountSummary cancels the account-summary request identified by reqID.

func (*Connection) CancelHistoricalData

func (c *Connection) CancelHistoricalData(ctx context.Context, reqID int) error

CancelHistoricalData cancels an active historical request and honors ctx while waiting for rate-limiter admission.

func (*Connection) CancelMarketData

func (c *Connection) CancelMarketData(reqID int) error

CancelMarketData cancels the market-data subscription identified by reqID.

func (*Connection) CancelOrder

func (c *Connection) CancelOrder(orderID int) error

CancelOrder sends a cancelOrder request for an existing order ID. The default build returns ErrTradingDisabled; the "trading" build enables the raw write but does not grant application cancel authority. A nil error means the frame was written, not that IBKR confirmed cancellation.

func (*Connection) CancelPaperOrder

func (c *Connection) CancelPaperOrder(gate PaperOrderGate, orderID int) error

CancelPaperOrder validates gate against the connection and sends a paper cancelOrder request in either build mode. The gate is connection evidence, not application cancel authority. A nil error means the frame was written, not that IBKR confirmed cancellation.

func (*Connection) CancelPnL

func (c *Connection) CancelPnL(reqID int) error

CancelPnL requests cancellation of the reqPnL stream identified by reqID. It returns nil when the connection is already down because socket closure also terminates the stream.

func (*Connection) CancelPnLSingle

func (c *Connection) CancelPnLSingle(reqID int) error

CancelPnLSingle requests cancellation of the reqPnLSingle stream identified by reqID. It returns nil when the connection is already down.

func (*Connection) Connect

func (c *Connection) Connect(ctx context.Context) error

Connect establishes and handshakes a TWS or IB Gateway connection using the configured client ID. Context cancellation bounds the connection attempt.

func (*Connection) Disconnect

func (c *Connection) Disconnect() error

Disconnect closes the protocol session and stops its background work. It is safe to call more than once.

func (*Connection) ExerciseOptions

func (c *Connection) ExerciseOptions(req OptionExerciseRequest) error

ExerciseOptions validates and sends an IBKR option exercise or lapse instruction. It can change a position if IBKR accepts it. A nil error means only that the frame was accepted for the socket write; the method does not wait for broker acknowledgement or finality. In the default build it returns ErrTradingDisabled before validation or transmission. The "trading" build tag enables this low-level wire method but does not grant submit authority.

func (*Connection) GetAccountCode

func (c *Connection) GetAccountCode() string

GetAccountCode returns the last known managed account code.

func (*Connection) GetAccountSummary

func (c *Connection) GetAccountSummary() map[string]string

GetAccountSummary returns a detached copy of the current account-summary cache.

func (*Connection) GetAccountValue

func (c *Connection) GetAccountValue(key string) (string, bool)

GetAccountValue returns the cached account value for key, if present.

func (*Connection) GetConnectionInfo

func (c *Connection) GetConnectionInfo() map[string]any

GetConnectionInfo returns a snapshot of connection diagnostics. The returned map is detached from the connection's internal state.

func (*Connection) GetNextOrderID

func (c *Connection) GetNextOrderID() int

GetNextOrderID reserves the next broker order ID after TWS has supplied a nextValidId for the current socket. Request and order IDs share one local monotonic namespace because msgErrMsg/msg-204 multiplex both kinds through one integer field. Zero means nextValidId has not arrived or the signed 32-bit broker namespace is exhausted; callers must not send an order then.

func (*Connection) GetNextRequestID

func (c *Connection) GetNextRequestID() int

GetNextRequestID reserves and returns the next connection-local request ID. Request and order IDs deliberately share one monotonic frontier so a delayed broker error can never be reinterpreted as a later order event. Zero means the signed 32-bit broker namespace is exhausted.

func (*Connection) GetPosition

func (c *Connection) GetPosition(key string) (*RawPosition, bool)

GetPosition returns the cached position for key, if present.

func (*Connection) GetPositions

func (c *Connection) GetPositions() map[string]*RawPosition

GetPositions returns a detached map containing the current position cache.

func (*Connection) GetPositionsSnapshot

func (c *Connection) GetPositionsSnapshot() map[string]*RawPosition

GetPositionsSnapshot returns the most recent complete reqPositions result. It is isolated from the streaming reqAccountUpdates projection; nil means no one-shot generation has completed in this connection.

func (*Connection) GetPositionsWithPortfolioHealth

func (c *Connection) GetPositionsWithPortfolioHealth() (map[string]*RawPosition, PortfolioStreamHealth)

GetPositionsWithPortfolioHealth captures the cached portfolio rows and the stream receipts under one lock order. The returned map and health value are detached copies.

func (*Connection) HasCompetingLiveSession

func (c *Connection) HasCompetingLiveSession() bool

HasCompetingLiveSession returns true if IBKR reported code 10197 for this connection.

func (*Connection) IsConnected

func (c *Connection) IsConnected() bool

IsConnected reports whether the protocol session is connected.

func (*Connection) IsWhatIfOrderID

func (c *Connection) IsWhatIfOrderID(orderID int) bool

IsWhatIfOrderID reports whether orderID is currently reserved for broker WhatIf evaluation callbacks rather than a working broker order.

func (*Connection) MarketDataType

func (c *Connection) MarketDataType(reqID int) int

MarketDataType returns the current market data type for a reqID. 1=RealTime, 2=Frozen, 3=Delayed, 4=DelayedFrozen. 0 if unknown.

func (*Connection) PlaceOrder

func (c *Connection) PlaceOrder(order *IBKROrder) error

PlaceOrder sends a placeOrder request using the v45+ wire format. The default build returns ErrTradingDisabled; the "trading" build enables the raw write but does not grant application submit authority. A nil error means the frame was written, not that IBKR accepted or finalized the order.

func (*Connection) PlacePaperOrder

func (c *Connection) PlacePaperOrder(gate PaperOrderGate, order *IBKROrder) error

PlacePaperOrder validates gate against the connection and sends a paper placeOrder request in either build mode. The gate is connection evidence, not application submit authority. A nil error means the frame was written, not that IBKR accepted or finalized the order.

func (*Connection) PortfolioProjectionGeneration

func (c *Connection) PortfolioProjectionGeneration() uint64

PortfolioProjectionGeneration returns the current structural portfolio generation. Price, mark, and P&L-only updates do not advance it.

func (*Connection) PreviewOrderWhatIf

func (c *Connection) PreviewOrderWhatIf(ctx context.Context, order *IBKROrder) (OrderWhatIfResult, error)

PreviewOrderWhatIf sends a broker WhatIf order preview and waits for the matching openOrder or error callback. It is available in both build modes: the encoded request has WhatIf and Transmit set true for broker evaluation, but does not create a working order. Preview evidence never grants submit authority; unrestricted PlaceOrder and CancelOrder remain build-tag guarded.

The method mutates order by applying defaults and IDs and by setting WhatIf and Transmit. Local validation or encoding failures are returned as errors. A disconnected connection, send failure, or ctx completion instead returns a result with Status OrderWhatIfStatusUnavailable and a nil error. Accepted and rejected results reflect callback classification, not order finality.

func (*Connection) PrewarmOptionChain

func (c *Connection) PrewarmOptionChain(
	ctx context.Context,
	symbol string,
	expiries []string,
	tradingClass string,
	timeout time.Duration,
) []PrewarmOptionChainResult

PrewarmOptionChain bulk-resolves an option chain by issuing one partial- Contract reqContractDetails per expiration — no Strike, no Right — and streaming the returned contractData frames into optionContractCache. This is the technique TWS uses internally to populate a chain instantly: IBKR's reqContractDetails returns every listed strike × C/P for a given (Symbol, SecType=OPT, Expiry, TradingClass) tuple in one burst.

Compared to per-leg resolution (the cold path each leg-fetcher takes via resolveOptionContract), this drops the gateway round-trip count from 2×strikes×expirations (typical: ~1600) to len(expiries) (typical: 6), and sidesteps the IBKR per-account reqContractDetails throttle that otherwise aborts the gamma fan-out at the first ~50 attempts.

Fan-out: each expiry runs in its own goroutine, gated by a small semaphore (4) to avoid bursting the gateway. Failures are localised — one timed-out expiry doesn't fail the others. tradingClass is load-bearing for SPY/SPX (separates SPY from SPYW weeklies); the caller is expected to know it (e.g. via the secDefOptParams response).

Returns one result per expiry (Cached count + Elapsed + per-expiry Err). The caller decides whether partial success is acceptable.

func (*Connection) RegisterHandler

func (c *Connection) RegisterHandler(msgID int, handler func([]string)) uint64

RegisterHandler adds a handler for msgID and returns the identifier accepted by Connection.UnregisterHandler. A nil handler is ignored and returns zero.

func (*Connection) RegisterHandlerAtEpoch

func (c *Connection) RegisterHandlerAtEpoch(msgID int, handler func([]string, uint64)) uint64

RegisterHandlerAtEpoch adds a handler that receives the socket epoch that read each frame. Connector installs its fixed handler set before starting the Connection reader; dynamic handlers must likewise register before the request that can produce their response.

func (*Connection) RequestAccountSummary

func (c *Connection) RequestAccountSummary(reqID int, tags string) error

RequestAccountSummary starts an account-summary request for reqID. An empty tags string requests the package's default set of account values.

func (*Connection) RequestAccountSummaryForAccount

func (c *Connection) RequestAccountSummaryForAccount(reqID int, tags, expectedAccount string) error

RequestAccountSummaryForAccount starts one account-bound summary read. TWS still receives group "All" because account codes are not account-group names; every returned row is checked against expectedAccount before it can enter the per-request snapshot.

func (*Connection) RequestAccountUpdates

func (c *Connection) RequestAccountUpdates(account string) error

RequestAccountUpdates subscribes to streaming account and portfolio updates for account.

func (*Connection) RequestAllOpenOrders

func (c *Connection) RequestAllOpenOrders() error

RequestAllOpenOrders sends reqAllOpenOrders to the gateway. Results arrive asynchronously as openOrder and orderStatus callbacks followed by openOrderEnd; a nil error means only that the request frame was accepted for the socket write. This read request is available in both build modes.

func (*Connection) RequestContractDetails

func (c *Connection) RequestContractDetails(contract Contract) (int, error)

RequestContractDetails sends a request to retrieve contract details for a contract. Returns the reqID used for the request.

func (*Connection) RequestCurrentTime

func (c *Connection) RequestCurrentTime() error

RequestCurrentTime asks the gateway for its current time. The connection uses this request as a heartbeat.

func (*Connection) RequestHistoricalData

func (c *Connection) RequestHistoricalData(ctx context.Context, contract Contract, endDateTime, duration, barSize, whatToShow string, useRTH bool, includeExpired bool, formatDate int, keepUpToDate bool, beforeSend func(int)) (int, error)

RequestHistoricalData submits an HMDS request for historical data and honors ctx while waiting for rate-limiter admission. The beforeSend callback is invoked after the reqID is allocated but before the message is sent, allowing callers to register tracking state safely. The parameter list past whatToShow mirrors the reqHistoricalData wire message field-for-field (useRTH, includeExpired, formatDate, keepUpToDate).

func (*Connection) RequestMarketData

func (c *Connection) RequestMarketData(ctx context.Context, symbol string) (int, error)

RequestMarketData subscribes to market data for a symbol. ctx must be non-nil and bounds the wait for market-data slot admission. Pass context.Background when the caller does not need cancellation.

func (*Connection) RequestMarketDataWithContract

func (c *Connection) RequestMarketDataWithContract(ctx context.Context, contract Contract, genericTicks string, snapshot bool, regulatorySnap bool) (int, error)

RequestMarketDataWithContract issues reqMktData for contract. ctx must be non-nil and bounds the wait for market-data slot admission. Pass context.Background when the caller does not need cancellation.

func (*Connection) RequestMarketDataWithPrimary

func (c *Connection) RequestMarketDataWithPrimary(ctx context.Context, symbol string, primaryExchange string) (int, error)

RequestMarketDataWithPrimary subscribes to market data with an explicit primary-exchange hint. ctx must be non-nil and bounds the wait for market-data slot admission. Pass context.Background when the caller does not need cancellation.

func (*Connection) RequestOptionsMarketData

func (c *Connection) RequestOptionsMarketData(ctx context.Context, symbol string, expiry string, strike float64, right string) (int, error)

RequestOptionsMarketData subscribes to market data for an option contract. ctx cancellation aborts the contract-resolution round trip, which would otherwise block up to 5 s × N exchange attempts even if the caller has already given up.

func (*Connection) RequestPnL

func (c *Connection) RequestPnL(reqID int, account, modelCode string) error

RequestPnL starts a reqPnL stream for account using reqID. modelCode is empty for accounts without a Financial Advisor model. The caller owns reqID, response handling, and cancellation; Connector.SubscribeAccountPnL provides those lifecycle and caching responsibilities.

func (*Connection) RequestPnLSingle

func (c *Connection) RequestPnLSingle(reqID int, account, modelCode string, conID int) error

RequestPnLSingle starts a reqPnLSingle stream for conID on account using reqID. modelCode is empty for accounts without a Financial Advisor model. The caller owns request-ID correlation, response handling, and cancellation; Connector.SubscribePositionDailyPnL provides those responsibilities.

func (*Connection) RequestPositions

func (c *Connection) RequestPositions() error

RequestPositions requests current positions via the one-shot reqPositions wire path. Library-callable; the daemon prefers the streaming portfolio path through Connector.CachedPositions backed by RequestAccountUpdates (no reqPositions round-trip on the read path — see doc.go). Kept here so downstream callers that bypass Connector can still drive the alternate path. Pairs with WaitForPositionsEnd.

func (*Connection) RequestSecDefOptParams

func (c *Connection) RequestSecDefOptParams(underlyingSymbol, futFopExchange, underlyingSecType string, underlyingConId int, beforeSend func(int)) (int, error)

RequestSecDefOptParams issues msg 78 (reqSecDefOptParams) to enumerate the option chain (expirations + strikes) for an underlying. The IBKR wire format (verified against ibapi.client.EClient.reqSecDefOptParams) has no version field — six total fields: msgID, reqID, underlyingSymbol, futFopExchange (empty for STK options), underlyingSecType, underlyingConId. The beforeSend callback runs after the reqID is allocated but before the message hits the wire so callers can register their per-request handler atomically.

func (*Connection) ServerVersion

func (c *Connection) ServerVersion() int

ServerVersion returns the protocol version negotiated with TWS or IB Gateway. It returns zero before a handshake completes.

func (*Connection) SetMarketDataType

func (c *Connection) SetMarketDataType(dataType int) error

SetMarketDataType sets the market data type (live, delayed, etc.)

func (*Connection) SetOnConnect

func (c *Connection) SetOnConnect(fn func())

SetOnConnect replaces the callback invoked after a successful connection.

func (*Connection) SetOnDisconnect

func (c *Connection) SetOnDisconnect(fn func(error))

SetOnDisconnect replaces the callback invoked after a connection is lost.

func (*Connection) SetPacketLogger

func (c *Connection) SetPacketLogger(logger PacketLogger)

SetPacketLogger installs a packet logger invoked for every outbound frame. Passing nil disables logging. Frames may contain account IDs, order references, and order details; callers must protect the sink as sensitive data and use it only for short-lived debugging.

func (*Connection) SetSystemNoticeHandler deprecated

func (c *Connection) SetSystemNoticeHandler(handler func(note *systemNotification, alias reqAliasEntry))

SetSystemNoticeHandler is the compatibility form of Connection.SetSystemNoticeHandlerAtEpoch.

Deprecated: the callback's parameter types are unexported, so a caller outside this package can only ever pass nil. It will be removed in the next major version.

func (*Connection) SetSystemNoticeHandlerAtEpoch deprecated

func (c *Connection) SetSystemNoticeHandlerAtEpoch(handler func(note *systemNotification, alias reqAliasEntry, epoch uint64))

SetSystemNoticeHandlerAtEpoch replaces the callback for parsed gateway system notices. Passing nil disables delivery.

Deprecated: the callback's parameter types are unexported, so a caller outside this package can only ever pass nil. It will be removed in the next major version.

func (*Connection) SetSystemNoticeHandlerAtEpochWithPostAction

func (c *Connection) SetSystemNoticeHandlerAtEpochWithPostAction(handler func(note *systemNotification, alias reqAliasEntry, epoch uint64) func())

SetSystemNoticeHandlerAtEpochWithPostAction is the Connector-facing form. The returned one-shot action runs only after Connection releases its inbound generation lease. This lets a current notice mark state atomically while deferring any outbound recovery frame until reconnect can no longer deadlock behind the reader. Its parameter types are unexported, so callers outside this package can only pass nil; the next major version unexports it.

func (*Connection) Status

func (c *Connection) Status() ConnectionStatus

Status returns the current connection lifecycle state.

func (*Connection) UnregisterHandler

func (c *Connection) UnregisterHandler(msgID int, handlerID uint64)

UnregisterHandler removes a previously registered handler for a message type.

func (*Connection) UsingTLS

func (c *Connection) UsingTLS() bool

UsingTLS reports whether the established session negotiated TLS. When EnableTLSFallback flips the configured value, this exposes the actual mode.

func (*Connection) WaitForAccountSummaryEnd

func (c *Connection) WaitForAccountSummaryEnd(timeout time.Duration) error

WaitForAccountSummaryEnd waits until an account-summary request completes or timeout elapses.

func (*Connection) WaitForPositionsEnd

func (c *Connection) WaitForPositionsEnd(timeout time.Duration) error

WaitForPositionsEnd waits for the matching msgPositionEnd frame after a RequestPositions call. Library-callable companion to RequestPositions (daemon uses the streaming path; see RequestPositions for details).

type ConnectionConfig

type ConnectionConfig struct {
	Host     string
	Port     int
	ClientID int
	Account  string

	// PacketLogPath enables the optional packet logger when non-empty. The path
	// may contain a %d placeholder that is formatted with the client ID. Packet
	// logs are account-sensitive and may contain order references and details.
	PacketLogPath string
	LogWireHex    bool // LogWireHex emits account-sensitive raw protocol frames.

	// WireInterceptor records frames for this connection when non-nil. When it
	// is nil, NewConnection creates an interceptor from the configured
	// environment, if enabled there.
	WireInterceptor *WireInterceptor

	// startAPI retry settings for the configured client ID.
	MaxClientIDRetries int // Max attempts for transient startAPI failures (default 5)

	// Reconnection settings (from hedge patterns)
	AutoReconnect     bool
	MaxRetries        int
	InitialDelay      time.Duration // Initial reconnect delay (5s)
	MaxDelay          time.Duration // Max reconnect delay (60s)
	BackoffMultiplier float64       // Exponential backoff multiplier (2.0)
	Jitter            bool          // Add random jitter to delays

	// Connection timeouts
	ConnectTimeout    time.Duration
	HeartbeatInterval time.Duration

	// TLS options
	UseTLS                bool
	EnableTLSFallback     bool
	TLSInsecureSkipVerify bool
	TLSServerName         string
}

ConnectionConfig configures one TWS or IB Gateway protocol session.

func DefaultConfig

func DefaultConfig() *ConnectionConfig

DefaultConfig returns a new connection configuration populated with the package defaults. Callers may modify the returned value before use.

type ConnectionStatus

type ConnectionStatus int

ConnectionStatus identifies the lifecycle state of a Connection.

const (
	// StatusDisconnected means no protocol session is established.
	StatusDisconnected ConnectionStatus = iota
	// StatusConnecting means a connection or handshake is in progress.
	StatusConnecting
	// StatusConnected means the protocol session is ready.
	StatusConnected
	// StatusReconnecting means recovery of a lost session is in progress.
	StatusReconnecting
	// StatusFailed means the most recent connection attempt failed.
	StatusFailed
)

func (ConnectionStatus) String

func (s ConnectionStatus) String() string

String returns the uppercase name of s, or "UNKNOWN" for an unrecognized value.

type Connector

type Connector struct {
	// contains filtered or unexported fields
}

Connector owns one broker connection together with its subscriptions and in-memory market, contract, account, and order caches. Construct a Connector with NewConnector, call Connector.Start to begin its lifecycle, and call Connector.Stop when finished.

func NewConnector

func NewConnector(config *ConnectorConfig) *Connector

NewConnector constructs a stopped Connector for one broker connection. It performs no network I/O and defensively copies config and BaseConfig. A nil config uses package defaults; call Connector.Start to connect.

func (*Connector) AccountDailyPnL

func (c *Connector) AccountDailyPnL() (AccountDailyPnL, bool)

AccountDailyPnL returns the most recently received account Daily P&L snapshot. ok is false until Connector.SubscribeAccountPnL is active and a frame has been received. The method neither blocks nor issues wire traffic. Handlers replace snapshots rather than mutating their pointed-to values, so the returned shallow copy remains stable.

func (*Connector) AccountID

func (c *Connector) AccountID() string

AccountID returns the account code most recently received from IBKR's managedAccounts frame. It returns an empty string before that frame is observed or when the connector has no connection.

func (*Connector) AccountSummaryRaw

func (c *Connector) AccountSummaryRaw() map[string]string

AccountSummaryRaw returns a defensive copy of the connector's current raw account-summary cache. The map uses IBKR keys: bare tags for base-currency values and `<tag>_<currency>` for currency-specific values.

It is empty when no connection or observations are available, and also whenever the cache cannot be attributed to the session's expected account — the same admissibility rule CachedAccountSummary applies, because it is the same unstamped map. Emptiness alone does not describe connection state. The method is safe to call concurrently with streaming cache updates.

func (*Connector) ActiveDailyPnLSubscriptions

func (c *Connector) ActiveDailyPnLSubscriptions() int

ActiveDailyPnLSubscriptions reports the number of tracked per-contract reqPnLSingle streams. It does not include the account-level reqPnL stream.

func (*Connector) BackendLinkStatus added in v2.8.2

func (c *Connector) BackendLinkStatus() (down bool, changedAt time.Time)

BackendLinkStatus reports the current TWS-to-IBKR upstream-link latch. It is intentionally separate from IsConnected/IsReady, which describe the local API socket and handshake. A code-1100 notice sets Down until a current session observes code 1101 or 1102.

func (*Connector) BeginDelayedMarketDataFallback added in v2.8.2

func (c *Connector) BeginDelayedMarketDataFallback(ctx context.Context, symbol string) (func(), error)

BeginDelayedMarketDataFallback temporarily changes subsequent market-data requests to IBKR delayed mode and force-refreshes symbol's rejected shared subscription. It is intentionally narrow: callers must have already observed a typed entitlement rejection and must release the returned lease after the bounded retry. Entitlement observations remain in-memory only.

IBKR returns live data even when type 3 was requested if the account is entitled to it. Otherwise it returns delayed ticks and names them through the per-request marketDataType notice. The lease restores the daemon's frozen-aware type-2 default unless this exact connection has since reported a competing live session, in which case delayed mode remains binding.

func (*Connector) CachedAccountSummary

func (c *Connector) CachedAccountSummary() *RawAccountSummary

CachedAccountSummary returns a caller-owned typed snapshot of the connector's streaming account-summary cache, labeled with the account it belongs to. It does not issue gateway traffic and returns nil until at least one core account value has been observed, or whenever the cache is not admissible for the session's expected account. The method is safe to call concurrently with streaming cache updates.

func (*Connector) CachedPositions

func (c *Connector) CachedPositions() ([]*RawPosition, error)

CachedPositions returns the latest filtered portfolio cache without issuing a positions request. The returned slice is detached, but its RawPosition pointers refer to cached rows and must be treated as read-only. Zero-quantity rows and stock placeholders with ConID zero are omitted. A disconnected Connector returns nil, nil; freshness is not implied by a non-empty result.

func (*Connector) CachedPositionsWithHealth

func (c *Connector) CachedPositionsWithHealth() ([]*RawPosition, PortfolioStreamHealth, error)

CachedPositionsWithHealth returns the same read-only cached rows as Connector.CachedPositions together with the latest stream completion and heartbeat receipts. It performs no positions snapshot request; a typed account-scope conflict may trigger the throttled stream resubscribe behind the read. A disconnected Connector returns nil rows, zero health, and a nil error.

func (*Connector) CancelOptionIV

func (c *Connector) CancelOptionIV(reqID int)

CancelOptionIV cancels an option-IV subscription previously returned by SubscribeOptionIV. Idempotent: zero reqID or an unknown reqID is a no-op. Best-effort on the wire — a failed CancelMarketData is logged but not returned, since the typical caller is a deferred cleanup.

Use this instead of UnsubscribeMarketData(symbol) for option-IV subscriptions: SubscribeOptionIV does not install a subscriptions[symbol] entry, so the symbol-scoped unsubscribe either no-ops or — worse — tears down an unrelated streaming-quote subscription for the same underlier.

func (*Connector) CancelOrder

func (c *Connector) CancelOrder(orderID int) error

CancelOrder sends a cancellation for broker orderID. Default builds return ErrTradingDisabled. A successful return means the cancellation frame was sent, not that the broker confirmed the order cancelled.

func (*Connector) CancelOrderForSession

func (c *Connector) CancelOrderForSession(binding ConnectorSessionBinding, orderID int) error

CancelOrderForSession sends a cancellation only on the exact Connector socket generation named by binding.

func (*Connector) CancelOrderForSessionGuarded

func (c *Connector) CancelOrderForSessionGuarded(ctx context.Context, binding ConnectorSessionBinding, orderID int, guard func() error) error

CancelOrderForSessionGuarded carries caller cancellation and a final authority guard to the exact cancel frame.

func (*Connector) CancelPaperOrder

func (c *Connector) CancelPaperOrder(gate PaperOrderGate, orderID int) error

CancelPaperOrder validates gate against the configured connection and sends a cancellation for broker orderID in a paper account. A successful return means the frame was sent, not that the broker confirmed cancellation.

func (*Connector) CancelPaperOrderForSession

func (c *Connector) CancelPaperOrderForSession(binding ConnectorSessionBinding, gate PaperOrderGate, orderID int) error

CancelPaperOrderForSession validates gate and sends a paper cancellation only on the exact Connector socket generation named by binding.

func (*Connector) CancelPaperOrderForSessionGuarded

func (c *Connector) CancelPaperOrderForSessionGuarded(ctx context.Context, binding ConnectorSessionBinding, gate PaperOrderGate, orderID int, guard func() error) error

CancelPaperOrderForSessionGuarded is the paper-gated counterpart to CancelOrderForSessionGuarded.

func (*Connector) CaptureBrokerEvidence

func (c *Connector) CaptureBrokerEvidence() (BrokerEvidenceBinding, bool)

CaptureBrokerEvidence returns one stable broker-evidence frontier. False means the Connector is not a ready current session.

func (*Connector) CaptureHistoricalSession

func (c *Connector) CaptureHistoricalSession() (HistoricalSessionBinding, bool)

CaptureHistoricalSession is the historical-data compatibility spelling for Connector.CaptureSession.

func (*Connector) CapturePortfolioProjectionForBoundSession

func (c *Connector) CapturePortfolioProjectionForBoundSession(binding ConnectorSessionBinding) (PortfolioProjectionBinding, bool)

CapturePortfolioProjectionForBoundSession snapshots the structural portfolio authority without acquiring publicationBarrier or evidenceBarrier. It is only valid from a protected order wire guard while the transport owns publicationBarrier for reading and evidenceBarrier exclusively. Keeping this variant lock-free preserves the publication-then-evidence lock order.

func (*Connector) CapturePortfolioProjectionForSession

func (c *Connector) CapturePortfolioProjectionForSession(binding ConnectorSessionBinding) (PortfolioProjectionBinding, bool)

CapturePortfolioProjectionForSession snapshots positions, health, and the structural generation while portfolio/session mutations are excluded. False means binding is stale or the Connector is not ready.

func (*Connector) CaptureSession

func (c *Connector) CaptureSession() (ConnectorSessionBinding, bool)

CaptureSession returns the exact ready Connection object and socket epoch that may own a new broker-adjacent read. The token is process-local and is evidence for a later equality check, not durable readiness or authority.

func (*Connector) ContractDetailsFirst

func (c *Connector) ContractDetailsFirst(ctx context.Context, contract Contract, timeout time.Duration) (*ContractDetailsLite, error)

ContractDetailsFirst returns the first contract-details row the gateway emits for contract. It does not apply option-candidate preference. A timeout of zero or less uses five seconds; context cancellation and send or timeout failures are returned to the caller.

func (*Connector) CurrencyLedgerSnapshot

func (c *Connector) CurrencyLedgerSnapshot() map[string]CurrencyLedger

CurrencyLedgerSnapshot returns a caller-owned map derived from the connector's streaming account-summary cache. It neither blocks nor issues gateway traffic. An empty map means either no non-base exposure was observed or the cache is not populated yet; use connection state to distinguish them. The method is safe to call concurrently with streaming cache updates.

func (*Connector) DataFarmStatuses

func (c *Connector) DataFarmStatuses() []DataFarmStatus

DataFarmStatuses returns a detached snapshot of the latest tracked farm notices, sorted by type and then name. It returns nil for a nil Connector; callers determine freshness from each entry's DataFarmStatus.AsOf.

func (*Connector) EnsureMarketDataSubscription

func (c *Connector) EnsureMarketDataSubscription(ctx context.Context, symbol string, fields []string, staleAfter time.Duration) (bool, error)

EnsureMarketDataSubscription creates a live symbol subscription or refreshes one whose last observed tick is at least staleAfter old. A staleAfter value of zero or less disables age-based refresh. The boolean reports whether a new wire request was sent. ctx must be non-nil and bounds market-data slot acquisition; unavailable, inactive, entitlement, and request failures are returned.

func (*Connector) ExerciseOptions

func (c *Connector) ExerciseOptions(ctx context.Context, req OptionExerciseRequest) error

ExerciseOptions sends an option exercise or lapse instruction through the connector's active connection. A zero TickerID is replaced with a new request ID. The method checks ctx only before sending and does not wait for broker acknowledgement; a nil error means only that the frame was accepted for the socket write. Once the call reaches an active Connection, the default build returns ErrTradingDisabled before validation or transmission.

func (*Connector) ExerciseOptionsForSession

func (c *Connector) ExerciseOptionsForSession(ctx context.Context, binding ConnectorSessionBinding, req OptionExerciseRequest) error

ExerciseOptionsForSession sends an option exercise or lapse instruction only on the exact Connector socket generation named by binding. A reconnect or disconnect before request-ID reservation or frame transmission is refused.

func (*Connector) ExerciseOptionsForSessionGuarded

func (c *Connector) ExerciseOptionsForSessionGuarded(ctx context.Context, binding ConnectorSessionBinding, req OptionExerciseRequest, guard func() error) error

ExerciseOptionsForSessionGuarded carries a final authority guard through pacing to the exact exercise/lapse socket write.

func (*Connector) FetchContractDetails

func (c *Connector) FetchContractDetails(symbol string, timeout time.Duration) ([]ContractDetailsLite, error)

FetchContractDetails returns cached contract details for symbol when a resolved entry exists; otherwise it requests all matching rows and waits for the broker's completion marker. Identical in-flight requests are coalesced; each response handler still filters by request ID so unrelated contracts can resolve independently. On timeout it returns any rows already received together with ErrContractDetailsTimeout.

func (*Connector) FetchHistoricalDailyBars

func (c *Connector) FetchHistoricalDailyBars(ctx context.Context, symbol string, lookbackDays int, timeout time.Duration) ([]HistoricalBar, error)

FetchHistoricalDailyBars requests daily bars for symbol and waits for the historical-data response. A lookbackDays value of zero or less uses 400 days; a timeout of zero or less uses 45 seconds. The earlier of timeout and the ctx deadline bounds both paced transmission and response waiting. Cancellation best-effort cancels an already-sent broker request.

func (*Connector) FetchHistoricalDailyBarsWhatToShow

func (c *Connector) FetchHistoricalDailyBarsWhatToShow(ctx context.Context, symbol string, lookbackDays int, whatToShow string, timeout time.Duration) ([]HistoricalBar, error)

FetchHistoricalDailyBarsWhatToShow requests daily bars using the normalized IBKR whatToShow value supplied by the caller. It does not fall back to another feed, so returned bars retain the requested feed provenance. Context, lookback, and timeout semantics match Connector.FetchHistoricalDailyBars.

func (*Connector) FetchHistoricalDailyBarsWithContract

func (c *Connector) FetchHistoricalDailyBarsWithContract(ctx context.Context, contract Contract, lookbackDays int, timeout time.Duration) ([]HistoricalBar, error)

FetchHistoricalDailyBarsWithContract requests daily bars using the routing fields already present on contract, including exchange, currency, local symbol, or ConID. Context, lookback, and timeout semantics match Connector.FetchHistoricalDailyBars.

func (*Connector) FetchHistoricalDailyFeeRates

func (c *Connector) FetchHistoricalDailyFeeRates(ctx context.Context, contract Contract, lookbackDays int, timeout time.Duration) ([]HistoricalBar, error)

FetchHistoricalDailyFeeRates requests daily stock-borrow fee-rate bars for an exact broker contract. It is intentionally narrower than the general historical APIs: FEE_RATE is pinned and ConID is required. A missing executable exchange may be completed only by a bounded exact-ConID contract details read whose identity and route are strictly checked; the method never resolves by symbol, substitutes another ConID, or fabricates SMART. Concurrent identical requests share one open HMDS request, and its detached typed result is reused for IBKR's 15-second identical-request cooldown.

func (*Connector) FetchMarketSnapshot

func (c *Connector) FetchMarketSnapshot(ctx context.Context, symbol string, timeout time.Duration) (*MarketSnapshot, error)

FetchMarketSnapshot requests a one-shot bid, ask, and last-price snapshot and waits for the broker's end marker. ctx must be non-nil. A timeout of zero or less uses five seconds. Context cancellation returns ctx.Err; timeout returns context.DeadlineExceeded. Both paths best-effort cancel the request and release its market-data slot. Inactive and unavailable connectors return ErrSymbolInactive and ErrIBKRUnavailable without sending a request.

func (*Connector) FetchOptionExpiries

func (c *Connector) FetchOptionExpiries(symbol string, timeout time.Duration) ([]string, error)

FetchOptionExpiries returns a newly allocated, sorted, deduplicated list of option expiry dates for symbol in YYYY-MM-DD form. A timeout of zero or less uses ten seconds. If the timeout expires after at least one response, the partial list is returned without an error; an empty timeout returns an error. An unavailable or inactive Connector returns the corresponding sentinel.

func (*Connector) FetchOptionExpiryStrikes

func (c *Connector) FetchOptionExpiryStrikes(symbol string, timeout time.Duration) (map[string][]float64, error)

FetchOptionExpiryStrikes returns newly allocated, sorted, deduplicated strike slices keyed by YYYY-MM-DD expiry. It merges strikes across exchanges and trading classes; callers that require class identity should use Connector.FetchOptionExpiryStrikesClassed. Timeout, partial-result, and availability semantics match Connector.FetchOptionExpiries.

func (*Connector) FetchOptionExpiryStrikesClassed

func (c *Connector) FetchOptionExpiryStrikesClassed(symbol string, timeout time.Duration) (map[string][]ExpiryClassedStrikes, error)

FetchOptionExpiryStrikesClassed returns newly allocated strike grids grouped first by YYYY-MM-DD expiry and then by broker trading class. Both class entries and strikes are sorted. This preserves distinct contracts that share a date and strike but have different trading classes. Timeout, partial-result, and availability semantics match Connector.FetchOptionExpiries.

func (*Connector) FetchWSHEarnings

func (c *Connector) FetchWSHEarnings(ctx context.Context, symbol string) (string, error)

FetchWSHEarnings returns the raw WSH earnings-event JSON for a stock symbol. It preserves the legacy symbol-resolution and temporary-inactive-cache behavior. Call Connector.FetchWSHEarningsWithIdentity when the caller has a positive held contract ID and needs fresh broker identity evidence.

func (*Connector) FetchWSHEarningsWithIdentity

func (c *Connector) FetchWSHEarningsWithIdentity(ctx context.Context, symbol string, conID int) (WSHEarningsResult, error)

FetchWSHEarningsWithIdentity reads WSH earnings events using a caller-proven positive held contract ID and independently attempts an exact contract- details lookup by that ID. A symbol-level temporary inactive mark does not suppress this exact lookup. If exact details are unavailable or contradict the request, the event read may still succeed but StockIdentity remains nil; callers must not infer issuer classification from the supplied ID or cache.

func (*Connector) HistoricalSessionCurrent

func (c *Connector) HistoricalSessionCurrent(binding HistoricalSessionBinding) bool

HistoricalSessionCurrent is the historical-data compatibility spelling for Connector.SessionCurrent.

func (*Connector) InactiveReason

func (c *Connector) InactiveReason(symbol string) (string, bool)

InactiveReason reports an unexpired in-memory inactivity mark for symbol. It performs no broker request. The boolean is false when no mark exists or the mark has expired; the returned reason is untrusted broker text.

func (*Connector) IsConnected

func (c *Connector) IsConnected() bool

IsConnected reports whether the Connector currently has an active broker connection. It does not imply that response handlers are ready; use Connector.IsReady when issuing requests.

func (*Connector) IsOptionContractCached

func (c *Connector) IsOptionContractCached(symbol, tradingClass, expiry string, strike float64, right string) bool

IsOptionContractCached reports whether the active connection has a resolved option entry matching symbol, tradingClass, expiry, strike, and right. Symbol, tradingClass, and right are trimmed and matched case-insensitively; expiry is trimmed, while strike is encoded to six decimal places. It returns false when no connection is attached or the matching entry has a zero ConID.

func (*Connector) IsReady

func (c *Connector) IsReady() bool

IsReady reports whether the broker connection is established and the Connector's response handlers are registered.

func (*Connector) IsSymbolInactive

func (c *Connector) IsSymbolInactive(symbol string) bool

IsSymbolInactive reports whether symbol has an unexpired in-memory inactivity mark. It performs no broker request.

func (*Connector) LastError

func (c *Connector) LastError() string

LastError returns the most recent connector startup error that left the connector in degraded mode. Empty means either healthy or no concrete connector-level diagnosis is available.

func (*Connector) MarketDataAbsences added in v2.8.0

func (c *Connector) MarketDataAbsences() []MarketDataAbsenceError

MarketDataAbsences snapshots every route key whose terminal entitlement rejection is still inside its retry window, ordered by key. Expired records are dropped on read exactly as marketDataAbsenceFor drops them, so an observation surface can never name a key the subscribe paths would already let through. Message stays untrusted broker text; callers that classify must read Code.

func (*Connector) MarketDataSnapshot

func (c *Connector) MarketDataSnapshot() map[string]*MarketData

MarketDataSnapshot returns a detached point-in-time copy of all locally tracked streaming subscriptions. The returned map and MarketData values may be mutated by the caller. Zero fields can represent data not yet observed. Timestamp carries the subscription's bookkeeping clock, which is seeded at subscribe time; LastTickAt is the any-tick liveness clock; LastPriceTickAt is the accepted-price observation clock. The latter two are zero until their respective tick class arrives. None guarantees broker-source freshness.

func (*Connector) MarketDataTypeForSymbol

func (c *Connector) MarketDataTypeForSymbol(symbol string) int

MarketDataTypeForSymbol returns the latest gateway data-type notice for the symbol's active subscription: 1=live, 2=frozen, 3=delayed, 4=delayed-frozen, or 0 when the subscription or notice is absent.

func (*Connector) MaybeResubscribeStaleDailyPnL

func (c *Connector) MaybeResubscribeStaleDailyPnL(marketOpen bool) bool

MaybeResubscribeStaleDailyPnL rebuilds all Daily P&L streams when marketOpen is true and the account stream has not produced its first frame or its last frame is stale. The caller owns the market calendar; off-hours inactivity is not treated as stale. It returns true when a rebuild attempt is issued, not when a replacement frame is received. Attempts are throttled to one per internal staleness window.

func (*Connector) OptionGreeks

func (c *Connector) OptionGreeks(symbol string) (Greeks, bool)

OptionGreeks returns the last valid model-computation Greeks for an option key returned by Connector.SubscribeOption. The boolean is false until at least one field has been observed; callers must not interpret absence as a zero-valued Greek. The returned value is a copy.

func (*Connector) OptionIV

func (c *Connector) OptionIV(symbol string) (float64, bool)

OptionIV returns the last valid implied-volatility observation for key as a fraction, such as 0.30 for 30 percent. The boolean is false when no valid observation has been cached; the method performs no broker request.

func (*Connector) OptionIVWithDataType added in v2.8.2

func (c *Connector) OptionIVWithDataType(symbol string) (iv float64, dataType int, ok bool)

OptionIVWithDataType returns the last valid implied-volatility observation together with the IBKR model-computation source type. dataType is 1 for tick 13, 3 for delayed tick 83, and 0 when IV came from an untyped generic tick. Callers that require clock alignment must reject 0 rather than infer.

func (*Connector) OptionPrevClose

func (c *Connector) OptionPrevClose(symbol string) (float64, bool)

OptionPrevClose returns the option contract's own previous regular-session close, not the underlying's close. The boolean is false when no positive value has been observed.

func (*Connector) OptionQuoteBidAsk

func (c *Connector) OptionQuoteBidAsk(symbol string) (bid, ask float64, ok bool)

OptionQuoteBidAsk returns the last observed bid and ask for an option key. It returns (0, 0, false) when neither side has been observed; one-sided results return true with the absent side left at zero. The method performs no broker request and does not itself determine freshness.

func (*Connector) OptionUnderlyingPrice

func (c *Connector) OptionUnderlyingPrice(symbol string) (float64, bool)

OptionUnderlyingPrice returns the underlying price embedded in the latest model-computation tick for an option key. The boolean is false when no valid price has been observed. This is the price the broker used for the associated Greeks.

func (*Connector) OrderLifecycleGeneration

func (c *Connector) OrderLifecycleGeneration() uint64

OrderLifecycleGeneration returns the current connection-local order-event frontier without issuing a broker request. Zero means no accepted lifecycle callback has been observed by this Connector.

func (*Connector) PortfolioProjectionGeneration

func (c *Connector) PortfolioProjectionGeneration() uint64

PortfolioProjectionGeneration returns the current structural portfolio frontier without issuing a broker request. It advances for scope, completeness, contract-set, or quantity changes, but not mark/PnL-only updates.

func (*Connector) PositionDailyPnL

func (c *Connector) PositionDailyPnL(conID int) (PositionDailyPnL, bool)

PositionDailyPnL returns the cached per-contract Daily P&L snapshot for conID. ok is false when no subscription exists. ok may be true while all value pointers are nil, meaning the stream is active but has not supplied usable values. The method neither blocks nor issues wire traffic. Handlers replace snapshots rather than mutating their pointed-to values, so the returned shallow copy remains stable.

func (*Connector) PreviewOrderWhatIf

func (c *Connector) PreviewOrderWhatIf(ctx context.Context, contract *Contract, order *RawOrder) (OrderWhatIfResult, error)

PreviewOrderWhatIf sends a broker WhatIf preview for a connector-level contract/order pair. Nil inputs fail validation. It does not mutate order or add to Connector.openOrders because no working order should exist. Status and error behavior match Connection.PreviewOrderWhatIf.

func (*Connector) PreviewOrderWhatIfForSession

func (c *Connector) PreviewOrderWhatIfForSession(ctx context.Context, binding ConnectorSessionBinding, contract *Contract, order *RawOrder) (OrderWhatIfResult, error)

PreviewOrderWhatIfForSession is PreviewOrderWhatIf constrained to the exact connector socket generation captured by binding.

func (*Connector) PreviewOrderWhatIfWithOrderID

func (c *Connector) PreviewOrderWhatIfWithOrderID(ctx context.Context, contract *Contract, order *RawOrder, orderID int) (OrderWhatIfResult, error)

PreviewOrderWhatIfWithOrderID sends a broker WhatIf preview using a positive, caller-supplied broker order ID. This supports evaluating a replacement draft for a tracked order, but does not modify that order or grant authority to do so. Status and error behavior match Connection.PreviewOrderWhatIf.

func (*Connector) PreviewOrderWhatIfWithOrderIDForSession

func (c *Connector) PreviewOrderWhatIfWithOrderIDForSession(ctx context.Context, binding ConnectorSessionBinding, contract *Contract, order *RawOrder, orderID int) (OrderWhatIfResult, error)

PreviewOrderWhatIfWithOrderIDForSession is PreviewOrderWhatIfWithOrderID constrained to the exact connector socket generation captured by binding.

func (*Connector) PrewarmOptionChain

func (c *Connector) PrewarmOptionChain(
	ctx context.Context,
	symbol string,
	expiries []string,
	tradingClass string,
	timeout time.Duration,
) []PrewarmOptionChainResult

PrewarmOptionChain resolves and caches option contracts for each expiry in a symbol and trading-class pair. It returns one result per expiry with cache counts, duration, and any error. The call returns nil when disconnected; ctx and timeout bound the underlying bulk requests. Later Connector.SubscribeOption calls can reuse the resolved contract identities.

func (*Connector) RefreshPositions

func (c *Connector) RefreshPositions(timeout time.Duration) ([]*RawPosition, error)

RefreshPositions issues the broker's singleton positions request, waits up to timeout for its end marker, and returns the filtered cache shape described by Connector.CachedPositions. Because the protocol supplies no request ID, callers must serialize refreshes.

func (*Connector) RegisterOrderLifecycleHandler

func (c *Connector) RegisterOrderLifecycleHandler(handler func(OrderLifecycleEvent))

RegisterOrderLifecycleHandler appends a compatibility callback for broker order lifecycle messages. Callbacks run synchronously in registration order and must return quickly. A nil Connector or handler is ignored.

func (*Connector) RegisterOrderLifecycleReceiptHandler

func (c *Connector) RegisterOrderLifecycleReceiptHandler(handler func(OrderLifecycleReceipt))

RegisterOrderLifecycleReceiptHandler appends a callback that receives the exact socket-session receipt for every event.

func (*Connector) RequestAccountSummary

func (c *Connector) RequestAccountSummary(ctx context.Context, timeout time.Duration) (*RawAccountSummary, error)

RequestAccountSummary issues a synchronous reqAccountSummary request and returns a caller-owned parsed snapshot. ctx must be non-nil. The call blocks until the gateway emits accountSummaryEnd, ctx is cancelled, or timeout elapses.

Behavior:

  • Returns ErrIBKRUnavailable immediately if the connector is not connected; no network traffic is generated.
  • On timeout the request is cancelled (cancelAccountSummary sent) so the gateway does not continue streaming updates against the consumed reqID.
  • timeout <= 0 falls back to defaultAccountSummaryTimeout (5s).

The method is safe to call concurrently; each invocation uses a fresh request ID and normally reads only that request's rows. If the gateway emits an end marker without rows, it falls back to a defensive copy of the streaming account-updates cache.

func (*Connector) RequestAccountSummaryWithProvenance

func (c *Connector) RequestAccountSummaryWithProvenance(ctx context.Context, timeout time.Duration) (*RawAccountSummary, AccountSummaryProvenance, error)

RequestAccountSummaryWithProvenance preserves RequestAccountSummary's fallback behavior while exposing whether the gateway actually supplied rows for this request. CachedFallback has no trustworthy source receipt even though parsing gives the caller-owned copy an AsOf timestamp.

func (*Connector) RequestAccountUpdates

func (c *Connector) RequestAccountUpdates(account string) error

RequestAccountUpdates starts the singleton streaming account and portfolio subscription used by Connector.CachedPositions. Pass an empty or aggregate account value to resolve a concrete managed account from the connection.

Aggregate values ("All", comma-separated managedAccounts lists) are not account codes — TWS rejects them with error 321 and the portfolio stream never starts. They are reduced to a concrete code (or to "", which TWS resolves itself for single-account logins) before hitting the wire.

func (*Connector) ReserveOrderID

func (c *Connector) ReserveOrderID() (int, error)

ReserveOrderID claims the next broker order ID without submitting an order. Default builds return ErrTradingDisabled. The ID is consumed locally and should be passed to a later Connector.SubmitOrder call.

func (*Connector) ReserveOrderIDForSession

func (c *Connector) ReserveOrderIDForSession(binding ConnectorSessionBinding) (int, error)

ReserveOrderIDForSession claims the next broker order ID from the exact socket generation named by binding. The reservation remains tied to that epoch and cannot authorize a later-session submission.

func (*Connector) ResolveExactHistoricalStockRoute

func (c *Connector) ResolveExactHistoricalStockRoute(ctx context.Context, contract Contract, timeout time.Duration) (Contract, error)

ResolveExactHistoricalStockRoute completes a missing executable exchange only through an exact positive-ConID contract-details request. It rejects wrong, missing, or ambiguous broker details and never resolves by symbol or substitutes a default route. Callers may retain their original position identity separately from the returned route used on the wire.

func (*Connector) ResolveOrderContractForSession

func (c *Connector) ResolveOrderContractForSession(ctx context.Context, binding ConnectorSessionBinding, contract Contract, timeout time.Duration) (ResolvedOrderContract, error)

ResolveOrderContractForSession resolves a symbol/option description to one exact positive-ConID identity. Epoch-aware handlers and an epoch-bound request prevent a callback from a retired socket completing a new preview.

func (*Connector) ResolveWSHStockIdentity

func (c *Connector) ResolveWSHStockIdentity(ctx context.Context, symbol string, conID int) (*ContractDetailsLite, error)

ResolveWSHStockIdentity independently reads exact broker contract details for a caller-proven positive held contract ID. It deliberately bypasses the symbol-level temporary inactive cache and does not make a WSH metadata or event request. All failures are returned as sanitized WSH errors.

func (*Connector) RunScannerParameters

func (c *Connector) RunScannerParameters(ctx context.Context, timeout time.Duration) (*ScannerParameters, error)

RunScannerParameters fetches and parses the gateway's scanner catalog. ctx must be non-nil, and a timeout of zero or less uses ten seconds. The returned value owns its typed slices and preserves the exact broker XML in RawXML. Because this broker request has no request ID, callers should serialize concurrent catalog requests.

func (*Connector) RunScannerSubscription

func (c *Connector) RunScannerSubscription(ctx context.Context, sub ScannerSubscription, timeout time.Duration) ([]ScannerRow, error)

RunScannerSubscription starts a scanner subscription, returns a newly allocated copy of the first result frame, and then cancels the subscription. ctx must be non-nil. A timeout of zero or less uses 20 seconds. Context cancellation, timeout, request failures, and request-scoped broker errors are returned; informational farm notices do not fail the call.

func (*Connector) SeedAccountDailyPnLForTest

func (c *Connector) SeedAccountDailyPnLForTest(account string, snap AccountDailyPnL)

SeedAccountDailyPnLForTest installs an account-level snapshot without wire traffic. It is intended only for tests outside package ibkr.

func (*Connector) SeedAccountIDForTest

func (c *Connector) SeedAccountIDForTest(account string)

SeedAccountIDForTest installs the managed-account code returned by Connector.AccountID. It is intended only for tests outside package ibkr; runtime callers must obtain the value from IBKR.

func (*Connector) SeedContractDetails

func (c *Connector) SeedContractDetails(symbol string, detail ContractDetailsLite) bool

SeedContractDetails adds a caller-supplied contract to the Connector's in-memory cache when symbol is non-empty, detail has a non-zero ConID, and no resolved entry is already cached for that symbol. It never replaces a live resolved entry and performs no broker request. The result reports whether the seed was applied.

func (*Connector) SeedOptionContracts

func (c *Connector) SeedOptionContracts(options map[string]ContractDetailsLite) int

SeedOptionContracts copies resolved entries into the active connection's option cache and returns the number inserted. Entries with a zero ConID are ignored, and an existing resolved entry always wins. The input map is not retained or mutated. It returns zero when no connection is attached.

func (*Connector) SeedPositionDailyPnLForTest

func (c *Connector) SeedPositionDailyPnLForTest(conID int, snap PositionDailyPnL)

SeedPositionDailyPnLForTest installs snap for conID without wire traffic and marks that contract as subscribed. It is intended only for tests outside package ibkr; runtime callers must use Connector.SubscribePositionDailyPnL.

func (*Connector) ServerVersion

func (c *Connector) ServerVersion() int

ServerVersion returns the IBKR server protocol version reported by the gateway during the handshake. Returns 0 when no connection is established.

func (*Connector) SessionCurrent

func (c *Connector) SessionCurrent(binding ConnectorSessionBinding) bool

SessionCurrent reports whether binding still names this Connector's ready Connection and exact socket epoch.

func (*Connector) SessionReceiptCurrent

func (c *Connector) SessionReceiptCurrent(binding ConnectorSessionBinding) bool

SessionReceiptCurrent reports whether binding names the Connector's exact installed inbound socket generation. Connecting is accepted because startAPI synchronously processes a small frame burst before onConnect; disconnected/failed/reconnecting states are never current. This does not authorize outbound requests.

func (*Connector) SetMarketDataType

func (c *Connector) SetMarketDataType(dataType int) error

SetMarketDataType requests the market-data mode for subsequent requests: 1=live, 2=frozen, 3=delayed, and 4=delayed-frozen. A live request is reduced to delayed mode when the connection has detected a competing live session. It returns an error when no broker connection is active or the write fails.

func (*Connector) SnapshotContracts

func (c *Connector) SnapshotContracts() map[string]ContractDetailsLite

SnapshotContracts returns a caller-owned copy of the connector's resolved ordinary-contract cache. Entries with a zero ConID are omitted. Concurrent cache updates are synchronized, and mutating the returned map does not affect the connector.

func (*Connector) SnapshotOpenOrders

func (c *Connector) SnapshotOpenOrders(ctx context.Context) (OpenOrderSnapshot, error)

SnapshotOpenOrders joins or starts one epoch-bound reqAllOpenOrders flight. Caller cancellation only stops that waiter; after the wire request begins, the collector remains installed until same-epoch openOrderEnd or the internal protocol deadline. This is required because the protocol has no request ID and a late terminator could otherwise bless a later flight.

A canceled waiter issues no late request. A protocol timeout or uncertain send poisons only the exact Connection epoch; callers fail closed until a reconnect advances that epoch.

func (*Connector) SnapshotOptionContracts

func (c *Connector) SnapshotOptionContracts() map[string]ContractDetailsLite

SnapshotOptionContracts returns a caller-owned copy of the active connection's resolved option-contract cache, keyed by normalized symbol, trading class, expiry, strike, and right. Entries with a zero ConID are omitted. It returns nil when no connection is attached. Concurrent cache updates are synchronized, and mutating the returned map does not affect the connection.

func (*Connector) Start

func (c *Connector) Start(ctx context.Context) error

Start attaches lifecycle handlers and attempts to open the Connector's broker connection. It returns an error when already started. An initial connection failure leaves the Connector running but not ready and is exposed through Connector.LastError, so that failure does not make Start fail. Context cancellation bounds the connection attempt.

func (*Connector) Stop

func (c *Connector) Stop() error

Stop marks the Connector stopped, cancels its P&L subscriptions, and closes the broker connection. It is idempotent. The Connector remains a valid value after Stop; later method calls report unavailable state or no-op as defined by each method.

func (*Connector) SubmitOrder

func (c *Connector) SubmitOrder(contract *Contract, order *RawOrder) error

SubmitOrder sends an unrestricted order through the active broker connection. Default builds return ErrTradingDisabled before transmission; builds with the "trading" tag enable the wire path. A successful return means the frame was sent, not that the broker accepted or filled the order.

func (*Connector) SubmitOrderForSession

func (c *Connector) SubmitOrderForSession(binding ConnectorSessionBinding, contract *Contract, order *RawOrder) error

SubmitOrderForSession sends an unrestricted order only on the exact Connector socket generation named by binding. The binding must have been captured from this Connector; reconnect or disconnect drift is rejected at allocator claim and again at the transport boundary before any wire write.

func (*Connector) SubmitOrderForSessionGuarded

func (c *Connector) SubmitOrderForSessionGuarded(ctx context.Context, binding ConnectorSessionBinding, contract *Contract, order *RawOrder, guard func() error) error

SubmitOrderForSessionGuarded carries caller cancellation and a final authority guard to the exact socket write. guard runs under the connection transport lock after pacing and epoch checks, immediately before any byte.

func (*Connector) SubmitPaperOrder

func (c *Connector) SubmitPaperOrder(gate PaperOrderGate, contract *Contract, order *RawOrder) error

SubmitPaperOrder validates gate against the configured connection and sends an order to a paper account. It is available in default builds without enabling Connector.SubmitOrder. A successful return means the frame was sent, not that the broker accepted or filled the order.

func (*Connector) SubmitPaperOrderForSession

func (c *Connector) SubmitPaperOrderForSession(binding ConnectorSessionBinding, gate PaperOrderGate, contract *Contract, order *RawOrder) error

SubmitPaperOrderForSession validates gate and sends a paper order only on the exact Connector socket generation named by binding.

func (*Connector) SubmitPaperOrderForSessionGuarded

func (c *Connector) SubmitPaperOrderForSessionGuarded(ctx context.Context, binding ConnectorSessionBinding, gate PaperOrderGate, contract *Contract, order *RawOrder, guard func() error) error

SubmitPaperOrderForSessionGuarded is the paper-gated counterpart to SubmitOrderForSessionGuarded.

func (*Connector) SubscribeAccountPnL

func (c *Connector) SubscribeAccountPnL(account string) error

SubscribeAccountPnL starts and caches a streaming reqPnL subscription for account. account must be non-empty. Repeated calls for the same account are idempotent; changing the account cancels the previous stream, clears its cached snapshot, and starts a new one. Connector.Stop cancels the active stream. Use Connector.AccountDailyPnL for non-blocking cache reads. Callers must serialize attempts to switch one connector between different accounts.

func (*Connector) SubscribeMarketData

func (c *Connector) SubscribeMarketData(ctx context.Context, symbol string, fields []string) error

SubscribeMarketData ensures a symbol-keyed streaming subscription exists. Repeating the call for the same normalized symbol is a no-op, including from concurrent callers. ctx must be non-nil and bounds acquisition of a market-data slot. fields is retained as subscription metadata; the wire tick set is selected by the Connector. The slice is not copied and must not be mutated while subscribed. When disconnected, the method records a local subscription with no live request. Use Connector.UnsubscribeMarketData for cleanup.

func (*Connector) SubscribeMarketDataWithContract

func (c *Connector) SubscribeMarketDataWithContract(ctx context.Context, contract Contract, fields []string) (string, error)

SubscribeMarketDataWithContract ensures a streaming subscription exists for an explicitly routed contract and returns its MarketDataKeyForContract key. Repeating the same route is a no-op. ctx must be non-nil and bounds slot acquisition. fields is retained as metadata; the Connector selects the wire tick set. The slice is not copied and must not be mutated while subscribed. When disconnected, it records a local subscription with ReqID zero.

func (*Connector) SubscribeMarketDataWithContractForSession

func (c *Connector) SubscribeMarketDataWithContractForSession(ctx context.Context, binding ConnectorSessionBinding, contract Contract, fields []string) (string, error)

SubscribeMarketDataWithContractForSession creates a short-lived, non-sharing subscription for one exact positive-ConID contract, or one explicit CASH/IDEALPRO currency pair, on binding's physical socket. The unique key prevents a symbol/route cache entry from a different contract or socket satisfying broker-write evidence.

func (*Connector) SubscribeOption

func (c *Connector) SubscribeOption(ctx context.Context, underlying, tradingClass, expiryYMD string, strike float64, right string) (string, int, error)

SubscribeOption ensures a streaming subscription exists for a fully specified option contract. expiryYMD uses YYYYMMDD and right uses C or P. An empty tradingClass defaults to the normalized underlying; callers handling multiple classes for one underlying must supply the class explicitly. The returned key addresses cached values in Connector.MarketDataSnapshot, and the request ID identifies the live subscription. ctx bounds contract resolution and slot acquisition.

func (*Connector) SubscribeOptionIV

func (c *Connector) SubscribeOptionIV(ctx context.Context, symbol string, expiry time.Time, strike float64, right string) (int, error)

SubscribeOptionIV starts an option market-data subscription and routes model-computation IV to the normalized underlying key read by Connector.OptionIV. expiry is converted to a UTC YYYYMMDD date and right is normalized to upper case. ctx bounds contract resolution and slot acquisition. Pair the returned request ID with Connector.CancelOptionIV.

func (*Connector) SubscribeOptionIVKeyed

func (c *Connector) SubscribeOptionIVKeyed(ctx context.Context, symbol string, expiry time.Time, strike float64, right string) (int, string, error)

SubscribeOptionIVKeyed starts one option market-data subscription and routes model IV to the returned per-contract key. Use the key with Connector.OptionIV and the request ID with Connector.CancelOptionIV. Unlike Connector.SubscribeOptionIV, concurrent legs for one underlying do not overwrite one shared underlying-keyed value.

func (*Connector) SubscribePositionDailyPnL

func (c *Connector) SubscribePositionDailyPnL(account string, conID int) error

SubscribePositionDailyPnL starts and caches a reqPnLSingle stream for conID on account. account must be non-empty and conID must be positive. Streams are keyed by conID, so repeated calls for an already subscribed contract are idempotent. Connector.Stop cancels all active position streams. The method returns ErrIBKRUnavailable when the connector is disconnected. One connector must not reuse the same conID for different accounts.

func (*Connector) SubscriptionRejectCh

func (c *Connector) SubscriptionRejectCh(key string) <-chan SubscriptionRejection

SubscriptionRejectCh returns the terminal-rejection channel for a tracked subscription key. The channel may receive at most one pending rejection and is not closed when the subscription ends. It returns nil when the key is not tracked or rejection signaling is unavailable; a nil channel can be used directly in a select to disable that case.

func (*Connector) UnsubscribeMarketData

func (c *Connector) UnsubscribeMarketData(symbol string) error

UnsubscribeMarketData removes the normalized symbol or route key from the local subscription cache and best-effort cancels its live broker request. It is idempotent when no matching subscription exists. For routed subscriptions, pass the key returned by Connector.SubscribeMarketDataWithContract.

func (*Connector) UnsubscribeMarketDataForSession

func (c *Connector) UnsubscribeMarketDataForSession(ctx context.Context, binding ConnectorSessionBinding, key string) error

UnsubscribeMarketDataForSession removes only the exact subscription created on binding and emits a cancel solely when that physical socket is still current. A retired cleanup can never cancel a successor subscription.

func (*Connector) UsingTLS

func (c *Connector) UsingTLS() bool

UsingTLS reports the TLS mode the active session negotiated. False when disconnected or when a non-TLS handshake succeeded (possibly via fallback).

func (*Connector) WithBoundBrokerSession

func (c *Connector) WithBoundBrokerSession(binding ConnectorSessionBinding, operation func() error) (bool, error)

WithBoundBrokerSession admits operation only when binding names the current Connector socket session. It deliberately does not hold publication while operation waits in pacing or on a paused transport. Protected transports acquire the publication read side only for their final guarded write, where the exact Connection epoch remains the final pre-wire authority. False means binding was not current and operation was not called.

func (*Connector) WithBrokerEvidenceMutation

func (c *Connector) WithBrokerEvidenceMutation(change func())

WithBrokerEvidenceMutation serializes an external owner-published identity change after all in-flight Connector evidence dispatch and exact-session broker operations have drained. It exists for daemon connector publication only; it does not authorize broker activity.

func (*Connector) WithStableBrokerEvidence

func (c *Connector) WithStableBrokerEvidence(binding BrokerEvidenceBinding, commit func() bool) bool

WithStableBrokerEvidence executes commit while structural portfolio/session writers and order lifecycle dispatch are excluded. It returns false without calling commit when binding is no longer exact.

type ConnectorConfig

type ConnectorConfig struct {
	// Deprecated: ServiceName has no effect; nothing reads it since the
	// connection-pool removal. It will be removed in the next major version.
	ServiceName       string
	PreferredClientID int
	BaseConfig        *ConnectionConfig
}

ConnectorConfig configures the single Connection owned by a Connector. A nil BaseConfig uses DefaultConfig. PreferredClientID falls back first to BaseConfig.ClientID and then to 1. NewConnector copies both config values.

type ConnectorSessionBinding

type ConnectorSessionBinding struct {
	// contains filtered or unexported fields
}

ConnectorSessionBinding is an opaque, process-local identity for the Connector's current Connection object and socket generation. Callers may retain it and ask the originating Connector whether it is still current, but cannot manufacture broker authority from its contents.

type Contract

type Contract struct {
	ConID        int
	Symbol       string
	SecType      string  // STK, OPT, FUT, etc.
	Expiry       string  // For options/futures
	Strike       float64 // For options
	Right        string  // P or C for options
	Multiplier   int
	Exchange     string
	PrimaryExch  string // Primary exchange for routing
	Currency     string
	LocalSymbol  string
	TradingClass string
	SecIDType    string
	SecID        string
}

Contract identifies an instrument in TWS wire requests.

type ContractCacheAuthority

type ContractCacheAuthority interface {
	LoadContractCache() (payload []byte, ok bool, err error)
	SaveContractCache(payload []byte, observedAt time.Time) error
}

ContractCacheAuthority stores the encoded contract-cache envelope for a ContractStore. SaveContractCache must publish payload and observedAt as one logical update; observedAt is the same UTC timestamp encoded in the payload.

Once ContractStore.UseAuthority succeeds, the store never reads or writes its legacy JSON path. An authority that reports ok=false represents an empty cache, not permission to fall back to that file.

type ContractDetailsLite

type ContractDetailsLite struct {
	ReqID        int
	Symbol       string
	SecType      string
	Expiry       string
	Strike       float64
	Right        string
	Exchange     string
	PrimaryExch  string
	Currency     string
	ConID        int
	LocalSymbol  string
	TradingClass string
	Multiplier   int
	Industry     string
	Category     string
	Subcategory  string
	StockType    string
	TimeZoneID   string
	TradingHours string
	LiquidHours  string
	// MinTick is the venue's minimum price increment for the contract.
	// Zero means the gateway did not report one.
	MinTick float64
}

ContractDetailsLite contains the routing, identity, schedule, and price-tick fields decoded from a broker contract-details response. Option-specific fields such as Expiry, Strike, and Right are empty for non-option contracts.

type ContractStore

type ContractStore struct {
	// contains filtered or unexported fields
}

ContractStore serializes snapshots of resolved contracts for reuse across connector lifetimes. It is safe for concurrent use.

Before ContractStore.UseAuthority succeeds, the store uses the legacy JSON codec at dir/contracts.json. That path exists for cutover and isolated tests, not as runtime authority. After an authority is attached, every load and save uses it exclusively; the store does not merge or fall back to the legacy file.

Ordinary contracts are keyed by symbol. Options are keyed by their normalized symbol, trading class, expiry, strike, and right. Expired option entries are excluded from loaded and saved snapshots.

func NewContractStore

func NewContractStore(dir string) *ContractStore

NewContractStore returns a store whose legacy JSON codec is rooted at dir. It performs no I/O and creates dir only on the first legacy save. dir is ignored after ContractStore.UseAuthority succeeds.

func (*ContractStore) Load

Load returns a caller-owned symbol-to-contract map and the membership hash stored with it. Calls are serialized with ContractStore.Save. A nil store, missing payload, or newer legacy-file envelope returns (nil, "", nil) as a cold cache. Read and decode failures return an error. Older legacy envelopes are accepted; attached authorities are validated as current by ContractStore.UseAuthority.

func (*ContractStore) LoadOptions

func (s *ContractStore) LoadOptions() (map[string]ContractDetailsLite, error)

LoadOptions returns a caller-owned option-key-to-contract map. Options whose expiry precedes the current New York date are omitted from the returned snapshot without rewriting persistence. Legacy keys without a trading class are migrated in memory to an empty class segment; malformed legacy keys are skipped. A nil store, missing payload, newer legacy envelope, or a snapshot containing no live options returns an empty non-nil map. Read and decode failures return an error. Calls are serialized with ContractStore.Save.

func (*ContractStore) Save

func (s *ContractStore) Save(contracts map[string]ContractDetailsLite, options map[string]ContractDetailsLite, membersHash string) error

Save publishes one filtered contract-cache snapshot. It copies its map inputs and does not mutate them. Contracts with a zero ConID and options expired before the current New York date are omitted. Every option key and value must form a valid, matching tuple; otherwise Save returns an error without publishing. membersHash may be empty when membership is not tracked.

Calls on one store are serialized. An attached authority receives one encoded envelope; the legacy codec writes a temporary file and renames it over dir/contracts.json.

func (*ContractStore) UseAuthority

func (s *ContractStore) UseAuthority(authority ContractCacheAuthority) error

UseAuthority validates authority's current payload and, on success, switches all subsequent loads and saves to it. A missing payload is a valid cold start. A nil store, nil authority, load failure, or invalid current envelope returns an error and leaves the existing backend unchanged. UseAuthority does not import or merge the legacy JSON file.

type CurrencyLedger

type CurrencyLedger struct {
	NetLiquidationByCurrency float64
	CashBalance              float64
	StockMarketValue         float64
	OptionMarketValue        float64
	UnrealizedPnL            float64
	RealizedPnL              float64
	ExchangeRate             float64
}

CurrencyLedger is one non-base-currency IBKR $LEDGER row. Monetary values are denominated in that row's currency, not converted to the account base currency. ExchangeRate is base-currency units per ledger-currency unit, so multiplying a monetary field by ExchangeRate yields its base-currency contribution. A zero field may be either an observed zero or an omitted value; the wire format does not preserve that distinction here.

type DailyPnLFrameStatus

type DailyPnLFrameStatus string

DailyPnLFrameStatus distinguishes a usable Daily P&L value from a gateway placeholder and from malformed wire data. Callers must not infer those states from a nil value alone.

const (
	DailyPnLFrameAvailable   DailyPnLFrameStatus = "available"
	DailyPnLFrameUnavailable DailyPnLFrameStatus = "unavailable"
	DailyPnLFrameMalformed   DailyPnLFrameStatus = "malformed"
)

Daily P&L frame statuses reported by the connector.

type DataFarmStatus

type DataFarmStatus struct {
	Name    string
	Type    string
	Status  string
	Code    int
	Message string
	AsOf    time.Time
}

DataFarmStatus describes the latest notice observed for one IBKR data farm. Type identifies the farm category, Status is one of "ok", "inactive", "disconnected", or "broken", and AsOf is the local observation time.

type ExpiryClassedStrikes

type ExpiryClassedStrikes struct {
	TradingClass string    `json:"trading_class"`
	Strikes      []float64 `json:"strikes"`
}

ExpiryClassedStrikes contains the sorted, deduplicated strike grid for one trading class on an expiry date. TradingClass preserves the broker's class discriminator when an underlying lists multiple contract classes.

type Greeks

type Greeks struct {
	Delta float64 `json:"delta"`
	Gamma float64 `json:"gamma"`
	Theta float64 `json:"theta"`
	Vega  float64 `json:"vega"`
	Rho   float64 `json:"rho"`
}

Greeks contains option sensitivities reported by the broker.

type HexPacketLogger

type HexPacketLogger struct {
	// contains filtered or unexported fields
}

HexPacketLogger writes outbound frames to a local file in a human-friendly hex representation. Each line contains:

<timestamp> <label> <byte-length> <hex>

func NewHexPacketLogger

func NewHexPacketLogger(path string) (*HexPacketLogger, error)

NewHexPacketLogger creates a packet logger that appends to the given path. The caller is responsible for closing the returned logger when finished.

func (*HexPacketLogger) Close

func (l *HexPacketLogger) Close() error

Close releases the underlying file handle.

func (*HexPacketLogger) Outbound

func (l *HexPacketLogger) Outbound(label string, payload []byte)

Outbound logs a payload if the logger is still active.

type HistoricalBar

type HistoricalBar struct {
	Time     time.Time
	Date     string
	Open     float64
	High     float64
	Low      float64
	Close    float64
	Volume   int64
	Average  float64
	BarCount int
}

HistoricalBar represents one OHLC bar returned by IBKR historical market data. Prices and Average use the contract's price units; Volume is the broker-reported volume. Time is parsed best-effort and is zero when parsing fails, while Date always retains the original broker value.

type HistoricalDataValidationError

type HistoricalDataValidationError struct {
	Reason string
}

HistoricalDataValidationError reports a connector-authored validation failure. Reason is an allowlisted token and never includes broker payload.

func (*HistoricalDataValidationError) Error

Error returns a fixed connector-authored description and the allowlisted reason token; it never returns raw broker payload text.

type HistoricalRequestError

type HistoricalRequestError struct {
	Code       int
	Message    string
	RetryAfter time.Duration
	Category   string
}

HistoricalRequestError reports a broker error from a historical-data request. RetryAfter is zero when the connector has no retry delay to suggest, and Message is untrusted broker text.

func (*HistoricalRequestError) Error

func (e *HistoricalRequestError) Error() string

Error returns the broker message when present, otherwise a code-based historical-data error description.

type HistoricalSessionBinding

type HistoricalSessionBinding = ConnectorSessionBinding

HistoricalSessionBinding preserves the historical-data API name while all broker-adjacent cached receipts share the same socket-session identity.

type IBKROrder

type IBKROrder struct {
	OrderID  int    // OrderID is the session-scoped broker order ID; zero requests allocation.
	ClientID int    // ClientID is the TWS API client ID; zero uses the connection's configured ID.
	PermID   int    // PermID is IBKR's permanent order ID; zero means not observed.
	Account  string // Account is the target broker account; empty uses connection account data.

	// Contract details
	Symbol       string
	SecType      string
	ConID        int
	Exchange     string
	Currency     string
	Expiry       string
	Strike       float64 // Strike is in the contract's quote currency; zero means unspecified.
	Right        string
	Multiplier   string // Multiplier is the broker's decimal string, such as "100" for many options.
	PrimaryExch  string
	LocalSymbol  string
	TradingClass string
	SecIDType    string
	SecID        string

	// Order details
	Action    string  // Action must be BUY or SELL.
	TotalQty  int     // TotalQty is a positive number of shares or contracts.
	OrderType string  // MKT, LMT, STP, etc.
	LmtPrice  float64 // LmtPrice is in quote-currency units; zero means unspecified.
	AuxPrice  float64 // AuxPrice is a stop price or trailing amount; zero means unspecified.

	// Time in force
	TIF           string // TIF is the broker time-in-force code; empty defaults to DAY.
	OcaGroup      string
	OcaType       int
	OrderRef      string // Our reference
	Transmit      bool   // Transmit is set true by write and WhatIf helpers before encoding.
	WhatIf        bool   // WhatIf is forced true for previews and false for order submission.
	OpenClose     string // OpenClose is O or C; connector helpers default an empty value to O.
	Origin        int
	ParentID      int
	BlockOrder    bool
	SweepToFill   bool
	DisplaySize   int
	TriggerMethod int
	OutsideRth    bool // OutsideRth asks IBKR to permit execution outside regular trading hours.
	Hidden        bool

	// State
	Status        string  // Status is locally assigned or broker-observed and is not finality by itself.
	Filled        int     // Filled is the observed filled quantity; zero may mean none or not observed.
	Remaining     int     // Remaining is the observed open quantity; zero may mean none or not observed.
	AvgFillPrice  float64 // AvgFillPrice is in quote-currency units; zero may mean unavailable.
	LastFillPrice float64 // LastFillPrice is in quote-currency units; zero may mean unavailable.

	// Timestamps
	CreatedTime   time.Time  // CreatedTime is local process time; IsZero reports unknown.
	SubmittedTime time.Time  // SubmittedTime is local socket-write time; IsZero reports unknown.
	FilledTime    *time.Time // FilledTime is nil when no fill time is recorded locally.
	CancelledTime *time.Time // CancelledTime is nil when no cancellation time is recorded locally.

	// Error tracking
	LastError string
	WhyHeld   string

	// Misc optional parameters
	GoodAfterTime                  string
	GoodTillDate                   string
	Rule80A                        string
	SettlingFirm                   string
	AllOrNone                      bool
	MinQty                         int
	PercentOffset                  float64
	ETradeOnly                     bool
	FirmQuoteOnly                  bool
	NbboPriceCap                   float64
	AuctionStrategy                int
	StartingPrice                  float64
	StockRefPrice                  float64
	Delta                          float64
	StockRangeLower                float64
	StockRangeUpper                float64
	OverridePercentageConstraints  bool
	Volatility                     float64
	VolatilityType                 int
	DeltaNeutralOrderType          string
	DeltaNeutralAuxPrice           float64
	DeltaNeutralConID              int
	DeltaNeutralSettlingFirm       string
	DeltaNeutralClearingAccount    string
	DeltaNeutralClearingIntent     string
	DeltaNeutralOpenClose          string
	DeltaNeutralShortSale          bool
	DeltaNeutralShortSaleSlot      int
	DeltaNeutralDesignatedLocation string
	ContinuousUpdate               int
	ReferencePriceType             int
	TrailStopPrice                 float64 // TrailStopPrice is the initial stop price in quote-currency units.
	TrailingPercent                float64 // TrailingPercent is the broker percentage value, not a fraction.
	LmtPriceOffset                 float64 // LmtPriceOffset is the TRAIL LIMIT offset in price units.
	BasisPoints                    float64
	BasisPointsType                int
	ScaleInitLevelSize             int
	ScaleSubsLevelSize             int
	ScalePriceIncrement            float64
	ScalePriceAdjustValue          float64
	ScalePriceAdjustInterval       int
	ScaleProfitOffset              float64
	ScaleAutoReset                 bool
	ScaleInitPosition              int
	ScaleInitFillQty               int
	ScaleRandomPercent             bool
	HedgeType                      string
	HedgeParam                     string
	OptOutSmartRouting             bool
	ClearingAccount                string
	ClearingIntent                 string
	NotHeld                        bool
	ModelCode                      string
	ShortSaleSlot                  int
	DesignatedLocation             string
	ExemptCode                     int
	DiscretionaryAmt               float64
	FaGroup                        string
	FaMethod                       string
	FaPercentage                   string
	FaProfile                      string
}

IBKROrder is the mutable, low-level order and contract representation used by Connection order-write and WhatIf methods. It is a wire request and local observation, not proof that IBKR accepted, filled, cancelled, or finalized an order.

Prices use the contract's quote currency and quantities use the broker's instrument units (shares for stock and contracts for options). Most optional numeric fields use zero to mean unspecified. Validation and sending may fill OrderID, ClientID, Account, OpenClose, and TIF and may update WhatIf, Transmit, Status, Remaining, and timestamp fields in place.

type MarketData

type MarketData struct {
	Symbol    string    `json:"symbol"`
	Timestamp time.Time `json:"timestamp"`

	Last float64 `json:"last"`
	Bid  float64 `json:"bid"`
	Ask  float64 `json:"ask"`
	Mid  float64 `json:"mid"`
	// MarkPrice is tick 37 from IBKR — the gateway's calculated fair
	// price. Populated for every symbol, but only load-bearing for
	// indices (VIX, VIX3M, SPX), which don't emit bid/ask/last.
	MarkPrice float64 `json:"mark_price,omitempty"`
	Open      float64 `json:"open"`
	High      float64 `json:"high"`
	Low       float64 `json:"low"`
	Close     float64 `json:"close"`
	VWAP      float64 `json:"vwap"`

	// Week-range highs/lows from generic tick 165 (Misc Stats). Zero when
	// the gateway hasn't delivered the tick yet — caller must distinguish
	// "not arrived" from "exactly zero" via the timestamp / Observed state.
	Week13Low  float64 `json:"week_13_low,omitempty"`
	Week13High float64 `json:"week_13_high,omitempty"`
	Week26Low  float64 `json:"week_26_low,omitempty"`
	Week26High float64 `json:"week_26_high,omitempty"`
	Week52Low  float64 `json:"week_52_low,omitempty"`
	Week52High float64 `json:"week_52_high,omitempty"`

	Volume    int64 `json:"volume"`
	AvgVolume int64 `json:"avg_volume,omitempty"`
	// LastTickAt is when this process last received a tick on the
	// subscription, or zero when none has ever arrived. See
	// [Subscription.LastTickAt] for the two limits that bind every reader:
	// it is an arrival instant rather than the instant the value was struck,
	// and it advances on any tick, size and volume included.
	LastTickAt time.Time `json:"last_tick_at,omitzero"`
	// LastPriceTickAt is when this process last accepted a positive price
	// tick on the subscription, or zero when none has arrived. It excludes
	// blank and rejected prices plus non-price traffic, but remains an arrival
	// instant rather than proof of broker-source freshness.
	LastPriceTickAt   time.Time `json:"last_price_tick_at,omitzero"`
	LastTradeTime     time.Time `json:"last_trade_time,omitzero"`
	BidSize           int       `json:"bid_size"`
	AskSize           int       `json:"ask_size"`
	OpenInt           int64     `json:"open_int"`
	OpenIntObserved   bool      `json:"open_int_observed,omitempty"`
	ShortableShares   int64     `json:"shortable_shares,omitempty"`
	ShortableObserved bool      `json:"shortable_observed,omitempty"`
	ShortableTickAt   time.Time `json:"shortable_tick_at,omitzero"`

	IV     float64 `json:"iv"`
	HV     float64 `json:"hv"`
	IVRank float64 `json:"iv_rank"`
	IVPerc float64 `json:"iv_perc"`

	Greeks *Greeks `json:"greeks,omitempty"`

	PutCallRatio  float64 `json:"put_call_ratio"`
	TickDirection string  `json:"tick_direction"`

	Session   string `json:"session,omitempty"`
	DataType  string `json:"data_type,omitempty"`
	IsDelayed bool   `json:"is_delayed,omitempty"`
}

MarketData is the latest set of market-data observations for a symbol. Callers must use the accompanying observed, timestamp, and data-type fields where provided; a numeric zero alone does not always prove the broker reported a zero value.

type MarketDataAbsenceError

type MarketDataAbsenceError struct {
	Key        string
	Code       int
	Message    string
	ObservedAt time.Time
	RetryAt    time.Time
}

MarketDataAbsenceError reports that a recent terminal entitlement rejection is suppressing another request for the same route key. ObservedAt and RetryAt are local times; Message is untrusted broker text.

func (*MarketDataAbsenceError) Error

func (e *MarketDataAbsenceError) Error() string

Error returns a concise description of the suppressed market-data request.

type MarketSnapshot

type MarketSnapshot struct {
	Symbol         string
	Bid            *float64
	Ask            *float64
	Last           *float64
	IV             *float64
	IVStatus       string // "real" when populated from tick 106, "unavailable" otherwise.
	AsOf           time.Time
	MarketDataType int // 1=live, 2=frozen, 3=delayed, 4=delayed-frozen, 0=unknown
}

MarketSnapshot is the result of one Connector.FetchMarketSnapshot request. Nil price pointers mean the broker did not provide that field. The one-shot request does not request generic ticks, so IV is nil and IVStatus is "unavailable". AsOf is the local completion time, not a broker tick timestamp.

type OpenOrderSnapshot

type OpenOrderSnapshot struct {
	Complete   bool                    // Complete reports whether same-epoch openOrderEnd arrived.
	Orders     []OrderLifecycleEvent   // Orders contains collected openOrder events and may be empty.
	AsOf       time.Time               // AsOf is the local UTC time at which the evidence completed.
	Session    ConnectorSessionBinding // Session identifies the exact Connection socket generation.
	Generation uint64                  // Generation is the order-event frontier captured at completion.
}

OpenOrderSnapshot is a one-shot read of the API-created open orders the gateway reports across client IDs. It does not bind or include manual TWS orders merely because Complete is true; those require the separate client-0 open-order binding flow, which this request does not perform.

Complete is true only when openOrderEnd arrived on the exact Connection socket epoch that sent reqAllOpenOrders. When Complete is false, Orders may contain callbacks collected before the caller or protocol deadline ended, but that proves nothing about absent orders. A request failure returns no collected orders. AsOf is the local UTC completion or failure time, not a broker timestamp. Session is the opaque Connection socket generation that sent the request, and Generation is the Connector order-lifecycle frontier at the exact same-epoch openOrderEnd; a change to either invalidates this receipt.

type OptionExerciseRequest

type OptionExerciseRequest struct {
	// TickerID correlates broker callbacks. Connector.ExerciseOptions allocates
	// one when it is zero; Connection.ExerciseOptions requires a positive value.
	TickerID int

	// Contract must be a non-nil OPT contract with symbol, expiry, positive
	// strike, and a C or P right.
	Contract         *Contract
	ExerciseAction   int    // ExerciseAction must be OptionExerciseActionExercise or OptionExerciseActionLapse.
	ExerciseQuantity int    // ExerciseQuantity is a positive number of option contracts.
	Account          string // Account is required and is trimmed before encoding.
	Override         int    // Override is the broker exercise override flag and must be 0 or 1.
	ManualOrderTime  string // ManualOrderTime is sent only when the negotiated server version supports it.
}

OptionExerciseRequest describes one exerciseOptions wire request. It is an instruction with position-changing side effects if IBKR accepts it, not a preview. The request does not itself carry paper-gate or application-level submit authority.

type OrderLifecycleEvent

type OrderLifecycleEvent struct {
	Type            string // Type is one of the OrderLifecycleEvent constants.
	OrderID         int    // OrderID is session-scoped; zero means absent.
	PermID          int    // PermID is IBKR's permanent order ID; zero means absent.
	ClientID        int    // ClientID identifies the TWS API client; zero is a valid client ID.
	ClientIDPresent bool   // ClientIDPresent distinguishes explicit client 0 from an omitted legacy field.
	RequestID       int    // RequestID correlates execDetails requests; zero means absent.
	Status          string // Status is unnormalized broker state and may be empty.
	ErrorCode       int    // ErrorCode is populated for synthesized error events.
	Message         string // Message is untrusted broker warning or error text.
	Symbol          string
	SecType         string
	ConID           int
	Expiry          string
	Strike          float64
	Right           string
	Multiplier      int
	Exchange        string
	Currency        string
	LocalSymbol     string
	TradingClass    string
	Action          string
	TotalQuantity   float64 // TotalQuantity is in shares or contracts.
	OrderType       string
	LimitPrice      float64 // LimitPrice is in quote-currency units.
	AuxPrice        float64 // AuxPrice is a stop price or trailing amount.
	TrailingPercent float64 // TrailingPercent is the broker percentage value, not a fraction.
	TrailStopPrice  float64 // TrailStopPrice is in quote-currency units.
	LmtPriceOffset  float64 // LmtPriceOffset is in price units.
	TIF             string
	TriggerMethod   int
	OutsideRth      bool
	WhatIf          bool
	Filled          float64 // Filled is the callback's cumulative filled quantity.
	Remaining       float64 // Remaining is the callback's unfilled quantity.
	AvgFillPrice    float64 // AvgFillPrice is in quote-currency units.
	LastFillPrice   float64 // LastFillPrice is in quote-currency units.
	WhyHeld         string
	MktCapPrice     float64
	ExecID          string
	ExecTime        string
	Account         string
	ExecutionSide   string
	Shares          float64 // Shares is this execution's quantity in shares or contracts.
	Price           float64 // Price is this execution's price in quote-currency units.
	CumQty          float64 // CumQty is the execution's cumulative filled quantity.
	OrderRef        string
	Raw             []string
}

OrderLifecycleEvent is a typed subset of one broker order callback. Type identifies which fields are meaningful. Status remains the broker's text and no individual callback, socket write, or local mutation proves lifecycle finality; consumers must reconcile the callback sequence and broker truth.

Quantities are in the broker's instrument units and prices are in the contract's quote currency. Numeric zero can be a real value or an absent or unparsable field because the wire callbacks do not preserve that distinction. Raw is a copied slice of untrusted wire fields and may be nil for synthesized error events.

func ParseOrderLifecycleEvent

func ParseOrderLifecycleEvent(fields []string) (ev OrderLifecycleEvent, ok bool)

ParseOrderLifecycleEvent parses openOrder, orderStatus, and execDetails wire callbacks. It accepts both legacy and summarized protobuf forms. Unknown or malformed messages return ok=false and a zero event; broker error events are correlated and synthesized separately by Connector. Parsed events are observations, not a finality decision.

type OrderLifecycleReceipt

type OrderLifecycleReceipt struct {
	Session ConnectorSessionBinding
	Event   OrderLifecycleEvent
}

OrderLifecycleReceipt binds one parsed broker lifecycle event to the exact Connection object and socket epoch that read its wire frame. Session is process-local evidence, not durable order authority.

type OrderSide

type OrderSide string

OrderSide identifies the buy or sell direction of an order.

const (
	// OrderSideBuy identifies a buy order.
	OrderSideBuy OrderSide = "BUY"
	// OrderSideSell identifies a sell order.
	OrderSideSell OrderSide = "SELL"
)

type OrderStatus

type OrderStatus string

OrderStatus identifies the package's normalized lifecycle state for an order.

const (
	// OrderStatusNew means the order has been created locally.
	OrderStatusNew OrderStatus = "NEW"
	// OrderStatusPending means submission is in progress.
	OrderStatusPending OrderStatus = "PENDING"
	// OrderStatusSubmitted means the broker has received the order.
	OrderStatusSubmitted OrderStatus = "SUBMITTED"
	// OrderStatusAccepted means the broker has accepted the order.
	OrderStatusAccepted OrderStatus = "ACCEPTED"
	// OrderStatusPartial means part, but not all, of the quantity has filled.
	OrderStatusPartial OrderStatus = "PARTIAL"
	// OrderStatusFilled means the full quantity has filled.
	OrderStatusFilled OrderStatus = "FILLED"
	// OrderStatusCancelled means cancellation was requested locally or observed
	// from the broker; the value alone does not prove broker-final cancellation.
	OrderStatusCancelled OrderStatus = "CANCELLED"
	// OrderStatusRejected means the broker rejected the order.
	OrderStatusRejected OrderStatus = "REJECTED"
	// OrderStatusExpired means the order elapsed without filling.
	OrderStatusExpired OrderStatus = "EXPIRED"
)

type OrderType

type OrderType string

OrderType identifies the requested broker execution instruction.

const (
	// OrderTypeMarket identifies a market order.
	OrderTypeMarket OrderType = "MARKET"
	// OrderTypeLimit identifies a limit order.
	OrderTypeLimit OrderType = "LIMIT"
	// OrderTypeStop identifies a stop order.
	OrderTypeStop OrderType = "STOP"
	// OrderTypeStopLimit identifies a stop-limit order.
	OrderTypeStopLimit OrderType = "STOP_LIMIT"
	// OrderTypeMOC identifies a market-on-close order.
	OrderTypeMOC OrderType = "MOC"
	// OrderTypeLOC identifies a limit-on-close order.
	OrderTypeLOC OrderType = "LOC"
	// OrderTypePegMid identifies an order pegged to the midpoint.
	OrderTypePegMid OrderType = "PEG_MID"
)

type OrderWhatIfMargin

type OrderWhatIfMargin struct {
	Currency                string // Currency is the currency of the margin and equity values.
	InitialMarginBefore     *float64
	InitialMarginAfter      *float64
	MaintenanceMarginBefore *float64
	MaintenanceMarginAfter  *float64
	EquityWithLoanBefore    *float64
	EquityWithLoanAfter     *float64
	Commission              *float64
	MinCommission           *float64
	MaxCommission           *float64
	CommissionCurrency      string // CommissionCurrency is the currency of commission values.
	WarningText             string // WarningText is untrusted broker text and does not authorize submission.
}

OrderWhatIfMargin is the broker's pre-trade margin and commission estimate returned on a WhatIf openOrder callback. Margin values are monetary amounts in Currency, while commission values use CommissionCurrency. A nil numeric pointer means the broker omitted the field or supplied an unusable sentinel; zero is a reported numeric value.

type OrderWhatIfResult

type OrderWhatIfResult struct {
	OrderID            int    // OrderID is the request's broker order ID; zero means unavailable before allocation.
	Status             string // Status is the package-level WhatIf classification.
	BrokerStatus       string // BrokerStatus is the unnormalized status from the matching callback.
	Message            string // Message explains rejection or unavailability and may contain broker text.
	AdvancedRejectJSON string // AdvancedRejectJSON is opaque, untrusted broker rejection data.
	Margin             OrderWhatIfMargin
}

OrderWhatIfResult is a broker WhatIf evaluation. Status is one of the OrderWhatIfStatus constants. OrderID correlates this preview only, Message and AdvancedRejectJSON are untrusted broker text, and nil margin pointers mean the corresponding estimates were absent. The result is neither submit authority nor an order receipt.

type PacketLogger

type PacketLogger interface {
	// Outbound logs a fully framed payload (length-prefix excluded) that is about
	// to be written to the socket.
	Outbound(label string, payload []byte)
}

PacketLogger captures raw IBKR frames for offline inspection. It is intended for narrow debugging sessions (e.g. verifying wire encoding) and is disabled by default to avoid noisy disk writes on production paths.

type PaperOrderGate

type PaperOrderGate struct {
	Mode    string // Mode must equal "paper", ignoring case and surrounding space.
	Account string // Account must be a non-aggregate account whose name starts with DU.

	// Endpoint may contain host:port. When it parses successfully, it takes
	// precedence over Host and Port during validation.
	Endpoint string
	Host     string // Host is required when Endpoint does not supply one.
	Port     int    // Port is required when Endpoint does not supply one; zero means absent.
	ClientID int    // ClientID must be positive and match a nonzero configured client ID.
}

PaperOrderGate identifies the paper account and connection coordinates that the narrow paper-order wrappers validate before writing a frame. Mode must be "paper", Account must name a concrete DU account, ClientID must be positive, and Endpoint or Host and Port must identify the configured connection.

A valid PaperOrderGate is caller-supplied evidence, not authorization to submit or cancel an order, proof of the connected broker session's identity, or a broker acknowledgement. Callers remain responsible for preview, policy, freeze, journaling, and reconciliation controls.

type PortfolioProjectionBinding

type PortfolioProjectionBinding struct {
	Session    ConnectorSessionBinding
	Positions  []*RawPosition
	Health     PortfolioStreamHealth
	Generation uint64
}

PortfolioProjectionBinding is a caller-owned, exact-session snapshot of the structural portfolio projection and its typed stream receipt.

type PortfolioStreamHealth

type PortfolioStreamHealth struct {
	Account            string
	RequestedAt        time.Time
	InitialCompletedAt time.Time
	LastUpdateAt       time.Time
	// ProjectionGeneration advances only when the structural portfolio
	// authority changes: scope/completeness/invalidity, contract set, or held
	// quantity. Mark-to-market and PnL-only ticks deliberately do not advance it.
	ProjectionGeneration uint64
	// ScopeConflictAt is set when the stream emits a portfolio or completion
	// frame for a blank or foreign account. Rows are retained as context, but
	// no receipt is trustworthy until reqAccountUpdates is resubscribed.
	ScopeConflictAt time.Time
	// InvalidPayloadAt is set when a portfolio generation contains a malformed
	// required identity, quantity, or valuation field. The entire staged
	// generation is discarded; later completion/heartbeat frames cannot bless
	// a partial projection.
	InvalidPayloadAt time.Time
}

PortfolioStreamHealth is receipt metadata for the streaming reqAccountUpdates portfolio cache. It contains no positions or balances; callers use it only to decide whether a cached projection is current enough to support a trustworthy negative rather than an unprimed or silent stream.

type PositionDailyPnL

type PositionDailyPnL struct {
	DailyPnL           *float64
	UnrealizedTotalPnL *float64
	RealizedTotalPnL   *float64
	AsOf               time.Time
}

PositionDailyPnL is the most recent per-contract frame from an IBKR reqPnLSingle subscription. Monetary values are expressed in the account's base currency, and AsOf is the UTC receive time. Pointer fields use the same missing-versus-zero semantics as AccountDailyPnL. UnrealizedTotalPnL and RealizedTotalPnL are lifetime totals, not components of DailyPnL.

type PrewarmOptionChainResult

type PrewarmOptionChainResult struct {
	Expiry  string
	Cached  int
	Dropped int
	Elapsed time.Duration
	Err     error
}

PrewarmOptionChainResult reports per-expiry outcome of a bulk prewarm: the number of contracts cached and the round-trip duration. Useful for the daemon-side caller to surface in logs.

type RateLimitedRequest deprecated

type RateLimitedRequest struct {
	Type       RequestType
	Priority   RequestPriority
	Context    context.Context
	SendFunc   func(context.Context) error
	ResultChan chan error
	Timestamp  time.Time
	Retries    int
	MaxRetries int
}

RateLimitedRequest wraps a request with rate limiting metadata.

Deprecated: RateLimitedRequest is internal to the scheduler — no exported API accepts or returns it — and it will be unexported in the next major version.

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter manages rate limiting for IBKR API requests. The IBKR limits it enforces are recorded on the individual buckets and semaphores below.

func NewRateLimiter

func NewRateLimiter(ctx context.Context) *RateLimiter

NewRateLimiter creates a rate limiter with IBKR-compliant limits

func (*RateLimiter) AcquireMarketDataSlot

func (rl *RateLimiter) AcquireMarketDataSlot(ctx context.Context) error

AcquireMarketDataSlot acquires a market data subscription slot

func (*RateLimiter) GetMetrics

func (rl *RateLimiter) GetMetrics() RateLimiterMetrics

GetMetrics returns current rate limiter metrics

func (*RateLimiter) ReleaseMarketDataSlot

func (rl *RateLimiter) ReleaseMarketDataSlot()

ReleaseMarketDataSlot releases a market data subscription slot

func (*RateLimiter) Stop

func (rl *RateLimiter) Stop()

Stop gracefully shuts down the rate limiter. The request queue is not closed: producers (Submit and the retry goroutine) race with shutdown and would panic on send to a closed channel. Instead, ctx cancellation signals both producers and consumers to exit, and the queue is GC'd once unreferenced.

func (*RateLimiter) Submit

func (rl *RateLimiter) Submit(reqType RequestType, sendFunc func() error) error

Submit submits a request for rate-limited execution with the default retry count (3). For one-shot requests where any failure should bubble straight back to the caller (heartbeat path, test fixtures), use SubmitWithRetries(reqType, sendFunc, 0).

func (*RateLimiter) SubmitContext

func (rl *RateLimiter) SubmitContext(ctx context.Context, reqType RequestType, sendFunc func() error) error

SubmitContext submits a request for rate-limited execution and cancels the queue/token wait when ctx is done. The send function should also check ctx if it may block after the limiter admits it.

func (*RateLimiter) SubmitWithRetries

func (rl *RateLimiter) SubmitWithRetries(reqType RequestType, sendFunc func() error, maxRetries int) error

SubmitWithRetries submits a request with a custom retry count. Requests dispatch in arrival order; the only scheduling distinction is the context-carried pacing lane (see WithRequestPriority), which bounds how many token reservations PriorityBackground work may hold at once. A "queue jump" parameter existed before v0.16.0 but was never wired and was removed; the background lane is the deliberate replacement.

func (*RateLimiter) SubmitWithRetriesContext

func (rl *RateLimiter) SubmitWithRetriesContext(ctx context.Context, reqType RequestType, sendFunc func() error, maxRetries int) error

SubmitWithRetriesContext is SubmitWithRetries plus caller-owned cancellation. This matters for interactive historical reads: the historical bucket can legitimately wait minutes during breadth fan-out, but a CLI/RPC request with a 60 s budget must leave that queue promptly when its caller is gone.

func (*RateLimiter) SubmitWithRetriesContextFunc

func (rl *RateLimiter) SubmitWithRetriesContextFunc(ctx context.Context, reqType RequestType, sendFunc func(context.Context) error, maxRetries int) error

SubmitWithRetriesContextFunc passes the limiter-owned request context to the admitted callback. In addition to caller cancellation, that context is canceled synchronously by the limiter's own completion timeout, so work already admitted but parked behind another transport cannot run late.

type RateLimiterMetrics

type RateLimiterMetrics struct {
	TotalRequests        uint64
	ThrottledRequests    uint64
	RejectedRequests     uint64
	CurrentQueueDepth    int
	MessageRatePerSec    float64
	HistoricalRatePerMin float64
	LastRateLimitError   time.Time
	ConsecutiveErrors    int
}

RateLimiterMetrics tracks rate limiting statistics

type RawAccountSummary

type RawAccountSummary struct {
	AccountID            string
	AccountType          string
	NetLiquidation       *float64
	BuyingPower          *float64
	AvailableFunds       *float64
	ExcessLiquidity      *float64
	TotalCashValue       *float64
	MaintenanceMargin    *float64
	InitMarginReq        *float64
	GrossPositionValue   *float64
	UnrealizedPnL        *float64
	RealizedPnL          *float64
	Cushion              *float64
	LookAheadInitMargin  *float64
	LookAheadMaintMargin *float64
	LookAheadAvailable   *float64
	LookAheadExcess      *float64
	Currency             string
	// BaseCurrency and its provenance are intentionally distinct from
	// Currency. Currency is the legacy deterministic fallback used for numeric
	// rows; it must never be treated as proof of the account's base unit.
	BaseCurrency           string
	BaseCurrencyProvenance AccountBaseCurrencyProvenance
	// CurrencyLedger holds the per-currency rollup the gateway emitted
	// in response to the $LEDGER:ALL tag — one entry per non-BASE
	// currency present in the portfolio. Empty for same-currency
	// accounts. The "BASE" pseudo-currency entry IBKR emits is dropped
	// here because it duplicates the top-level totals already reported.
	CurrencyLedger map[string]CurrencyLedger
	AsOf           time.Time
	// Raw is the unparsed map from IBKR keyed exactly as the gateway returned it
	// (`<tag>` for BASE currency, `<tag>_<currency>` otherwise). Provided for
	// diagnostic and forward-compatibility purposes.
	Raw map[string]string
}

RawAccountSummary is a point-in-time view of the account values returned by IBKR. Currency-denominated top-level fields use the account's base-currency row when IBKR supplied one. If a base row is absent, the parser selects a currency-specific row deterministically. Currency records the first such fallback; Raw preserves the currency suffix for every field.

Fields are pointers when their absence is meaningful (IBKR may omit tags the user does not have permission for, e.g., margin fields on a cash account, or LookAhead* on cash). Callers must check for nil before dereferencing.

type RawOrder

type RawOrder struct {
	OrderID         int
	ClientID        int
	PermID          int
	Action          string // BUY or SELL
	TotalQty        int
	OrderType       string // MKT, LMT, STP, etc.
	LmtPrice        float64
	AuxPrice        float64 // Stop price for stop orders
	TrailStopPrice  float64
	TrailingPercent float64
	LmtPriceOffset  float64
	TIF             string // Time in force: DAY, GTC, IOC, etc.
	TriggerMethod   int    // IBKR stop trigger method for stop/trailing orders
	Account         string
	OrderRef        string // Our internal order ID
	OutsideRth      bool   // Allow execution outside regular trading hours
	OpenClose       string // O=open, C=close
}

RawOrder contains the broker-wire fields accepted by Connector order-write methods. Numeric price fields use the contract currency. Callers are responsible for supplying a broker-valid combination of order type, prices, quantity, time in force, account, and routing fields.

type RawPosition

type RawPosition struct {
	Account       string
	Contract      Contract
	Position      float64
	MarketPrice   float64
	MarketValue   float64
	AverageCost   float64
	UnrealizedPNL float64
	RealizedPNL   float64
}

RawPosition contains the latest broker-reported position and portfolio values for one contract.

type RequestPriority added in v2.7.0

type RequestPriority int

RequestPriority selects the pacing lane for a submitted request. The default (PriorityInteractive) is right for caller-facing work; bulk prewarm/fan-out traffic opts into PriorityBackground via WithRequestPriority so a cold-boot fan-out cannot starve an interactive read that arrives mid-flight.

const (
	// PriorityInteractive requests reserve pacing tokens immediately, in
	// arrival order. This is the default for any context without an
	// explicit priority.
	PriorityInteractive RequestPriority = iota
	// PriorityBackground requests must hold one of a small pool of
	// in-flight slots before reserving pacing tokens. The pool bounds how
	// many token reservations a fan-out can book ahead of an interactive
	// arrival, so the interactive request waits behind at most the pool,
	// not the whole fan-out. Token reservations stay FIFO across lanes and
	// slots release as sends complete, so background work keeps the full
	// bucket rate whenever no interactive request is competing — bounded
	// interactive delay, no starvation in either direction.
	PriorityBackground
)

type RequestType

type RequestType int

RequestType categorizes different IBKR request types for proper rate limiting

const (
	RequestTypeGeneral RequestType = iota
	RequestTypeMarketData
	RequestTypeHistorical
	RequestTypeOrder
	RequestTypeHeartbeat
)

Request types select the limiter bucket and pacing policy used for a call.

type ResolvedOrderContract

type ResolvedOrderContract struct {
	Contract Contract
	MinTick  float64
}

ResolvedOrderContract is an unambiguous broker contract-details identity captured on one exact Connector session. Contract always has a positive ConID; MinTick is zero only when the broker omitted it.

type ScannerInstrument

type ScannerInstrument struct {
	Name string `json:"name"`
	Type string `json:"type"`
}

ScannerInstrument names one instrument group supported by the gateway. Type is the wire identifier passed as ScannerSubscription.Instrument.

type ScannerLocation

type ScannerLocation struct {
	Code        string `json:"code"`
	DisplayName string `json:"display_name"`
}

ScannerLocation is one valid scanner location code. Code is the wire value passed as ScannerSubscription.Exchange, and DisplayName is broker-provided display text.

type ScannerParameters

type ScannerParameters struct {
	Instruments []ScannerInstrument `json:"instruments"`
	Locations   []ScannerLocation   `json:"locations"`
	ScanTypes   []ScannerScanType   `json:"scan_types"`
	RawXML      string              `json:"raw_xml,omitempty"`
}

ScannerParameters is the parsed catalog of scan codes, location codes, and instruments supported by the gateway this connector is attached to.

The catalog is a live gateway capability response and may vary by gateway version and market-data entitlements. RawXML retains the untrusted broker response for fields not represented by the typed slices.

func (*ScannerParameters) FilterByInstrument

func (p *ScannerParameters) FilterByInstrument(instrument string) []ScannerScanType

FilterByInstrument returns scan types whose Instruments contain instrument, matched case-insensitively after trimming a non-empty query. An empty string returns all scan types. Returned values share nested slice data with p and must be treated as read-only.

type ScannerRow

type ScannerRow struct {
	Rank         int
	Symbol       string
	SecType      string
	Exchange     string
	Currency     string
	LocalSymbol  string
	TradingClass string
	Distance     string
	Benchmark    string
	Projection   string
	Comment      string
}

ScannerRow is one broker-ranked entry from the first scanner result frame. Distance, Benchmark, Projection, and Comment are opaque broker strings. The row carries no broker timestamp; callers should treat it as observed during the Connector.RunScannerSubscription call.

type ScannerScanType

type ScannerScanType struct {
	Code        string   `json:"code"`
	DisplayName string   `json:"display_name"`
	Instruments []string `json:"instruments,omitempty"`
}

ScannerScanType is one valid scanner metric. Code is the wire value passed as ScannerSubscription.Type, DisplayName is broker-provided text, and Instruments contains the parsed instrument identifiers accepted by the scan.

type ScannerSubscription

type ScannerSubscription struct {
	Type       string // scanCode, e.g. TOP_PERC_GAIN
	Exchange   string // locationCode, e.g. STK.US.MAJOR
	Instrument string // e.g. STK; defaults to STK
	Limit      int    // numberOfRows; <=0 means default
}

ScannerSubscription contains the broker scanner fields supported by Connector.RunScannerSubscription. Type is the scan code, Exchange is the location code, Instrument defaults to "STK", and Limit values of zero or less use the broker default. Unsupported scanner filters are sent empty.

type Semaphore

type Semaphore struct {
	// contains filtered or unexported fields
}

Semaphore limits concurrent operations

func NewSemaphore

func NewSemaphore(capacity int) *Semaphore

NewSemaphore creates a semaphore with given capacity

func (*Semaphore) Acquire

func (s *Semaphore) Acquire(ctx context.Context) error

Acquire blocks until a slot is available

func (*Semaphore) Count

func (s *Semaphore) Count() int

Count returns current number of acquired slots

func (*Semaphore) Release

func (s *Semaphore) Release()

Release frees a slot. Panics if the semaphore is empty — an over-release is always a bookkeeping bug at the caller (mismatched Acquire/Release pair), and silently absorbing it would mask the root cause.

func (*Semaphore) TryAcquire

func (s *Semaphore) TryAcquire() bool

TryAcquire attempts to acquire without blocking

type SendDisposition

type SendDisposition string

SendDisposition classifies what an error proves about one broker instruction at the physical transport boundary. It says nothing about broker acceptance: even a nil local return still requires broker lifecycle evidence.

const (
	// SendDispositionDefinitelyUnsent proves that no byte from the instruction
	// reached the socket writer. Callers may safely discard provisional local
	// correlation created only for that attempt.
	SendDispositionDefinitelyUnsent SendDisposition = "definitely_unsent"
	// SendDispositionMayHaveWritten means at least one frame byte may have
	// reached the socket writer. The instruction must not be replayed blindly.
	SendDispositionMayHaveWritten SendDisposition = "may_have_written"
	// SendDispositionUnknown is the conservative fallback when an error source
	// cannot prove either of the stronger transport facts.
	SendDispositionUnknown SendDisposition = "unknown"
)

func SendDispositionOf

func SendDispositionOf(err error) SendDisposition

SendDispositionOf extracts the strongest transport fact attached to err. Untyped errors, including errors returned by custom broker hooks, are conservatively unknown. A nil error also has no send disposition and returns unknown; callers should classify only non-nil results.

type SendDispositionError

type SendDispositionError struct {
	// contains filtered or unexported fields
}

SendDispositionError preserves the original error while attaching a machine-readable broker-send disposition. Construct it with WithSendDisposition.

func (*SendDispositionError) Error

func (e *SendDispositionError) Error() string

Error returns the underlying broker-send error text.

func (*SendDispositionError) SendDisposition

func (e *SendDispositionError) SendDisposition() SendDisposition

SendDisposition returns the attached transport fact.

func (*SendDispositionError) Unwrap

func (e *SendDispositionError) Unwrap() error

Unwrap returns the underlying broker-send error.

type Subscription

type Subscription struct {
	Symbol string
	// SessionEpoch is set for exact-session subscriptions. Zero identifies a
	// legacy/shared subscription that cannot satisfy broker-write preview
	// evidence.
	SessionEpoch uint64
	// Right is the normalized option right ("C" or "P") for option-leg
	// subscriptions. It is empty for non-option subscriptions.
	Right     string
	ReqID     int
	Fields    []string
	LastPrice float64
	Bid       float64
	Ask       float64
	// MarkPrice is tick 37 — the gateway's calculated "fair" price for
	// the symbol. For tradeable instruments (ETFs, equities) it is
	// usually redundant with last/(bid+ask)/2; for indices like VIX,
	// VIX3M, and SPX, IBKR delivers tick 37 as the ONLY price (indices
	// don't trade, so they have no bid/ask/last). Consumers use this
	// as a final fallback so an index symbol still yields a usable
	// scalar when bid/ask/last all stay zero.
	MarkPrice float64
	BidSize   int64
	AskSize   int64
	Volume    int64
	AvgVolume int64
	// OpenInt is the option open interest at this contract: tick 27
	// (callOpenInterest) for CALL legs, tick 28 (putOpenInterest) for
	// PUT legs. The gateway also emits a zero-valued companion tick for
	// the opposite right, so only the tick matching Right is committed.
	// OpenIntObserved distinguishes "gateway sent zero OI for this right"
	// from "gateway has not delivered the matching OI tick yet".
	OpenInt         int64
	OpenIntObserved bool
	// ShortableShares is wire tick 89 (a tickSize), delivered for the
	// generic-tick-236 request. ShortableObserved distinguishes "IBKR
	// observed zero shares available" from "this subscription has not
	// delivered borrow inventory".
	ShortableShares   int64
	ShortableObserved bool
	// ShortableTickAt is when this process last received wire tick 89 for
	// ShortableShares. It is zero until that field is observed and does not
	// advance for other price, size, generic, or string ticks.
	ShortableTickAt time.Time
	PrevClose       float64
	Open            float64
	High            float64
	Low             float64
	// Week-range highs/lows arrive via generic tick 165 (Misc Stats) as
	// tickPrice messages with tick types 15-20. Captured here so consumers
	// (notably scan-row enrichment, where 52w range is a standard column)
	// can read them without a separate market-data call.
	Week13Low  float64
	Week13High float64
	Week26Low  float64
	Week26High float64
	Week52Low  float64
	Week52High float64
	// LastTradeTime is IBKR tick-string type 45, a Unix timestamp for the
	// last trade/close print. It is distinct from LastTime, which records
	// when this process observed any tick on the subscription.
	LastTradeTime time.Time
	// LastTickAt is when this process last received a tick message from the
	// gateway on this subscription. Unlike LastTime it is never seeded at
	// subscribe time and never advanced by subscription bookkeeping, so a
	// zero value means "no tick has ever arrived" rather than "not observed
	// recently". It is the only field here that can distinguish a live
	// subscription that has gone quiet from one that is ticking.
	//
	// Two limits bind every reader. It records arrival, not the instant the
	// value was struck: under frozen mode the gateway re-sends the last
	// known value on request, so a frozen quote's LastTickAt is essentially
	// read time however old the value is. And it advances on any tick,
	// including size, volume and IV ticks, so a subscription delivering only
	// size ticks looks alive while its price is frozen.
	LastTickAt time.Time
	// LastPriceTickAt is when this process last accepted a positive price tick
	// from the gateway on this subscription. It is never seeded at subscribe
	// time and does not advance for blank or rejected price payloads, size,
	// volume, IV, or last-trade-time ticks. RTVolume advances it only when that
	// payload carries a positive last price.
	//
	// Like LastTickAt, this is an arrival instant rather than the instant the
	// broker value was struck: frozen data can still arrive now while carrying
	// an older value. It is price-specific, not per-field; a new high, close, or
	// week-range price advances the same clock as bid, ask, last, and mark.
	LastPriceTickAt time.Time
	// IV is the option implied volatility tick (generic tick 106), present
	// only when the streaming subscribe requested it. Stored as a fraction
	// (0.234 == 23.4%); the gateway sometimes emits the percent form, which
	// the handler normalizes.
	IV float64
	// LastTime is the re-request staleness clock read by
	// EnsureMarketDataSubscription. It is seeded at subscribe time and
	// advanced by subscription bookkeeping as well as by ticks, so it is not
	// an observation instant — use LastTickAt for that.
	LastTime time.Time
	Observed bool // true once we receive any tick for this reqID
	// RejectCh receives a [SubscriptionRejection] when the gateway returns
	// a terminal error for this reqID (codes 200, 320, 321, 322, 354,
	// 10197) — "the subscription will never produce ticks" semantics.
	// Buffered 1; the producer drops on a full buffer so it never blocks
	// the error-handler goroutine. A nil channel means fast-abort is
	// disabled (used by test fixtures that bypass the Subscribe path).
	RejectCh chan SubscriptionRejection
	// contains filtered or unexported fields
}

Subscription holds the latest values observed for one streaming market-data request. Zero-valued fields may mean either an observed zero or data not yet received; fields with an accompanying Observed flag distinguish those cases. LastTime is the subscription bookkeeping clock, LastTickAt is the any-tick liveness clock, and LastPriceTickAt is the accepted-price observation clock; they differ and are documented on the fields.

type SubscriptionRejection

type SubscriptionRejection struct {
	Code    int
	Message string
}

SubscriptionRejection records a terminal IBKR error for a market-data subscription. Code is the broker error code and Message is untrusted broker text. Receiving a value means that request will not produce further ticks.

type TimeInForce

type TimeInForce string

TimeInForce identifies how long an order remains eligible for execution.

const (
	// TimeInForceDay keeps an order active for the current trading day.
	TimeInForceDay TimeInForce = "DAY"
	// TimeInForceGTC keeps an order active until it fills or is cancelled.
	TimeInForceGTC TimeInForce = "GTC"
	// TimeInForceIOC requests immediate execution and cancels any remainder.
	TimeInForceIOC TimeInForce = "IOC"
	// TimeInForceFOK requires immediate execution of the full quantity.
	TimeInForceFOK TimeInForce = "FOK"
	// TimeInForceGTD keeps an order active through its specified date.
	TimeInForceGTD TimeInForce = "GTD"
	// TimeInForceOPG requests execution at the market open.
	TimeInForceOPG TimeInForce = "OPG"
)

type TokenBucket

type TokenBucket struct {
	// contains filtered or unexported fields
}

TokenBucket implements token bucket algorithm for rate limiting

func NewTokenBucket

func NewTokenBucket(capacity int, refillRate float64) *TokenBucket

NewTokenBucket creates a new token bucket

func (*TokenBucket) TryAcquire

func (tb *TokenBucket) TryAcquire(n int) bool

TryAcquire attempts to acquire n tokens, returns true if successful

func (*TokenBucket) WaitForTokens

func (tb *TokenBucket) WaitForTokens(ctx context.Context, n int) error

WaitForTokens blocks until n tokens are available

type WSHEarningsResult

type WSHEarningsResult struct {
	EventJSON     string
	StockIdentity *ContractDetailsLite
}

WSHEarningsResult pairs WSH event JSON with an optional exact broker stock identity. StockIdentity is nil unless a fresh positive-ConID contract-details row matched the requested ConID, stock security type, and symbol.

type WSHError

type WSHError struct {
	Kind      WSHErrorKind
	Operation string
	Code      int
	// contains filtered or unexported fields
}

WSHError describes a failed read-only Wall Street Horizon request. Operation and Code are allowlisted protocol facts; broker and transport prose is not retained. Context cancellation is the only wrapped cause.

func (*WSHError) Error

func (e *WSHError) Error() string

Error returns a sanitized classification without broker response prose.

func (*WSHError) Unwrap

func (e *WSHError) Unwrap() error

Unwrap exposes only a caller context cancellation or deadline cause.

type WSHErrorKind

type WSHErrorKind string

WSHErrorKind is a stable, sanitized classification for a failed Wall Street Horizon request. Gateway prose is deliberately not retained: consumers can branch on Kind and Code without persisting an untrusted broker message.

const (
	// WSHErrorCanceled means the caller canceled the queued or active request.
	WSHErrorCanceled WSHErrorKind = "canceled"
	// WSHErrorTimeout means the caller's deadline expired.
	WSHErrorTimeout WSHErrorKind = "timeout"
	// WSHErrorTransport means no usable broker transport was available.
	WSHErrorTransport WSHErrorKind = "transport_failure"
	// WSHErrorUnsupportedProtocol means TWS or Gateway is too old for the request.
	WSHErrorUnsupportedProtocol WSHErrorKind = "unsupported_protocol"
	// WSHErrorConnectorInactive means the current connector temporarily marked
	// the symbol inactive after repeated definition failures. The mark expires
	// after a bounded interval and is cleared on reconnect, so callers must not
	// persist it as a provider verdict about the security.
	WSHErrorConnectorInactive WSHErrorKind = "connector_inactive"
	// WSHErrorUnsupportedSecurity means WSH cannot be queried for the instrument.
	WSHErrorUnsupportedSecurity WSHErrorKind = "unsupported_security"
	// WSHErrorContractResolution means the stock conId could not be resolved.
	WSHErrorContractResolution WSHErrorKind = "contract_resolution_failure"
	// WSHErrorEntitlementRequired means the account lacks the WSH subscription.
	WSHErrorEntitlementRequired WSHErrorKind = "entitlement_required"
	// WSHErrorDuplicateRequest means TWS rejected a concurrent WSH request.
	WSHErrorDuplicateRequest WSHErrorKind = "duplicate_request"
	// WSHErrorMetadataRequired means event data was requested without current metadata.
	WSHErrorMetadataRequired WSHErrorKind = "metadata_required"
	// WSHErrorProviderFailure means WSH rejected or failed the request.
	WSHErrorProviderFailure WSHErrorKind = "provider_failure"
	// WSHErrorMalformedResponse means WSH returned empty or invalid JSON.
	WSHErrorMalformedResponse WSHErrorKind = "malformed_response"
	// WSHErrorEventTypeUnavailable means metadata did not advertise earnings dates.
	WSHErrorEventTypeUnavailable WSHErrorKind = "event_type_unavailable"
)

type WireDirection

type WireDirection string

WireDirection indicates message flow relative to the IBKR gateway.

const (
	WireOutbound WireDirection = "OUT"
	WireInbound  WireDirection = "IN"
)

Wire directions are relative to the client connection.

type WireFrame

type WireFrame struct {
	Seq         uint64        `json:"seq"`
	When        time.Time     `json:"ts"`
	Direction   WireDirection `json:"direction"`
	MsgID       int           `json:"msg_id"`
	MsgName     string        `json:"msg_name"`
	ReqID       string        `json:"req_id,omitempty"`
	Symbol      string        `json:"symbol,omitempty"`
	LengthBytes string        `json:"len_hex,omitempty"`
	Fields      []string      `json:"fields"`
	RawHex      string        `json:"hex"`
	Notes       string        `json:"notes,omitempty"`
}

WireFrame captures a single encoded message with decoded fields.

type WireInterceptor

type WireInterceptor struct {
	// contains filtered or unexported fields
}

WireInterceptor passively records the IBKR wire protocol for diagnostics. Off by default; enable with IBKR_WIRE_INTERCEPTOR=1. The recorder mirrors every frame into a per-process ring buffer (size IBKR_WIRE_RING_SIZE, default 256) and, when IBKR_WIRE_LOG_PATH is set, also appends one JSON object per line to the named file. Captured frames are account-sensitive — see SECURITY.md.

func NewWireInterceptorFromEnv

func NewWireInterceptorFromEnv(clientID int) (*WireInterceptor, error)

NewWireInterceptorFromEnv instantiates a wire interceptor using environment flags.

func (*WireInterceptor) Close

func (w *WireInterceptor) Close() error

Close releases any resources associated with the interceptor.

func (*WireInterceptor) Enabled

func (w *WireInterceptor) Enabled() bool

Enabled returns true if the interceptor is active.

func (*WireInterceptor) RecordInbound

func (w *WireInterceptor) RecordInbound(msgID int, raw []byte, fields []string)

RecordInbound records an incoming frame from IBKR.

func (*WireInterceptor) RecordOutbound

func (w *WireInterceptor) RecordOutbound(msgID int, raw []byte, fields []string)

RecordOutbound processes an outgoing frame. fields may be nil; in that case decode will be skipped.

Directories

Path Synopsis
internal
logging
Package logging is a tiny slog-backed shim that preserves the call-site API the ibkr package was originally written against (Component(name).Debugf/Infof/...).
Package logging is a tiny slog-backed shim that preserves the call-site API the ibkr package was originally written against (Component(name).Debugf/Infof/...).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL