Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/quant_platform_kit/common/runtime_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,12 +448,18 @@ def build_account_state_from_portfolio_snapshot(
if resolved_liquid_cash is None:
resolved_liquid_cash = 0.0

total_strategy_equity = (
float(resolved_liquid_cash) + sum(float(value) for value in market_values.values())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Include all duplicate strategy positions in equity

When a filtered snapshot contains more than one Position for the same strategy symbol, this sums market_values after the loop above has overwritten earlier rows for that symbol. That can happen with the IBKR snapshot path when multiple selected accounts hold the same ticker (fetch_portfolio_snapshot appends per-account positions while summing account values), so total_strategy_equity will include only the last account's holding plus cash and understate the strategy equity. Sum the matching positions directly or aggregate duplicate symbols before computing this value.

Useful? React with 👍 / 👎.

if filter_enabled
else float(snapshot.total_equity)
)

account_state = {
"available_cash": float(resolved_liquid_cash),
"market_values": market_values,
"quantities": quantities,
"sellable_quantities": sellable_quantities,
"total_strategy_equity": float(snapshot.total_equity),
"total_strategy_equity": total_strategy_equity,
}
raw_cash_by_currency = (
metadata.get("cash_by_currency") if isinstance(metadata, Mapping) else None
Expand Down
17 changes: 16 additions & 1 deletion tests/test_strategy_contracts.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,24 @@ def test_build_account_state_from_portfolio_snapshot_filters_strategy_symbols(se
account_state["sellable_quantities"],
{"TQQQ": 3, "BOXX": 10, "QQQI": 0},
)
self.assertEqual(account_state["total_strategy_equity"], 50000.0)
self.assertEqual(account_state["total_strategy_equity"], 14000.0)
self.assertEqual(account_state["cash_by_currency"], {"USD": 8000.0, "SGD": 350.0})

def test_build_account_state_without_strategy_symbols_preserves_snapshot_equity(self) -> None:
snapshot = PortfolioSnapshot(
as_of="2026-04-09",
total_equity=50000.0,
buying_power=12000.0,
positions=(
Position(symbol="TQQQ", quantity=5, market_value=1000.0),
Position(symbol="QQQ", quantity=99, market_value=9999.0),
),
)

account_state = build_account_state_from_portfolio_snapshot(snapshot)

self.assertEqual(account_state["total_strategy_equity"], 50000.0)

def test_build_portfolio_snapshot_from_account_state_keeps_strategy_symbol_order(self) -> None:
snapshot = build_portfolio_snapshot_from_account_state(
{
Expand Down