Skip to content

fix: Portfolio NAV snapshot understates total_net_gain by ~3x (#397)#399

Merged
MDUYN merged 2 commits into
devfrom
fix/portfolio-net-gain-understatement-397
Mar 19, 2026
Merged

fix: Portfolio NAV snapshot understates total_net_gain by ~3x (#397)#399
MDUYN merged 2 commits into
devfrom
fix/portfolio-net-gain-understatement-397

Conversation

@MDUYN
Copy link
Copy Markdown
Collaborator

@MDUYN MDUYN commented Mar 19, 2026

Summary

Closes #397

Fixes portfolio NAV snapshot total_net_gain being understated by ~3x due to two bugs in the trade service's sell order accounting.

Root Cause

Bug 1 (Primary): Accumulated cost double-counting

In create_order_metadata_with_trade_context, when a sell order closes multiple trades, the cost variable accumulated across loop iterations but the entire accumulated cost was subtracted from each trade's revenue:

# BEFORE (buggy):
cost = 0
net_gain = 0
for metadata in order_metadatas:
    cost += trade.open_price * metadata.amount
    net_gain += (sell_price * metadata.amount) - cost  # subtracts ALL prior costs again

With N trades, earlier costs were subtracted N times → systematic understatement proportional to the number of overlapping trades.

Bug 2 (Secondary): Wrong amount in per-trade net_gain

In _create_trade_metadata_with_sell_order_and_trades, sell_amount (total sell order) was used instead of trade_data["amount"] (per-trade portion) in the net_gain calculation, overcounting gain per trade when a sell order was split across trades.

Fix

# AFTER (fixed):
cost = 0
net_gain = 0
for metadata in order_metadatas:
    trade_cost = trade.open_price * metadata.amount
    cost += trade_cost
    net_gain += (sell_price * metadata.amount) - trade_cost  # only THIS trade's cost

The cost accumulator remains correct for position.cost -= cost below. Only the net_gain calculation changes.

Files Changed

  • investing_algorithm_framework/services/trade_service/trade_service.py — Two fixes (per-iteration cost, per-trade amount)
  • tests/services/test_trade_service_net_gain.py (new) — 3 regression tests

Tests

All 161 app tests + 451 service/scenario tests + 3 new regression tests pass.

MDUYN added 2 commits March 19, 2026 16:09
… by ~3x (#397)

Bug 1: In create_order_metadata_with_trade_context, the cost variable
accumulated across loop iterations but the entire accumulated value was
subtracted from each trade's revenue. With N trades, earlier costs were
subtracted N times instead of once, systematically understating net_gain.
Fix: use per-iteration trade_cost variable.

Bug 2: In _create_trade_metadata_with_sell_order_and_trades, net_gain
used sell_amount (total sell order) instead of trade_data['amount']
(per-trade portion), overcounting gain per trade when a sell order
was split across multiple trades. Fix: use trade_data['amount'].

Added 3 regression tests in tests/services/test_trade_service_net_gain.py.
@MDUYN MDUYN merged commit 424998e into dev Mar 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant