105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
from __future__ import annotations
|
|
|
|
from hypothesis import given, settings, strategies as st
|
|
|
|
from app.services.recommendation_service import direction_analyzer, probability_estimator
|
|
|
|
|
|
@settings(max_examples=100, deadline=None)
|
|
@given(
|
|
technical=st.floats(min_value=0, max_value=100),
|
|
momentum=st.floats(min_value=0, max_value=100),
|
|
fundamental=st.floats(min_value=0, max_value=100),
|
|
sentiment=st.sampled_from(["bearish", "neutral", "bullish", None]),
|
|
)
|
|
def test_property_confidence_bounds(technical, momentum, fundamental, sentiment):
|
|
"""Feature: intelligent-trade-recommendations, Property 3: Confidence Score Bounds."""
|
|
scores = {
|
|
"technical": technical,
|
|
"momentum": momentum,
|
|
"fundamental": fundamental,
|
|
}
|
|
|
|
long_conf = direction_analyzer.calculate_confidence("long", scores, sentiment, conflicts=[])
|
|
short_conf = direction_analyzer.calculate_confidence("short", scores, sentiment, conflicts=[])
|
|
|
|
assert 0 <= long_conf <= 100
|
|
assert 0 <= short_conf <= 100
|
|
|
|
|
|
@settings(max_examples=100, deadline=None)
|
|
@given(
|
|
strength_low=st.floats(min_value=0, max_value=50),
|
|
strength_high=st.floats(min_value=50, max_value=100),
|
|
)
|
|
def test_property_strength_monotonic_probability(strength_low, strength_high):
|
|
"""Feature: intelligent-trade-recommendations, Property 11: S/R Strength Monotonicity."""
|
|
config = {
|
|
"recommendation_signal_alignment_weight": 0.15,
|
|
"recommendation_sr_strength_weight": 0.20,
|
|
"recommendation_distance_penalty_factor": 0.10,
|
|
}
|
|
scores = {"technical": 65.0, "momentum": 65.0}
|
|
|
|
base_target = {
|
|
"classification": "Moderate",
|
|
"distance_atr_multiple": 3.0,
|
|
}
|
|
|
|
low = probability_estimator.estimate_probability(
|
|
{**base_target, "sr_strength": strength_low},
|
|
scores,
|
|
"bullish",
|
|
"long",
|
|
config,
|
|
)
|
|
high = probability_estimator.estimate_probability(
|
|
{**base_target, "sr_strength": strength_high},
|
|
scores,
|
|
"bullish",
|
|
"long",
|
|
config,
|
|
)
|
|
|
|
assert high >= low
|
|
|
|
|
|
@settings(max_examples=100, deadline=None)
|
|
@given(
|
|
near_distance=st.floats(min_value=1.0, max_value=3.0),
|
|
far_distance=st.floats(min_value=3.1, max_value=8.0),
|
|
)
|
|
def test_property_distance_probability_relationship(near_distance, far_distance):
|
|
"""Feature: intelligent-trade-recommendations, Property 12: Distance Probability Relationship."""
|
|
config = {
|
|
"recommendation_signal_alignment_weight": 0.15,
|
|
"recommendation_sr_strength_weight": 0.20,
|
|
"recommendation_distance_penalty_factor": 0.10,
|
|
}
|
|
scores = {"technical": 65.0, "momentum": 65.0}
|
|
|
|
near_prob = probability_estimator.estimate_probability(
|
|
{
|
|
"classification": "Conservative",
|
|
"sr_strength": 60,
|
|
"distance_atr_multiple": near_distance,
|
|
},
|
|
scores,
|
|
"bullish",
|
|
"long",
|
|
config,
|
|
)
|
|
far_prob = probability_estimator.estimate_probability(
|
|
{
|
|
"classification": "Aggressive",
|
|
"sr_strength": 60,
|
|
"distance_atr_multiple": far_distance,
|
|
},
|
|
scores,
|
|
"bullish",
|
|
"long",
|
|
config,
|
|
)
|
|
|
|
assert near_prob >= far_prob
|