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:
getAccount() prefers account-summary NetLiquidation over reconstructed position values.
getAccount() falls back to cached account values when account summary is unavailable.
- Net liquidation is reconstructed only when no broker
NetLiquidation is available.
getPositions() refreshes option marks using snapshot quote bid/ask and recalculates market value / unrealized PnL.
getPositions() keeps cached updatePortfolio() values if the snapshot quote fails.
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.
Symptom
IBKR account and position reporting can drift from TWS/IB Gateway values:
IbkrBroker.getAccount()reconstructsnetLiquidationfrom cash plus cached position market values whenever positions exist, even when IBKR account summary exposes an authoritativeNetLiquidationvalue.requestAccountSummary()is unavailable, the fallback should be the cached accountNetLiquidationvalue before reconstructing from positions.IbkrBroker.getPositions()currently returns cachedupdatePortfolio()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.tsThe spec covers:
getAccount()prefers account-summaryNetLiquidationover reconstructed position values.getAccount()falls back to cached account values when account summary is unavailable.NetLiquidationis available.getPositions()refreshes option marks using snapshot quote bid/ask and recalculates market value / unrealized PnL.getPositions()keeps cachedupdatePortfolio()values if the snapshot quote fails.RequestBridgededuplicates repeatedupdatePortfoliocallbacks by account and contract, preserving the newest values.Suspected locations
services/uta/src/domain/trading/brokers/ibkr/IbkrBroker.tsaroundgetAccount()andgetPositions()services/uta/src/domain/trading/brokers/ibkr/request-bridge.tsaroundupdatePortfolio()Expected behavior
NetLiquidationfrom IBKR wins whenever available.NetLiquidationis the fallback if summary fetch fails.(bid + ask) / 2when snapshot data is available, with cached values retained on quote failure.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.