summaryrefslogtreecommitdiff
path: root/tests/integration/test_portfolio_tracking_flow.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/integration/test_portfolio_tracking_flow.py')
-rw-r--r--tests/integration/test_portfolio_tracking_flow.py59
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