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:
2026-08-04 17:36:06 +02:00
co-authored by Claude Sonnet 5
parent 6c1139c909
commit 8c2089d734
@@ -74,7 +74,12 @@ class UltimateAIMLHybridGenerator:
"""
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):
self.data_path = data_path
self.df = None
@@ -406,7 +411,7 @@ class UltimateAIMLHybridGenerator:
"""High-EV: 23 Zahlen >31, max. 1 Lucky Number, soft Consecutive-Vermeidung."""
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
selected = []
@@ -628,49 +633,66 @@ class UltimateAIMLHybridGenerator:
return (distance_score * 0.4 + range_score * 0.4 + balance_score * 0.2)
def _get_smart_superzahl(self, tip_number):
"""Intelligente Superzahl."""
base_sz = [7, 6, 3, 2, 0, 1, 4, 5, 8, 9]
try:
if 'SZ' in self.df.columns and len(self.df) > 10:
recent_sz = self.df['SZ'].tail(30).dropna()
if len(recent_sz) > 0:
sz_freq = Counter(recent_sz)
top_sz = [int(sz) for sz, _ in sz_freq.most_common(7) if 0 <= sz <= 9]
if top_sz:
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
"""
EV-optimierte Superzahl: bevorzugt Ziffern, die Spieler erfahrungsgemäß
seltener frei wählen (0 wirkt nicht wie eine "eigene" Zahl; 7/3 gelten als
klassische Glückszahlen und werden überproportional gewählt). Historische
Ziehungshäufigkeit fließt bewusst NICHT mehr ein - die SZ wird pro Ziehung
unabhängig und gleichverteilt (0-9) gezogen, "häufig gezogen in letzten 30
Ziehungen" ist reines Rauschen ohne Vorhersagewert.
"""
ev_order = [0, 9, 8, 4, 2, 6, 1, 5, 3, 7] # unpopulärste zuerst
return ev_order[tip_number % len(ev_order)]
@staticmethod
def _calculate_popularity_score(numbers):
"""
Schätzt den Erwartungswert-Vorteil durch Vermeidung populärer Zahlenkombinationen.
Höher = unpopulärer = höherer Gewinnanteil bei einem Treffer.
Basis: Spieler bevorzugen Geburtstagszahlen (1-31), Glückszahlen und Zahlenfolgen.
Höher = unpopulärer bei Mitspielern = höherer Gewinnanteil bei einem Treffer
(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)
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
# Aufeinanderfolgende Zahlen vermeiden (visuelle Muster)
consecutive_pairs = sum(1 for i in range(n - 1) if sorted_nums[i + 1] - sorted_nums[i] == 1)
consecutive_ratio = consecutive_pairs / (n - 1) if n > 1 else 0
# 2) Empirisch belegte populäre Einzelzahlen meiden
popular_ratio = sum(
1 for x in numbers
if x in UltimateAIMLHybridGenerator.POPULAR_PLAYER_PICKS
) / n
# Häufig gespielte "Glückszahlen" vermeiden
lucky_numbers = {3, 7, 9, 11, 13, 17, 19, 21, 23}
lucky_ratio = sum(1 for x in numbers if x in lucky_numbers) / n
# 3) Muster/Zahlenfolgen meiden: direkte Nachbarn UND allgemeine
# arithmetische Folgen (konstante Schrittweite, z.B. 5-10-15-20-25-30
# 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)
def _calculate_quality_score(self, numbers, ai_predictions, pattern_weight):
@@ -702,12 +724,16 @@ class UltimateAIMLHybridGenerator:
else:
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 = (
ai_quality * 0.30
+ pattern_quality * 0.20
ai_quality * 0.15
+ pattern_quality * 0.10
+ diversity_quality * 0.15
+ popularity_quality * 0.20
+ recency_quality * 0.15
+ popularity_quality * 0.50
+ recency_quality * 0.10
)
return min(quality, 1.0)