This commit is contained in:
Executable
+46
@@ -0,0 +1,46 @@
|
||||
import os
|
||||
import yaml
|
||||
from typing import Dict, Any, Optional
|
||||
|
||||
class EnsembleConfig:
|
||||
_instance: Optional['EnsembleConfig'] = None
|
||||
_config: Dict[str, Any] = {}
|
||||
|
||||
def __new__(cls):
|
||||
if cls._instance is None:
|
||||
cls._instance = super(EnsembleConfig, cls).__new__(cls)
|
||||
cls._instance._load_config()
|
||||
return cls._instance
|
||||
|
||||
def _load_config(self):
|
||||
"""Load configuration from YAML file."""
|
||||
config_path = os.path.join(os.path.dirname(__file__), 'ensemble_config.yaml')
|
||||
try:
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
self._config = yaml.safe_load(f)
|
||||
# print(f"✅ Loaded ensemble config from {config_path}")
|
||||
except Exception as e:
|
||||
print(f"❌ Failed to load ensemble config: {e}")
|
||||
self._config = {}
|
||||
|
||||
def get(self, key: str, default: Any = None) -> Any:
|
||||
"""Get configuration value by key (supports dot notation for nested keys)."""
|
||||
keys = key.split('.')
|
||||
value = self._config
|
||||
|
||||
try:
|
||||
for k in keys:
|
||||
value = value[k]
|
||||
return value
|
||||
except (KeyError, TypeError):
|
||||
return default
|
||||
|
||||
# Singleton accessor
|
||||
def get_config() -> EnsembleConfig:
|
||||
return EnsembleConfig()
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Test
|
||||
cfg = get_config()
|
||||
print(f"Weights: {cfg.get('engine_weights')}")
|
||||
print(f"Team Weight: {cfg.get('engine_weights.team')}")
|
||||
Executable
+186
@@ -0,0 +1,186 @@
|
||||
engine_weights:
|
||||
team: 0.30
|
||||
player: 0.25
|
||||
odds: 0.30
|
||||
referee: 0.15
|
||||
min_weight: 0.05
|
||||
|
||||
weight_redistribution:
|
||||
player_missing_to_team: 0.5
|
||||
player_missing_to_odds: 0.5
|
||||
referee_missing_to_team: 0.4
|
||||
referee_missing_to_odds: 0.6
|
||||
referee_min_matches: 5
|
||||
|
||||
match_result:
|
||||
min_draw_prob: 0.15
|
||||
|
||||
over_under:
|
||||
prob_min: 0.02
|
||||
prob_max: 0.98
|
||||
ou15_threshold: 0.55
|
||||
ou25_threshold: 0.52
|
||||
ou35_threshold: 0.48
|
||||
btts_threshold: 0.58
|
||||
poisson_blend_weight: 0.25
|
||||
poisson_grid_max: 6
|
||||
|
||||
half_time:
|
||||
ft_to_ht_ratio: 0.42
|
||||
poisson_grid_max: 5
|
||||
ht_over_05_min: 0.20
|
||||
ht_over_05_max: 0.95
|
||||
ht_ou_threshold: 0.55
|
||||
ht_draw_floor: 0.28
|
||||
low_xg_threshold: 2.0
|
||||
low_xg_ratio_adjust: 0.85
|
||||
|
||||
confidence:
|
||||
agreement_boost: 1.3
|
||||
disagreement_penalty: 0.7
|
||||
|
||||
handicap:
|
||||
xg_diff_threshold: 1.2
|
||||
|
||||
corners:
|
||||
xg_multiplier: 3.0
|
||||
baseline: 3.0
|
||||
home_dominant_bonus: 1.5
|
||||
away_dominant_bonus: 1.0
|
||||
dominance_threshold: 0.6
|
||||
line: 9.5
|
||||
|
||||
cards:
|
||||
derby_heat_factor: 1.3
|
||||
line: 4.5
|
||||
|
||||
score:
|
||||
poisson_grid_max: 7
|
||||
ms_confidence_threshold: 15.0
|
||||
|
||||
risk:
|
||||
# Lowered thresholds for better surprise detection (was 0.20+)
|
||||
# Model typically outputs 4-8% for reversals, so we need lower thresholds
|
||||
surprise_threshold: 0.05
|
||||
surprise_threshold_top: 0.05
|
||||
surprise_threshold_non_top: 0.06
|
||||
surprise_threshold_favorite_reversal: 0.06
|
||||
surprise_threshold_favorite_reversal_top: 0.06
|
||||
surprise_threshold_favorite_reversal_non_top: 0.08
|
||||
surprise_threshold_underdog_reversal: 0.05
|
||||
surprise_threshold_underdog_reversal_top: 0.05
|
||||
surprise_threshold_underdog_reversal_non_top: 0.06
|
||||
surprise_threshold_basketball: 0.08
|
||||
surprise_threshold_basketball_top: 0.08
|
||||
surprise_threshold_basketball_non_top: 0.10
|
||||
surprise_min_top_gap: 0.01
|
||||
surprise_min_top_gap_top: 0.01
|
||||
surprise_min_top_gap_non_top: 0.015
|
||||
# New: Upset alert threshold for potential upsets (lower than main threshold)
|
||||
upset_alert_threshold: 0.05 # 5% - alert when reversal prob > 5%
|
||||
htft_temperature: 1.25
|
||||
htft_temperature_top: 1.25
|
||||
htft_temperature_non_top: 1.35
|
||||
htft_temperature_basketball: 1.08
|
||||
htft_temperature_basketball_top: 1.08
|
||||
htft_temperature_basketball_non_top: 1.15
|
||||
htft_reversal_multiplier: 0.60
|
||||
htft_reversal_multiplier_top: 0.60
|
||||
htft_reversal_multiplier_non_top: 0.45
|
||||
htft_reversal_multiplier_favorite: 0.72
|
||||
htft_reversal_multiplier_favorite_top: 0.72
|
||||
htft_reversal_multiplier_favorite_non_top: 0.55
|
||||
htft_reversal_multiplier_underdog: 0.45
|
||||
htft_reversal_multiplier_underdog_top: 0.45
|
||||
htft_reversal_multiplier_underdog_non_top: 0.30
|
||||
htft_reversal_multiplier_basketball: 0.90
|
||||
htft_reversal_multiplier_basketball_top: 0.90
|
||||
htft_reversal_multiplier_basketball_non_top: 0.75
|
||||
htft_reversal_gap_medium: 0.50
|
||||
htft_reversal_gap_strong: 1.00
|
||||
htft_prior_min_matches: 300
|
||||
htft_prior_blend_league: 0.65
|
||||
htft_prior_blend_top: 0.50
|
||||
htft_prior_blend_non_top: 0.58
|
||||
htft_prior_odds_blend_top: 0.35
|
||||
htft_prior_odds_blend_top_with_league: 0.22
|
||||
htft_favorite_balance_gap: 0.20
|
||||
htft_reversal_cap_factor: 2.30
|
||||
extreme_upset: 0.7
|
||||
high_upset: 0.5
|
||||
medium_upset: 0.3
|
||||
extreme_warnings: 3
|
||||
high_warnings: 2
|
||||
balanced_match_gap: 0.1
|
||||
referee_min_data: 10
|
||||
|
||||
recommendations:
|
||||
confidence_threshold: 45
|
||||
value_confidence_min: 10
|
||||
value_confidence_max: 30
|
||||
value_edge_margin: 0.02
|
||||
value_upgrade_edge: 5.0
|
||||
|
||||
# ACİL DÜZELTİLDİ: Güvenilir marketler genişletildi
|
||||
safe_markets: ['ÇŞ', '1.5 Üst/Alt', '2.5 Üst/Alt']
|
||||
|
||||
# ACİL DÜZELTİLDİ: Market bazlı minimum confidence threshold'lar (Artık Olasılık Yüzdesi!)
|
||||
market_min_confidence:
|
||||
MS: 50.0 # Match result is hardest; 50%+ true probability is actually strong
|
||||
ÇŞ: 65.0 # Double chance naturally has high probability (2 sides of 3)
|
||||
1.5 Üst/Alt: 70.0 # 1.5 Goals needs to be highly probable to be worth playing
|
||||
2.5 Üst/Alt: 55.0 # Standard threshold for 50/50 lines
|
||||
3.5 Üst/Alt: 60.0 # Needs higher certianty than 2.5
|
||||
BTTS: 60.0 # Both Teams To Score - raised for accuracy (was 47.7%)
|
||||
|
||||
risk_safe_boost: 1.2
|
||||
risk_ms_penalty_high: 0.5
|
||||
risk_ms_penalty_medium: 0.8
|
||||
risk_other_penalty: 0.7
|
||||
|
||||
# ACİL DÜZELTİLDİ: Market weights güvenilir marketlere göre ayarlandı
|
||||
market_weights:
|
||||
MS: 0.5 # ⬇️ Düşürüldü (zayıf performans)
|
||||
ÇŞ: 1.5 # ⬆️ Artırıldı (güçlü performans)
|
||||
1.5 Üst/Alt: 1.6 # ⬆️ En yüksek (en güvenilir)
|
||||
2.5 Üst/Alt: 1.2 # ⬆️ Artırıldı
|
||||
3.5 Üst/Alt: 0.9 # ⬇️ Düşürüldü
|
||||
BTTS: 0.4 # ⬇️ Düşürüldü (zayıf performans)
|
||||
|
||||
# Confidence Calibration (backtest-derived accuracy)
|
||||
baseline_accuracy: 65.0
|
||||
market_accuracy:
|
||||
MS: 52.1 # ❌ Zayıf
|
||||
ÇŞ: 77.9 # ✅ İyi
|
||||
1.5 Üst/Alt: 82.1 # ✅ Mükemmel
|
||||
2.5 Üst/Alt: 61.4 # ⚠️ Orta
|
||||
3.5 Üst/Alt: 60.7 # ⚠️ Orta
|
||||
BTTS: 50.7 # ❌ Zayıf
|
||||
|
||||
calibration_buckets:
|
||||
ms_home:
|
||||
heavy_fav: 1.40 # home odds <= 1.40
|
||||
fav: 1.80 # home odds > 1.40 and <= 1.80
|
||||
balanced: 2.50 # home odds > 1.80 and <= 2.50
|
||||
underdog: 99.0 # home odds > 2.50
|
||||
|
||||
team_xg:
|
||||
home_base: 1.35
|
||||
away_base: 1.10
|
||||
home_conversion_mult: 3.0
|
||||
away_conversion_mult: 2.5
|
||||
|
||||
sidelined:
|
||||
position_weights:
|
||||
K: 0.35
|
||||
D: 0.20
|
||||
O: 0.25
|
||||
F: 0.30
|
||||
max_rating: 10
|
||||
adaptation_threshold: 10
|
||||
adaptation_discount: 0.5
|
||||
goalkeeper_penalty: 0.15
|
||||
confidence_boost: 10
|
||||
max_impact: 0.85
|
||||
key_player_threshold: 3
|
||||
recent_matches_lookback: 15
|
||||
Reference in New Issue
Block a user