The header's "matched" subtotal used the FIFO round-trip sum, which doesn't equal the broker's average-cost day P&L while positions are partially open — so "matched + open" never tied to the headline day P&L (e.g. -1340 + open vs the broker's -627). Show broker-authoritative realized instead: matched = day P&L - open unrealized, so matched + open == day P&L by construction. Per-trade rows stay FIFO-accurate (each is a real fill pair); only the header subtotal is broker-truth. Factor the open-unrealized sum into a shared helper used by both the live board and the `journal` close capture. Falls back to the FIFO sum when no equity snapshot exists. Verified live: board + journal both reconcile (matched + open == day P&L). Tests: 3 new (reconciliation invariant + FIFO fallback). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
30 lines
1.2 KiB
Python
30 lines
1.2 KiB
Python
"""Board/journal P&L header: the broker-authoritative split must reconcile.
|
|
|
|
The header shows `day P&L (matched M · open O)`. M is broker-authoritative
|
|
realized (day P&L minus current open unrealized) so M + O == day P&L exactly,
|
|
even though the per-trade rows use FIFO lot accounting (whose sum can differ on
|
|
partially-closed names). When the broker day P&L is unavailable, M falls back
|
|
to the FIFO realized sum.
|
|
"""
|
|
|
|
from momentum_cli import _matched_realized
|
|
|
|
|
|
def test_matched_plus_open_equals_day_pnl():
|
|
day_pnl, open_unreal, fifo = -652.0, -339.0, -1339.0
|
|
matched = _matched_realized(day_pnl, open_unreal, fifo)
|
|
assert matched == day_pnl - open_unreal # broker-authoritative
|
|
assert abs((matched + open_unreal) - day_pnl) < 1e-9 # reconciles exactly
|
|
assert matched != fifo # not the FIFO sum
|
|
|
|
|
|
def test_matched_reconciles_for_a_profitable_day():
|
|
day_pnl, open_unreal, fifo = 1200.0, 800.0, 50.0
|
|
matched = _matched_realized(day_pnl, open_unreal, fifo)
|
|
assert matched == 400.0 and matched + open_unreal == day_pnl
|
|
|
|
|
|
def test_matched_falls_back_to_fifo_when_day_pnl_missing():
|
|
# no broker equity snapshot -> use the FIFO realized sum
|
|
assert _matched_realized(None, -339.0, -1339.0) == -1339.0
|