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