61 lines
2.0 KiB
Python
61 lines
2.0 KiB
Python
|
|
"""Tests for the ICT indicator engine."""
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
import pandas as pd
|
||
|
|
import numpy as np
|
||
|
|
|
||
|
|
from indicators.ict_engine import ICTEngine, ICTSignals
|
||
|
|
|
||
|
|
|
||
|
|
def generate_sample_ohlc(n: int = 200) -> pd.DataFrame:
|
||
|
|
"""Generate synthetic OHLC data for testing."""
|
||
|
|
np.random.seed(42)
|
||
|
|
dates = pd.date_range("2025-01-01", periods=n, freq="1h")
|
||
|
|
close = 50000 + np.cumsum(np.random.randn(n) * 100)
|
||
|
|
high = close + np.abs(np.random.randn(n) * 50)
|
||
|
|
low = close - np.abs(np.random.randn(n) * 50)
|
||
|
|
open_ = close + np.random.randn(n) * 30
|
||
|
|
volume = np.random.randint(100, 10000, n).astype(float)
|
||
|
|
|
||
|
|
return pd.DataFrame(
|
||
|
|
{"open": open_, "high": high, "low": low, "close": close, "volume": volume},
|
||
|
|
index=dates,
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
class TestICTEngine:
|
||
|
|
"""Tests for ICTEngine."""
|
||
|
|
|
||
|
|
def test_init_default_swing_length(self):
|
||
|
|
engine = ICTEngine()
|
||
|
|
assert engine.swing_length == 50
|
||
|
|
|
||
|
|
def test_init_custom_swing_length(self):
|
||
|
|
engine = ICTEngine(swing_length=30)
|
||
|
|
assert engine.swing_length == 30
|
||
|
|
|
||
|
|
def test_analyze_returns_ict_signals(self):
|
||
|
|
engine = ICTEngine(swing_length=10)
|
||
|
|
df = generate_sample_ohlc(100)
|
||
|
|
try:
|
||
|
|
result = engine.analyze(df)
|
||
|
|
assert isinstance(result, ICTSignals)
|
||
|
|
assert isinstance(result.swing_highs_lows, pd.DataFrame)
|
||
|
|
assert isinstance(result.fvg, pd.DataFrame)
|
||
|
|
assert isinstance(result.bos_choch, pd.DataFrame)
|
||
|
|
assert isinstance(result.order_blocks, pd.DataFrame)
|
||
|
|
except ImportError:
|
||
|
|
pytest.skip("smartmoneyconcepts not installed")
|
||
|
|
|
||
|
|
def test_analyze_too_few_candles(self):
|
||
|
|
engine = ICTEngine(swing_length=50)
|
||
|
|
df = generate_sample_ohlc(10)
|
||
|
|
with pytest.raises(ValueError, match="Need at least"):
|
||
|
|
engine.analyze(df)
|
||
|
|
|
||
|
|
def test_analyze_empty_dataframe(self):
|
||
|
|
engine = ICTEngine(swing_length=10)
|
||
|
|
df = pd.DataFrame()
|
||
|
|
with pytest.raises(ValueError):
|
||
|
|
engine.analyze(df)
|