diff options
Diffstat (limited to 'tests/integration/test_portfolio_tracking_flow.py')
| -rw-r--r-- | tests/integration/test_portfolio_tracking_flow.py | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/tests/integration/test_portfolio_tracking_flow.py b/tests/integration/test_portfolio_tracking_flow.py new file mode 100644 index 0000000..386e78f --- /dev/null +++ b/tests/integration/test_portfolio_tracking_flow.py @@ -0,0 +1,59 @@ +"""Integration test: order -> portfolio tracker -> position state.""" +import sys +from pathlib import Path + +sys.path.insert(0, str(Path(__file__).resolve().parents[2] / "services" / "portfolio-manager" / "src")) + +import pytest +from decimal import Decimal +from datetime import datetime, timezone + +from shared.models import Order, OrderSide, OrderType, OrderStatus +from portfolio_manager.portfolio import PortfolioTracker + + +def test_portfolio_tracks_buy_sell_cycle(): + """Buy then sell should update position and reset on full sell.""" + tracker = PortfolioTracker() + + buy_order = Order( + signal_id="sig-1", symbol="BTCUSDT", side=OrderSide.BUY, + type=OrderType.MARKET, price=Decimal("50000"), + quantity=Decimal("0.1"), status=OrderStatus.FILLED, + ) + tracker.apply_order(buy_order) + + pos = tracker.get_position("BTCUSDT") + assert pos is not None + assert pos.quantity == Decimal("0.1") + assert pos.avg_entry_price == Decimal("50000") + + sell_order = Order( + signal_id="sig-2", symbol="BTCUSDT", side=OrderSide.SELL, + type=OrderType.MARKET, price=Decimal("55000"), + quantity=Decimal("0.1"), status=OrderStatus.FILLED, + ) + tracker.apply_order(sell_order) + + pos = tracker.get_position("BTCUSDT") + assert pos is None # Fully sold + + +def test_portfolio_weighted_average_on_multiple_buys(): + """Multiple buys at different prices should compute weighted average.""" + tracker = PortfolioTracker() + + tracker.apply_order(Order( + signal_id="s1", symbol="BTCUSDT", side=OrderSide.BUY, + type=OrderType.MARKET, price=Decimal("50000"), + quantity=Decimal("0.1"), status=OrderStatus.FILLED, + )) + tracker.apply_order(Order( + signal_id="s2", symbol="BTCUSDT", side=OrderSide.BUY, + type=OrderType.MARKET, price=Decimal("60000"), + quantity=Decimal("0.1"), status=OrderStatus.FILLED, + )) + + pos = tracker.get_position("BTCUSDT") + assert pos.quantity == Decimal("0.2") + assert pos.avg_entry_price == Decimal("55000") # weighted avg |
