Hierarchical ML Pipeline for trading predictions:
- Level 0: Attention Models (volatility/flow classification)
- Level 1: Base Models (XGBoost per symbol/timeframe)
- Level 2: Metamodels (XGBoost Stacking + Neural Gating)
Key components:
- src/pipelines/hierarchical_pipeline.py - Main prediction pipeline
- src/models/ - All ML model classes
- src/training/ - Training utilities
- src/api/ - FastAPI endpoints
- scripts/ - Training and evaluation scripts
- config/ - YAML configurations
Note: Trained models (*.joblib, *.pt) are gitignored.
Regenerate with training scripts.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
171 lines
4.6 KiB
Python
171 lines
4.6 KiB
Python
"""
|
|
Test AMD Detector
|
|
"""
|
|
|
|
import pytest
|
|
import pandas as pd
|
|
import numpy as np
|
|
from datetime import datetime, timedelta
|
|
|
|
from src.models.amd_detector import AMDDetector, AMDPhase
|
|
|
|
|
|
@pytest.fixture
|
|
def sample_ohlcv_data():
|
|
"""Create sample OHLCV data for testing"""
|
|
dates = pd.date_range(start='2024-01-01', periods=200, freq='5min')
|
|
np.random.seed(42)
|
|
|
|
# Generate synthetic price data
|
|
base_price = 2000
|
|
returns = np.random.randn(200) * 0.001
|
|
prices = base_price * np.cumprod(1 + returns)
|
|
|
|
df = pd.DataFrame({
|
|
'open': prices,
|
|
'high': prices * (1 + abs(np.random.randn(200) * 0.001)),
|
|
'low': prices * (1 - abs(np.random.randn(200) * 0.001)),
|
|
'close': prices * (1 + np.random.randn(200) * 0.0005),
|
|
'volume': np.random.randint(1000, 10000, 200)
|
|
}, index=dates)
|
|
|
|
# Ensure OHLC consistency
|
|
df['high'] = df[['open', 'high', 'close']].max(axis=1)
|
|
df['low'] = df[['open', 'low', 'close']].min(axis=1)
|
|
|
|
return df
|
|
|
|
|
|
def test_amd_detector_initialization():
|
|
"""Test AMD detector initialization"""
|
|
detector = AMDDetector(lookback_periods=100)
|
|
assert detector.lookback_periods == 100
|
|
assert len(detector.phase_history) == 0
|
|
assert detector.current_phase is None
|
|
|
|
|
|
def test_detect_phase_insufficient_data():
|
|
"""Test phase detection with insufficient data"""
|
|
detector = AMDDetector(lookback_periods=100)
|
|
|
|
# Create small dataset
|
|
dates = pd.date_range(start='2024-01-01', periods=50, freq='5min')
|
|
df = pd.DataFrame({
|
|
'open': [2000] * 50,
|
|
'high': [2010] * 50,
|
|
'low': [1990] * 50,
|
|
'close': [2005] * 50,
|
|
'volume': [1000] * 50
|
|
}, index=dates)
|
|
|
|
phase = detector.detect_phase(df)
|
|
|
|
assert phase.phase == 'unknown'
|
|
assert phase.confidence == 0
|
|
assert phase.strength == 0
|
|
|
|
|
|
def test_detect_phase_with_sufficient_data(sample_ohlcv_data):
|
|
"""Test phase detection with sufficient data"""
|
|
detector = AMDDetector(lookback_periods=100)
|
|
phase = detector.detect_phase(sample_ohlcv_data)
|
|
|
|
# Should return a valid phase
|
|
assert phase.phase in ['accumulation', 'manipulation', 'distribution']
|
|
assert 0 <= phase.confidence <= 1
|
|
assert 0 <= phase.strength <= 1
|
|
assert isinstance(phase.characteristics, dict)
|
|
assert isinstance(phase.signals, list)
|
|
|
|
|
|
def test_trading_bias_accumulation():
|
|
"""Test trading bias for accumulation phase"""
|
|
detector = AMDDetector()
|
|
|
|
phase = AMDPhase(
|
|
phase='accumulation',
|
|
confidence=0.7,
|
|
start_time=datetime.utcnow(),
|
|
end_time=None,
|
|
characteristics={},
|
|
signals=[],
|
|
strength=0.6
|
|
)
|
|
|
|
bias = detector.get_trading_bias(phase)
|
|
|
|
assert bias['phase'] == 'accumulation'
|
|
assert bias['direction'] == 'long'
|
|
assert bias['risk_level'] == 'low'
|
|
assert 'buy_dips' in bias['strategies']
|
|
|
|
|
|
def test_trading_bias_manipulation():
|
|
"""Test trading bias for manipulation phase"""
|
|
detector = AMDDetector()
|
|
|
|
phase = AMDPhase(
|
|
phase='manipulation',
|
|
confidence=0.7,
|
|
start_time=datetime.utcnow(),
|
|
end_time=None,
|
|
characteristics={},
|
|
signals=[],
|
|
strength=0.6
|
|
)
|
|
|
|
bias = detector.get_trading_bias(phase)
|
|
|
|
assert bias['phase'] == 'manipulation'
|
|
assert bias['direction'] == 'neutral'
|
|
assert bias['risk_level'] == 'high'
|
|
assert bias['position_size'] == 0.3
|
|
|
|
|
|
def test_trading_bias_distribution():
|
|
"""Test trading bias for distribution phase"""
|
|
detector = AMDDetector()
|
|
|
|
phase = AMDPhase(
|
|
phase='distribution',
|
|
confidence=0.7,
|
|
start_time=datetime.utcnow(),
|
|
end_time=None,
|
|
characteristics={},
|
|
signals=[],
|
|
strength=0.6
|
|
)
|
|
|
|
bias = detector.get_trading_bias(phase)
|
|
|
|
assert bias['phase'] == 'distribution'
|
|
assert bias['direction'] == 'short'
|
|
assert bias['risk_level'] == 'medium'
|
|
assert 'sell_rallies' in bias['strategies']
|
|
|
|
|
|
def test_amd_phase_to_dict():
|
|
"""Test AMDPhase to_dict conversion"""
|
|
phase = AMDPhase(
|
|
phase='accumulation',
|
|
confidence=0.75,
|
|
start_time=datetime(2024, 1, 1, 12, 0),
|
|
end_time=datetime(2024, 1, 1, 13, 0),
|
|
characteristics={'range_compression': 0.65},
|
|
signals=['breakout_imminent'],
|
|
strength=0.7
|
|
)
|
|
|
|
phase_dict = phase.to_dict()
|
|
|
|
assert phase_dict['phase'] == 'accumulation'
|
|
assert phase_dict['confidence'] == 0.75
|
|
assert phase_dict['strength'] == 0.7
|
|
assert '2024-01-01' in phase_dict['start_time']
|
|
assert isinstance(phase_dict['characteristics'], dict)
|
|
assert isinstance(phase_dict['signals'], list)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
pytest.main([__file__, "-v"])
|