81 lines
2.9 KiB
Python
81 lines
2.9 KiB
Python
|
|
"""Tests for divergence detection in indicators."""
|
||
|
|
|
||
|
|
import pytest
|
||
|
|
import pandas as pd
|
||
|
|
import numpy as np
|
||
|
|
from src.data.indicators import get_indicators
|
||
|
|
|
||
|
|
|
||
|
|
class TestDivergenceDetection:
|
||
|
|
"""Tests for divergence detection."""
|
||
|
|
|
||
|
|
@pytest.fixture
|
||
|
|
def indicators(self):
|
||
|
|
"""Create indicators instance."""
|
||
|
|
return get_indicators()
|
||
|
|
|
||
|
|
@pytest.fixture
|
||
|
|
def sample_data(self):
|
||
|
|
"""Create sample price data with clear trend."""
|
||
|
|
dates = pd.date_range(start='2025-01-01', periods=100, freq='1H')
|
||
|
|
# Create price data with trend
|
||
|
|
prices = [100 + i * 0.1 + np.random.randn() * 0.5 for i in range(100)]
|
||
|
|
return pd.Series(prices, index=dates)
|
||
|
|
|
||
|
|
def test_detect_divergence_insufficient_data(self, indicators):
|
||
|
|
"""Test divergence detection with insufficient data."""
|
||
|
|
prices = pd.Series([100, 101, 102])
|
||
|
|
indicator = pd.Series([50, 51, 52])
|
||
|
|
|
||
|
|
result = indicators.detect_divergence(prices, indicator, lookback=20)
|
||
|
|
|
||
|
|
assert result['type'] is None
|
||
|
|
assert result['confidence'] == 0.0
|
||
|
|
|
||
|
|
def test_detect_divergence_structure(self, indicators, sample_data):
|
||
|
|
"""Test divergence detection returns correct structure."""
|
||
|
|
# Create indicator data
|
||
|
|
indicator = pd.Series([50 + i * 0.1 for i in range(100)], index=sample_data.index)
|
||
|
|
|
||
|
|
result = indicators.detect_divergence(sample_data, indicator, lookback=20)
|
||
|
|
|
||
|
|
# Check structure
|
||
|
|
assert 'type' in result
|
||
|
|
assert 'confidence' in result
|
||
|
|
assert 'price_swing_high' in result
|
||
|
|
assert 'price_swing_low' in result
|
||
|
|
assert 'indicator_swing_high' in result
|
||
|
|
assert 'indicator_swing_low' in result
|
||
|
|
|
||
|
|
# Type should be None, 'bullish', or 'bearish'
|
||
|
|
assert result['type'] in [None, 'bullish', 'bearish']
|
||
|
|
|
||
|
|
# Confidence should be 0.0 to 1.0
|
||
|
|
assert 0.0 <= result['confidence'] <= 1.0
|
||
|
|
|
||
|
|
def test_detect_divergence_with_trend(self, indicators):
|
||
|
|
"""Test divergence detection with clear trend data."""
|
||
|
|
# Create price making lower lows
|
||
|
|
prices = pd.Series([100, 95, 90, 85, 80])
|
||
|
|
|
||
|
|
# Create indicator making higher lows (bullish divergence)
|
||
|
|
indicator = pd.Series([30, 32, 34, 36, 38])
|
||
|
|
|
||
|
|
# Need more data for lookback
|
||
|
|
prices_long = pd.concat([pd.Series([110] * 30), prices])
|
||
|
|
indicator_long = pd.concat([pd.Series([25] * 30), indicator])
|
||
|
|
|
||
|
|
result = indicators.detect_divergence(
|
||
|
|
prices_long,
|
||
|
|
indicator_long,
|
||
|
|
lookback=5,
|
||
|
|
min_swings=2
|
||
|
|
)
|
||
|
|
|
||
|
|
# Should detect bullish divergence (price down, indicator up)
|
||
|
|
# Note: This may not always detect due to swing detection logic
|
||
|
|
assert result is not None
|
||
|
|
assert 'type' in result
|
||
|
|
assert 'confidence' in result
|
||
|
|
|