Files
momentum-system/tests/unit/test_journal_pnl.py
T
momentum devandClaude Opus 4.8 bace33edfd Board/journal: broker-authoritative realized in the P&L header
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>
2026-06-18 14:42:35 -04:00

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