diff options
| author | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-01 17:05:45 +0900 |
|---|---|---|
| committer | TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> | 2026-04-01 17:05:45 +0900 |
| commit | b8dc7344ff99eb23d5f003795f17cdba3b89c40b (patch) | |
| tree | b072312d8c7b3dcd6c0f2e521370deb9a6758630 /tests/integration/test_portfolio_tracking_flow.py | |
| parent | b4624c77de2ea615a65c04a39d657a38ff2a7c95 (diff) | |
test: add integration tests for strategy, order, portfolio, and backtest flows
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 |
