summaryrefslogtreecommitdiff
path: root/services/portfolio-manager/src/portfolio_manager/portfolio.py
diff options
context:
space:
mode:
authorTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-04-01 17:55:44 +0900
committerTheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com>2026-04-01 17:55:44 +0900
commita65575124b18f2ec5d418623e22c5bdef6c3424e (patch)
tree2e9f9e2b66083c54adf017c3676d970a6b34d0d5 /services/portfolio-manager/src/portfolio_manager/portfolio.py
parent70a33a5236fd9c3b51b8db0cbaf11376f9817ac5 (diff)
feat(portfolio): track realized PnL on sell orders
Diffstat (limited to 'services/portfolio-manager/src/portfolio_manager/portfolio.py')
-rw-r--r--services/portfolio-manager/src/portfolio_manager/portfolio.py13
1 files changed, 11 insertions, 2 deletions
diff --git a/services/portfolio-manager/src/portfolio_manager/portfolio.py b/services/portfolio-manager/src/portfolio_manager/portfolio.py
index 2c93643..4a7a11f 100644
--- a/services/portfolio-manager/src/portfolio_manager/portfolio.py
+++ b/services/portfolio-manager/src/portfolio_manager/portfolio.py
@@ -18,6 +18,11 @@ class PortfolioTracker:
def __init__(self) -> None:
self._positions: dict[str, _PositionState] = {}
+ self._realized_pnl: Decimal = Decimal("0")
+
+ @property
+ def realized_pnl(self) -> Decimal:
+ return self._realized_pnl
def _get_or_create(self, symbol: str) -> _PositionState:
if symbol not in self._positions:
@@ -35,8 +40,12 @@ class PortfolioTracker:
if state.quantity > Decimal("0"):
state.avg_entry = total_cost / state.quantity
elif order.side == OrderSide.SELL:
- state.quantity -= order.quantity
- # Keep avg_entry unchanged unless fully sold
+ # Calculate realized PnL for this sell
+ sell_quantity = min(order.quantity, state.quantity)
+ if sell_quantity > 0 and state.avg_entry > 0:
+ self._realized_pnl += sell_quantity * (order.price - state.avg_entry)
+
+ state.quantity -= sell_quantity
if state.quantity <= Decimal("0"):
state.quantity = Decimal("0")
state.avg_entry = Decimal("0")