summaryrefslogtreecommitdiff
path: root/shared/tests/test_models.py
blob: 40bb7911f85e4288dbdc973f30dff92bf30ddb99 (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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""Tests for shared models and settings."""

import os
from datetime import UTC, datetime
from decimal import Decimal
from unittest.mock import patch


def test_settings_defaults():
    """Test that Settings has correct defaults."""
    from shared.config import Settings

    with patch.dict(os.environ, {}, clear=False):
        settings = Settings()
        assert settings.redis_url.get_secret_value() == "redis://localhost:6379"
        assert (
            settings.database_url.get_secret_value()
            == "postgresql://trading:trading@localhost:5432/trading"
        )
        assert settings.log_level == "INFO"
        assert settings.risk_max_position_size == 0.1
        assert settings.risk_stop_loss_pct == 5.0
        assert settings.risk_daily_loss_limit_pct == 10.0
        assert settings.dry_run is True


def test_candle_creation():
    """Test Candle model creation."""
    from shared.models import Candle

    now = datetime.now(UTC)
    candle = Candle(
        symbol="AAPL",
        timeframe="1m",
        open_time=now,
        open=Decimal("50000.00"),
        high=Decimal("51000.00"),
        low=Decimal("49500.00"),
        close=Decimal("50500.00"),
        volume=Decimal("100.5"),
    )
    assert candle.symbol == "AAPL"
    assert candle.timeframe == "1m"
    assert candle.open == Decimal("50000.00")
    assert candle.high == Decimal("51000.00")
    assert candle.low == Decimal("49500.00")
    assert candle.close == Decimal("50500.00")
    assert candle.volume == Decimal("100.5")


def test_signal_creation():
    """Test Signal model creation."""
    from shared.models import OrderSide, Signal

    signal = Signal(
        strategy="rsi_strategy",
        symbol="AAPL",
        side=OrderSide.BUY,
        price=Decimal("50000.00"),
        quantity=Decimal("0.01"),
        reason="RSI oversold",
    )
    assert signal.strategy == "rsi_strategy"
    assert signal.symbol == "AAPL"
    assert signal.side == OrderSide.BUY
    assert signal.price == Decimal("50000.00")
    assert signal.quantity == Decimal("0.01")
    assert signal.reason == "RSI oversold"
    assert signal.id is not None
    assert signal.created_at is not None


def test_order_creation():
    """Test Order model creation with defaults."""
    import uuid

    from shared.models import Order, OrderSide, OrderStatus, OrderType

    signal_id = str(uuid.uuid4())
    order = Order(
        signal_id=signal_id,
        symbol="AAPL",
        side=OrderSide.BUY,
        type=OrderType.MARKET,
        price=Decimal("50000.00"),
        quantity=Decimal("0.01"),
    )
    assert order.id is not None
    assert order.signal_id == signal_id
    assert order.status == OrderStatus.PENDING
    assert order.filled_at is None
    assert order.created_at is not None


def test_signal_conviction_default():
    """Test Signal defaults for conviction, stop_loss, take_profit."""
    from shared.models import OrderSide, Signal

    signal = Signal(
        strategy="rsi",
        symbol="AAPL",
        side=OrderSide.BUY,
        price=Decimal("50000"),
        quantity=Decimal("0.01"),
        reason="test",
    )
    assert signal.conviction == 1.0
    assert signal.stop_loss is None
    assert signal.take_profit is None


def test_signal_with_stops():
    """Test Signal with explicit conviction, stop_loss, take_profit."""
    from shared.models import OrderSide, Signal

    signal = Signal(
        strategy="rsi",
        symbol="AAPL",
        side=OrderSide.BUY,
        price=Decimal("50000"),
        quantity=Decimal("0.01"),
        reason="test",
        conviction=0.8,
        stop_loss=Decimal("48000"),
        take_profit=Decimal("55000"),
    )
    assert signal.conviction == 0.8
    assert signal.stop_loss == Decimal("48000")
    assert signal.take_profit == Decimal("55000")


def test_position_unrealized_pnl():
    """Test Position unrealized_pnl computed property."""
    from shared.models import Position

    position = Position(
        symbol="AAPL",
        quantity=Decimal("0.1"),
        avg_entry_price=Decimal("50000"),
        current_price=Decimal("51000"),
    )
    # 0.1 * (51000 - 50000) = 100
    assert position.unrealized_pnl == Decimal("100")