This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test the improved surprise detection logic"""
|
||||
|
||||
import sys
|
||||
sys.path.insert(0, 'ai-engine')
|
||||
|
||||
from core.calculators.risk_assessor import RiskAssessor
|
||||
from config.config_loader import get_config
|
||||
|
||||
def test_surprise_detection():
|
||||
config = get_config()
|
||||
assessor = RiskAssessor(config)
|
||||
|
||||
# Test cases based on real scenarios
|
||||
test_cases = [
|
||||
{
|
||||
'name': 'Bayern vs Augsburg (1.30 odds, 2% 1/2 prob)',
|
||||
'odds': {'ms_h': 1.30, 'ms_d': 5.00, 'ms_a': 8.00},
|
||||
'ht_ft': {'1/1': 0.30, '1/X': 0.07, '1/2': 0.02, 'X/1': 0.15, 'X/X': 0.16, 'X/2': 0.09, '2/1': 0.03, '2/X': 0.04, '2/2': 0.14},
|
||||
'expected_surprise': True,
|
||||
'expected_type': '1/2 Potential Upset'
|
||||
},
|
||||
{
|
||||
'name': 'Strong favorite (1.20 odds, 1.5% 1/2 prob)',
|
||||
'odds': {'ms_h': 1.20, 'ms_d': 6.00, 'ms_a': 12.00},
|
||||
'ht_ft': {'1/1': 0.35, '1/X': 0.05, '1/2': 0.015, 'X/1': 0.20, 'X/X': 0.15, 'X/2': 0.05, '2/1': 0.02, '2/X': 0.03, '2/2': 0.10},
|
||||
'expected_surprise': True,
|
||||
'expected_type': '1/2 Potential Upset'
|
||||
},
|
||||
{
|
||||
'name': 'Moderate favorite (1.50 odds, 3% 1/2 prob)',
|
||||
'odds': {'ms_h': 1.50, 'ms_d': 4.00, 'ms_a': 6.00},
|
||||
'ht_ft': {'1/1': 0.28, '1/X': 0.08, '1/2': 0.03, 'X/1': 0.18, 'X/X': 0.15, 'X/2': 0.08, '2/1': 0.04, '2/X': 0.05, '2/2': 0.11},
|
||||
'expected_surprise': True,
|
||||
'expected_type': '1/2 Potential Upset'
|
||||
},
|
||||
{
|
||||
'name': 'Even match (2.00 odds, 5% 1/2 prob)',
|
||||
'odds': {'ms_h': 2.00, 'ms_d': 3.30, 'ms_a': 3.30},
|
||||
'ht_ft': {'1/1': 0.20, '1/X': 0.10, '1/2': 0.05, 'X/1': 0.15, 'X/X': 0.15, 'X/2': 0.10, '2/1': 0.05, '2/X': 0.10, '2/2': 0.10},
|
||||
'expected_surprise': False, # No clear favorite
|
||||
'expected_type': None
|
||||
},
|
||||
{
|
||||
'name': 'Away favorite (1.40 away odds, 2% 2/1 prob)',
|
||||
'odds': {'ms_h': 6.00, 'ms_d': 4.00, 'ms_a': 1.40},
|
||||
'ht_ft': {'1/1': 0.10, '1/X': 0.05, '1/2': 0.04, 'X/1': 0.08, 'X/X': 0.15, 'X/2': 0.20, '2/1': 0.02, '2/X': 0.06, '2/2': 0.30},
|
||||
'expected_surprise': True,
|
||||
'expected_type': '2/1 Potential Upset'
|
||||
},
|
||||
]
|
||||
|
||||
print("=" * 70)
|
||||
print("SURPRISE DETECTION TEST RESULTS")
|
||||
print("=" * 70)
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for tc in test_cases:
|
||||
class MockCtx:
|
||||
is_surprise = False
|
||||
is_top_league = True
|
||||
sport = 'football'
|
||||
xgboost_preds = {'ht_ft': tc['ht_ft']}
|
||||
odds_data = tc['odds']
|
||||
|
||||
result = assessor.assess_risk(MockCtx())
|
||||
|
||||
# Check if result matches expectation
|
||||
is_correct = result.is_surprise_risk == tc['expected_surprise']
|
||||
if tc['expected_type'] and result.surprise_type != tc['expected_type']:
|
||||
is_correct = False
|
||||
|
||||
status = "✅ PASS" if is_correct else "❌ FAIL"
|
||||
if is_correct:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"\n{status} - {tc['name']}")
|
||||
print(f" Expected: surprise={tc['expected_surprise']}, type={tc['expected_type']}")
|
||||
print(f" Got: surprise={result.is_surprise_risk}, type={result.surprise_type}")
|
||||
if result.reasons:
|
||||
print(f" Reasons: {result.reasons}")
|
||||
|
||||
print("\n" + "=" * 70)
|
||||
print(f"SUMMARY: {passed} passed, {failed} failed")
|
||||
print("=" * 70)
|
||||
|
||||
return failed == 0
|
||||
|
||||
if __name__ == "__main__":
|
||||
success = test_surprise_detection()
|
||||
sys.exit(0 if success else 1)
|
||||
Reference in New Issue
Block a user