diff --git a/apps/web/routers/paper_trading.py b/apps/web/routers/paper_trading.py index 7c976ff..13ce5f5 100644 --- a/apps/web/routers/paper_trading.py +++ b/apps/web/routers/paper_trading.py @@ -314,13 +314,19 @@ def get_positions(session_id: str) -> dict[str, Any]: is_parking = parking_symbol and p.symbol == parking_symbol if ss is None and not is_parking: continue # Only show positions tracked by this session - # Use locally-recorded entry price/qty for strategy positions to avoid - # orphaned-share contamination of Alpaca's blended avg_entry_price. + # Use locally-recorded entry price/qty to avoid cross-session contamination + # of Alpaca's blended avg_entry_price (multiple sessions share one broker account). ot = open_trades.get(p.symbol) if not is_parking else None - qty = float(ot["shares"]) if ot and ot.get("shares") else float(p.qty) - entry = float(ot["entry_price"]) if ot and ot.get("entry_price") else ( - float(p.avg_entry_price) if p.avg_entry_price else 0.0 - ) + if is_parking and parking_state: + qty = float(parking_state.get("qty") or p.qty) + entry = float(parking_state["avg_price"]) if parking_state.get("avg_price") else ( + float(p.avg_entry_price) if p.avg_entry_price else 0.0 + ) + else: + qty = float(ot["shares"]) if ot and ot.get("shares") else float(p.qty) + entry = float(ot["entry_price"]) if ot and ot.get("entry_price") else ( + float(p.avg_entry_price) if p.avg_entry_price else 0.0 + ) cur_price = float(p.current_price) if p.current_price else None pnl = (cur_price - entry) * qty if cur_price and entry and qty else float(p.unrealized_pl) pnl_pct = pnl / (entry * qty) * 100 if entry and qty else 0.0