Coverage for src/finbot/market/models.py: 100%
29 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 17:12 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-21 17:12 +0000
1import math
2from dataclasses import dataclass
3from datetime import datetime
6@dataclass
7class Bar:
8 symbol: str
9 timestamp: datetime
11 open: float
12 high: float
13 low: float
14 close: float
15 volume: float
17 def __post_init__(self):
18 if not isinstance(self.symbol, str) or not self.symbol.strip():
19 raise ValueError("Symbol must be a non-empty string.")
21 for name in ("open", "high", "low", "close"):
22 value = getattr(self, name)
24 if not math.isfinite(value):
25 raise ValueError(f"{name.capitalize()} price must be a valid number.")
27 if value <= 0:
28 raise ValueError(f"{name.capitalize()} price must be greater than zero.")
30 if not math.isfinite(self.volume):
31 raise ValueError("Volume must be a valid number.")
33 if self.volume < 0:
34 raise ValueError("Volume cannot be negative.")
36 if self.high < max(self.open, self.close):
37 raise ValueError("High price must be >= open and close.")
38 if self.low > min(self.open, self.close):
39 raise ValueError("Low price must be <= open and close.")