Big refactoring
This commit is contained in:
130
tests/unit/test_recommendation_service.py
Normal file
130
tests/unit/test_recommendation_service.py
Normal file
@@ -0,0 +1,130 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from app.services.recommendation_service import (
|
||||
direction_analyzer,
|
||||
probability_estimator,
|
||||
signal_conflict_detector,
|
||||
target_generator,
|
||||
)
|
||||
|
||||
|
||||
@dataclass
|
||||
class _SRLevelStub:
|
||||
id: int
|
||||
price_level: float
|
||||
type: str
|
||||
strength: int
|
||||
|
||||
|
||||
def test_high_confidence_long_example():
|
||||
dimension_scores = {
|
||||
"technical": 75.0,
|
||||
"momentum": 68.0,
|
||||
"fundamental": 55.0,
|
||||
}
|
||||
|
||||
confidence = direction_analyzer.calculate_confidence(
|
||||
direction="long",
|
||||
dimension_scores=dimension_scores,
|
||||
sentiment_classification="bullish",
|
||||
conflicts=[],
|
||||
)
|
||||
|
||||
assert confidence > 70.0
|
||||
|
||||
|
||||
def test_high_confidence_short_example():
|
||||
dimension_scores = {
|
||||
"technical": 30.0,
|
||||
"momentum": 35.0,
|
||||
"fundamental": 45.0,
|
||||
}
|
||||
|
||||
confidence = direction_analyzer.calculate_confidence(
|
||||
direction="short",
|
||||
dimension_scores=dimension_scores,
|
||||
sentiment_classification="bearish",
|
||||
conflicts=[],
|
||||
)
|
||||
|
||||
assert confidence > 70.0
|
||||
|
||||
|
||||
def test_detects_sentiment_technical_conflict():
|
||||
conflicts = signal_conflict_detector.detect_conflicts(
|
||||
dimension_scores={"technical": 72.0, "momentum": 55.0, "fundamental": 50.0},
|
||||
sentiment_classification="bearish",
|
||||
)
|
||||
|
||||
assert any("sentiment-technical" in conflict for conflict in conflicts)
|
||||
|
||||
|
||||
def test_generate_targets_respects_direction_and_order():
|
||||
sr_levels = [
|
||||
_SRLevelStub(id=1, price_level=110.0, type="resistance", strength=80),
|
||||
_SRLevelStub(id=2, price_level=115.0, type="resistance", strength=70),
|
||||
_SRLevelStub(id=3, price_level=120.0, type="resistance", strength=60),
|
||||
_SRLevelStub(id=4, price_level=95.0, type="support", strength=75),
|
||||
]
|
||||
|
||||
targets = target_generator.generate_targets(
|
||||
direction="long",
|
||||
entry_price=100.0,
|
||||
stop_loss=96.0,
|
||||
sr_levels=sr_levels, # type: ignore[arg-type]
|
||||
atr_value=2.0,
|
||||
)
|
||||
|
||||
assert len(targets) >= 1
|
||||
assert all(target["price"] > 100.0 for target in targets)
|
||||
distances = [target["distance_from_entry"] for target in targets]
|
||||
assert distances == sorted(distances)
|
||||
|
||||
|
||||
def test_probability_ranges_by_classification():
|
||||
config = {
|
||||
"recommendation_signal_alignment_weight": 0.15,
|
||||
"recommendation_sr_strength_weight": 0.20,
|
||||
"recommendation_distance_penalty_factor": 0.10,
|
||||
}
|
||||
dimension_scores = {"technical": 70.0, "momentum": 70.0}
|
||||
|
||||
conservative = probability_estimator.estimate_probability(
|
||||
{
|
||||
"classification": "Conservative",
|
||||
"sr_strength": 80,
|
||||
"distance_atr_multiple": 1.5,
|
||||
},
|
||||
dimension_scores,
|
||||
"bullish",
|
||||
"long",
|
||||
config,
|
||||
)
|
||||
moderate = probability_estimator.estimate_probability(
|
||||
{
|
||||
"classification": "Moderate",
|
||||
"sr_strength": 60,
|
||||
"distance_atr_multiple": 3.0,
|
||||
},
|
||||
dimension_scores,
|
||||
"bullish",
|
||||
"long",
|
||||
config,
|
||||
)
|
||||
aggressive = probability_estimator.estimate_probability(
|
||||
{
|
||||
"classification": "Aggressive",
|
||||
"sr_strength": 40,
|
||||
"distance_atr_multiple": 6.0,
|
||||
},
|
||||
dimension_scores,
|
||||
"bullish",
|
||||
"long",
|
||||
config,
|
||||
)
|
||||
|
||||
assert conservative > 60
|
||||
assert 40 <= moderate <= 70
|
||||
assert aggressive < 50
|
||||
Reference in New Issue
Block a user