"""Tests for candle models.""" import pytest from exchange_data_manager.candles.models import Candle, CandleRequest class TestCandle: """Tests for Candle dataclass.""" def test_create_candle(self): """Test creating a candle.""" candle = Candle( time=1709337600, open=50000.0, high=51000.0, low=49500.0, close=50500.0, volume=100.5, ) assert candle.time == 1709337600 assert candle.open == 50000.0 assert candle.high == 51000.0 assert candle.low == 49500.0 assert candle.close == 50500.0 assert candle.volume == 100.5 assert candle.closed is True def test_candle_closed_default(self): """Test that closed defaults to True.""" candle = Candle( time=1709337600, open=50000.0, high=50000.0, low=50000.0, close=50000.0, volume=0.0, ) assert candle.closed is True def test_candle_not_closed(self): """Test creating an unclosed candle.""" candle = Candle( time=1709337600, open=50000.0, high=50000.0, low=50000.0, close=50000.0, volume=0.0, closed=False, ) assert candle.closed is False def test_to_dict(self): """Test converting candle to dictionary.""" candle = Candle( time=1709337600, open=50000.0, high=51000.0, low=49500.0, close=50500.0, volume=100.5, ) result = candle.to_dict() assert result == { "time": 1709337600, "open": 50000.0, "high": 51000.0, "low": 49500.0, "close": 50500.0, "volume": 100.5, "closed": True, } def test_from_dict(self): """Test creating candle from dictionary.""" data = { "time": 1709337600, "open": 50000.0, "high": 51000.0, "low": 49500.0, "close": 50500.0, "volume": 100.5, } candle = Candle.from_dict(data) assert candle.time == 1709337600 assert candle.open == 50000.0 assert candle.high == 51000.0 assert candle.low == 49500.0 assert candle.close == 50500.0 assert candle.volume == 100.5 def test_from_ccxt(self): """Test creating candle from ccxt OHLCV format.""" # ccxt format: [timestamp_ms, open, high, low, close, volume] ohlcv = [1709337600000, 50000.0, 51000.0, 49500.0, 50500.0, 100.5] candle = Candle.from_ccxt(ohlcv) # Time should be converted from ms to seconds assert candle.time == 1709337600 assert candle.open == 50000.0 assert candle.high == 51000.0 assert candle.low == 49500.0 assert candle.close == 50500.0 assert candle.volume == 100.5 assert candle.closed is True def test_timestamp_ms_property(self): """Test timestamp_ms property.""" candle = Candle( time=1709337600, open=50000.0, high=50000.0, low=50000.0, close=50000.0, volume=0.0, ) assert candle.timestamp_ms == 1709337600000 def test_datetime_property(self): """Test datetime property.""" candle = Candle( time=1709337600, open=50000.0, high=50000.0, low=50000.0, close=50000.0, volume=0.0, ) dt = candle.datetime assert dt.year == 2024 assert dt.month == 3 assert dt.day == 2 # 1709337600 = 2024-03-02 00:00:00 UTC class TestCandleRequest: """Tests for CandleRequest dataclass.""" def test_create_request(self): """Test creating a candle request.""" request = CandleRequest( exchange="binance", symbol="BTC/USDT", timeframe="5m", ) assert request.exchange == "binance" assert request.symbol == "BTC/USDT" assert request.timeframe == "5m" assert request.start is None assert request.end is None assert request.limit is None def test_create_request_with_range(self): """Test creating a candle request with time range.""" request = CandleRequest( exchange="binance", symbol="BTC/USDT", timeframe="1h", start=1709251200, end=1709337600, limit=100, ) assert request.start == 1709251200 assert request.end == 1709337600 assert request.limit == 100 def test_cache_key_property(self): """Test cache key generation.""" request = CandleRequest( exchange="Binance", # Mixed case symbol="btc/usdt", # Lowercase timeframe="5M", # Uppercase ) # Should be normalized assert request.cache_key == "binance:BTC/USDT:5m" def test_cache_key_different_symbols(self): """Test that different symbols produce different keys.""" request1 = CandleRequest(exchange="binance", symbol="BTC/USDT", timeframe="5m") request2 = CandleRequest(exchange="binance", symbol="ETH/USDT", timeframe="5m") assert request1.cache_key != request2.cache_key def test_cache_key_different_timeframes(self): """Test that different timeframes produce different keys.""" request1 = CandleRequest(exchange="binance", symbol="BTC/USDT", timeframe="5m") request2 = CandleRequest(exchange="binance", symbol="BTC/USDT", timeframe="1h") assert request1.cache_key != request2.cache_key def test_symbol_normalization(self): """Test that symbols are normalized.""" # Lowercase should be uppercased request = CandleRequest(exchange="binance", symbol="btc/usdt", timeframe="5m") assert request.symbol == "BTC/USDT" def test_symbol_separator_added(self): """Test that separator is added to symbols without one.""" request = CandleRequest(exchange="binance", symbol="BTCUSDT", timeframe="5m") assert request.symbol == "BTC/USDT" def test_exchange_normalization(self): """Test that exchange is normalized to lowercase.""" request = CandleRequest(exchange="BINANCE", symbol="BTC/USDT", timeframe="5m") assert request.exchange == "binance"