Ground popularity/EV score in empirical player-choice biases

Since draws are i.i.d., only expected value (jackpot-sharing avoidance)
is actually improvable, not hit probability. Replaces the ad-hoc "lucky
numbers" list with empirically-documented picks, adds general arithmetic-
progression detection (not just +1 consecutive pairs), and scores extreme
odd/even splits and sums higher since humans favor "balanced-looking"
combinations despite every combination being equally likely.

Raises popularity's weight in the quality score from 20% to 50%, since
AI/pattern/recency signals carry no real predictive value and recency
("overdue" numbers) risks converging with other systematic players'
picks, undermining the EV goal. Superzahl selection now uses an EV
heuristic instead of chasing historical draw frequency, which is pure
noise for an independently drawn digit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
cbazzaandClaude Sonnet 5 committed 2026-08-04 17:36:06 +02:00
1 parent 6c1139c909
commit 8c2089d734
1 file changed
+62 -36
@@ -74,7 +74,12 @@ class UltimateAIMLHybridGenerator:
""" """
Ultimate Generator - OPTIMIZED VERSION Ultimate Generator - OPTIMIZED VERSION
""" """
# Empirisch belegte "griffige" Einzelzahlen, die Spieler überproportional oft frei
# wählen (Quelle: Analysen realer Tippscheine, z.B. frz. 6aus49 über 25 Jahre:
# populärste Zahlen 5,7,9,11,12,13). Unabhängig vom Geburtstags-Bias (<=31).
POPULAR_PLAYER_PICKS = {5, 7, 9, 11, 12, 13}
def __init__(self, data_path, fast_mode=True): def __init__(self, data_path, fast_mode=True):
self.data_path = data_path self.data_path = data_path
self.df = None self.df = None
@@ -406,7 +411,7 @@ class UltimateAIMLHybridGenerator:
"""High-EV: 2–3 Zahlen >31, max. 1 Lucky Number, soft Consecutive-Vermeidung.""" """High-EV: 2–3 Zahlen >31, max. 1 Lucky Number, soft Consecutive-Vermeidung."""
random.seed(42 + tip_number * 41) random.seed(42 + tip_number * 41)
lucky_numbers = {3, 7, 9, 11, 13, 17, 19, 21, 23} lucky_numbers = UltimateAIMLHybridGenerator.POPULAR_PLAYER_PICKS
above_31_target = 2 + (tip_number % 2) # wechselt zwischen 2 und 3 above_31_target = 2 + (tip_number % 2) # wechselt zwischen 2 und 3
selected = [] selected = []
@@ -628,49 +633,66 @@ class UltimateAIMLHybridGenerator:
return (distance_score * 0.4 + range_score * 0.4 + balance_score * 0.2) return (distance_score * 0.4 + range_score * 0.4 + balance_score * 0.2)
def _get_smart_superzahl(self, tip_number): def _get_smart_superzahl(self, tip_number):
"""Intelligente Superzahl.""" """
base_sz = [7, 6, 3, 2, 0, 1, 4, 5, 8, 9] EV-optimierte Superzahl: bevorzugt Ziffern, die Spieler erfahrungsgemäß
seltener frei wählen (0 wirkt nicht wie eine "eigene" Zahl; 7/3 gelten als
try: klassische Glückszahlen und werden überproportional gewählt). Historische
if 'SZ' in self.df.columns and len(self.df) > 10: Ziehungshäufigkeit fließt bewusst NICHT mehr ein - die SZ wird pro Ziehung
recent_sz = self.df['SZ'].tail(30).dropna() unabhängig und gleichverteilt (0-9) gezogen, "häufig gezogen in letzten 30
if len(recent_sz) > 0: Ziehungen" ist reines Rauschen ohne Vorhersagewert.
sz_freq = Counter(recent_sz) """
top_sz = [int(sz) for sz, _ in sz_freq.most_common(7) if 0 <= sz <= 9] ev_order = [0, 9, 8, 4, 2, 6, 1, 5, 3, 7] # unpopulärste zuerst
if top_sz: return ev_order[tip_number % len(ev_order)]
base_sz = top_sz + [7, 6, 3]
except:
pass
if tip_number <= 3:
sz = base_sz[0]
else:
sz = base_sz[tip_number % len(base_sz)]
return int(sz) if 0 <= int(sz) <= 9 else 7
@staticmethod @staticmethod
def _calculate_popularity_score(numbers): def _calculate_popularity_score(numbers):
""" """
Schätzt den Erwartungswert-Vorteil durch Vermeidung populärer Zahlenkombinationen. Schätzt den Erwartungswert-Vorteil durch Vermeidung populärer Zahlenkombinationen.
Höher = unpopulärer = höherer Gewinnanteil bei einem Treffer. Höher = unpopulärer bei Mitspielern = höherer Gewinnanteil bei einem Treffer
Basis: Spieler bevorzugen Geburtstagszahlen (1-31), Glückszahlen und Zahlenfolgen. (Hit-Wahrscheinlichkeit selbst ist bei i.i.d. Ziehungen nicht beeinflussbar).
Basis: dokumentierte Spielerverhalten-Biases (Henze/Riedwyl-artige Analysen
realer Tippscheine): Geburtstagszahlen (<=31), einzelne "griffige" Zahlen,
Zahlenfolgen/arithmetische Muster (z.B. 5-10-15-20-25-30) und "zufällig
aussehende" ausgeglichene Odd/Even-Splits + mittige Summen werden von
Menschen überproportional oft gewählt - jede einzelne Kombination ist aber
exakt gleich wahrscheinlich, unabhängig von diesen Eigenschaften.
""" """
n = len(numbers) n = len(numbers)
sorted_nums = sorted(numbers) sorted_nums = sorted(numbers)
# Anteil Zahlen > 31 (Geburtstags-Range vermeiden) # 1) Geburtstags-Range (1-31) meiden
above_31_ratio = sum(1 for x in numbers if x > 31) / n above_31_ratio = sum(1 for x in numbers if x > 31) / n
# Aufeinanderfolgende Zahlen vermeiden (visuelle Muster) # 2) Empirisch belegte populäre Einzelzahlen meiden
consecutive_pairs = sum(1 for i in range(n - 1) if sorted_nums[i + 1] - sorted_nums[i] == 1) popular_ratio = sum(
consecutive_ratio = consecutive_pairs / (n - 1) if n > 1 else 0 1 for x in numbers
if x in UltimateAIMLHybridGenerator.POPULAR_PLAYER_PICKS
) / n
# Häufig gespielte "Glückszahlen" vermeiden # 3) Muster/Zahlenfolgen meiden: direkte Nachbarn UND allgemeine
lucky_numbers = {3, 7, 9, 11, 13, 17, 19, 21, 23} # arithmetische Folgen (konstante Schrittweite, z.B. 5-10-15-20-25-30
lucky_ratio = sum(1 for x in numbers if x in lucky_numbers) / n # zählt zu den meistgespielten Kombinationen überhaupt)
diffs = [sorted_nums[i + 1] - sorted_nums[i] for i in range(n - 1)]
small_step_ratio = sum(1 for d in diffs if d <= 5) / (n - 1) if diffs else 0
is_perfect_progression = len(diffs) > 1 and len(set(diffs)) == 1
pattern_penalty = small_step_ratio * (0.6 if not is_perfect_progression else 1.0)
score = above_31_ratio * 0.5 + (1 - consecutive_ratio) * 0.3 + (1 - lucky_ratio) * 0.2 # 4) Odd/Even-Split: Menschen bevorzugen "ausgeglichen aussehende" 3-3
# Splits, obwohl jede einzelne Kombination gleich wahrscheinlich ist
even_count = sum(1 for x in numbers if x % 2 == 0)
split_extremity = abs(even_count - 3) / 3 # 0.0 bei 3-3, 1.0 bei 6-0/0-6
# 5) Summe: Menschen bevorzugen Summen nahe dem statistischen Mittel (~150)
sum_extremity = min(abs(sum(numbers) - 150) / 100.0, 1.0)
score = (
above_31_ratio * 0.25
+ (1 - popular_ratio) * 0.15
+ (1 - pattern_penalty) * 0.20
+ split_extremity * 0.20
+ sum_extremity * 0.20
)
return min(max(score, 0.0), 1.0) return min(max(score, 0.0), 1.0)
def _calculate_quality_score(self, numbers, ai_predictions, pattern_weight): def _calculate_quality_score(self, numbers, ai_predictions, pattern_weight):
@@ -702,12 +724,16 @@ class UltimateAIMLHybridGenerator:
else: else:
recency_quality = 0.5 # neutral wenn noch nicht berechnet recency_quality = 0.5 # neutral wenn noch nicht berechnet
# Popularity/EV dominiert bewusst: AI-Score, Pattern und Recency sagen nichts
# über die (unbeeinflussbare) Trefferwahrscheinlichkeit aus - Recency/Pattern
# folgen zudem Heuristiken, die auch andere Systemspieler nutzen und damit die
# Popularity eher untergraben statt sie zu unterstützen.
quality = ( quality = (
ai_quality * 0.30 ai_quality * 0.15
+ pattern_quality * 0.20 + pattern_quality * 0.10
+ diversity_quality * 0.15 + diversity_quality * 0.15
+ popularity_quality * 0.20 + popularity_quality * 0.50
+ recency_quality * 0.15 + recency_quality * 0.10
) )
return min(quality, 1.0) return min(quality, 1.0)