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
|
"""Tests for shared models and settings."""
import os
from decimal import Decimal
from datetime import datetime, timezone
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(timezone.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 Signal, OrderSide
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."""
from shared.models import Order, OrderSide, OrderType, OrderStatus
import uuid
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 Signal, OrderSide
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 Signal, OrderSide
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")
|