Skip to content

[IBKR] Use broker NetLiquidation and refresh option position marks from snapshots #314

@randomradio

Description

@randomradio

Symptom

IBKR account and position reporting can drift from TWS/IB Gateway values:

  • IbkrBroker.getAccount() reconstructs netLiquidation from cash plus cached position market values whenever positions exist, even when IBKR account summary exposes an authoritative NetLiquidation value.
  • If requestAccountSummary() is unavailable, the fallback should be the cached account NetLiquidation value before reconstructing from positions.
  • IbkrBroker.getPositions() currently returns cached updatePortfolio() marks directly. Those marks can freeze after market hours; for option positions we should refresh from snapshot bid/ask when available and recompute market value / unrealized PnL.
  • RequestBridge.updatePortfolio() should deduplicate repeated callbacks for the same account + contract instead of appending duplicate positions during a batch.

Evidence / repro

A local regression spec has been drafted at:

services/uta/src/domain/trading/brokers/ibkr/IbkrBroker.spec.ts

The spec covers:

  1. getAccount() prefers account-summary NetLiquidation over reconstructed position values.
  2. getAccount() falls back to cached account values when account summary is unavailable.
  3. Net liquidation is reconstructed only when no broker NetLiquidation is available.
  4. getPositions() refreshes option marks using snapshot quote bid/ask and recalculates market value / unrealized PnL.
  5. getPositions() keeps cached updatePortfolio() values if the snapshot quote fails.
  6. RequestBridge deduplicates repeated updatePortfolio callbacks by account and contract, preserving the newest values.

Suspected locations

  • services/uta/src/domain/trading/brokers/ibkr/IbkrBroker.ts around getAccount() and getPositions()
  • services/uta/src/domain/trading/brokers/ibkr/request-bridge.ts around updatePortfolio()

Expected behavior

  • Account-level NetLiquidation from IBKR wins whenever available.
  • Cached account-level NetLiquidation is the fallback if summary fetch fails.
  • Position-derived reconstruction is only a last resort.
  • Option position marks use snapshot midpoint (bid + ask) / 2 when snapshot data is available, with cached values retained on quote failure.
  • Repeated portfolio callbacks update the existing cache entry instead of duplicating the position.

Related context

This is adjacent to #295, but distinct: #295 is about account-value keys overwriting across currencies; this issue is about account valuation precedence, stale option marks, and duplicate portfolio rows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions