summaryrefslogtreecommitdiff
path: root/tests/integration/test_portfolio_tracking_flow.py
blob: 386e78f149fd28fac5cce5f09629edf9adb83586 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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