This project includes multiple AI/ML-based lottery number generators for German Lotto 6aus49, including pattern analysis, weighted predictions, and hybrid approaches. Features automated weekly tip generation, performance tracking, and Telegram bot integration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
302 lines
9.6 KiB
Python
302 lines
9.6 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Wöchentlicher Lotto 6aus49 Tipp-Generator
|
||
|
||
Automatisiert:
|
||
1. Prüft ob neue Tipps nötig sind (basierend auf letzter Generierung)
|
||
2. Generiert 10 Ultimate Tipps
|
||
3. Speichert mit Timestamp
|
||
4. Trackt Generierungs-Historie
|
||
|
||
Verwendung:
|
||
python weekly_tip_generator.py
|
||
|
||
Oder als Cronjob:
|
||
0 9 * * 3,6 cd /path/to/lotto && source venv/bin/activate && python scripts/automation/weekly_tip_generator.py
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
from datetime import datetime, timedelta
|
||
import json
|
||
|
||
# Füge Parent-Verzeichnisse zum Path hinzu
|
||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||
project_dir = os.path.dirname(os.path.dirname(script_dir))
|
||
generators_dir = os.path.join(project_dir, 'scripts', 'generators')
|
||
sys.path.insert(0, project_dir)
|
||
sys.path.insert(0, generators_dir)
|
||
|
||
# Import des Ultimate Generators
|
||
from scripts.generators.ultimate_ai_ml_hybrid_generator import UltimateAIMLHybridGenerator
|
||
from scripts.utils.notifier import LottoNotifier
|
||
|
||
|
||
class WeeklyTipGenerator:
|
||
"""Automatischer wöchentlicher Tipp-Generator für Lotto 6aus49."""
|
||
|
||
def __init__(self, data_dir: str):
|
||
self.data_dir = data_dir
|
||
# CSV file is in Lotto/data folder
|
||
# data_dir = .../Lotto/data
|
||
# We need .../Lotto/data/AlleLottozahlen.csv
|
||
self.data_file = os.path.join(data_dir, "AlleLottozahlen.csv")
|
||
self.tips_dir = os.path.join(data_dir, "generated_tips")
|
||
self.history_file = os.path.join(self.tips_dir, "generation_history.json")
|
||
|
||
os.makedirs(self.tips_dir, exist_ok=True)
|
||
|
||
# Initialisiere Notifier
|
||
self.notifier = LottoNotifier()
|
||
|
||
print("🤖 AUTOMATISCHER WÖCHENTLICHER LOTTO 6AUS49 TIPP-GENERATOR")
|
||
print("=" * 70)
|
||
|
||
def load_history(self) -> dict:
|
||
"""Lädt Generierungs-Historie."""
|
||
if os.path.exists(self.history_file):
|
||
with open(self.history_file, 'r') as f:
|
||
return json.load(f)
|
||
return {"generations": []}
|
||
|
||
def save_history(self, history: dict):
|
||
"""Speichert Historie."""
|
||
with open(self.history_file, 'w') as f:
|
||
json.dump(history, f, indent=2)
|
||
|
||
def needs_new_tips(self) -> bool:
|
||
"""
|
||
Prüft ob neue Tipps nötig sind.
|
||
|
||
Logik:
|
||
- Lotto 6aus49: Mittwoch & Samstag Ziehungen
|
||
- Generiere Tipps wenn:
|
||
a) Noch nie generiert
|
||
b) Letzte Generierung > 3 Tage her
|
||
c) Es ist Dienstag oder Freitag (vor Ziehung)
|
||
"""
|
||
history = self.load_history()
|
||
|
||
if not history["generations"]:
|
||
print(" ℹ️ Noch nie Tipps generiert")
|
||
return True
|
||
|
||
last_gen = history["generations"][-1]
|
||
last_date = datetime.fromisoformat(last_gen["timestamp"])
|
||
days_since = (datetime.now() - last_date).days
|
||
|
||
print(f" 📅 Letzte Generierung: {last_date.strftime('%Y-%m-%d %H:%M')}")
|
||
print(f" ⏱️ Vor {days_since} Tagen")
|
||
|
||
# Wenn > 3 Tage her
|
||
if days_since > 3:
|
||
print(" ✅ Mehr als 3 Tage her - neue Tipps nötig")
|
||
return True
|
||
|
||
# Prüfe Wochentag (0=Montag, 2=Mittwoch, 5=Samstag)
|
||
today = datetime.now().weekday()
|
||
|
||
# Dienstag (vor Mittwoch-Ziehung)
|
||
if today == 1 and days_since >= 1:
|
||
print(" ✅ Dienstag - generiere für Mittwoch-Ziehung")
|
||
return True
|
||
|
||
# Freitag (vor Samstag-Ziehung)
|
||
if today == 4 and days_since >= 1:
|
||
print(" ✅ Freitag - generiere für Samstag-Ziehung")
|
||
return True
|
||
|
||
print(" ⏭️ Keine neuen Tipps nötig")
|
||
return False
|
||
|
||
def generate_tips(self, num_tips: int = 10, force: bool = False) -> bool:
|
||
"""
|
||
Generiert neue Tipps.
|
||
|
||
Args:
|
||
num_tips: Anzahl Tipps
|
||
force: Ignoriere needs_new_tips Check
|
||
|
||
Returns:
|
||
True bei Erfolg
|
||
"""
|
||
print("\n🎯 TIPP-GENERIERUNG")
|
||
print("=" * 70)
|
||
|
||
# Check ob nötig
|
||
if not force and not self.needs_new_tips():
|
||
print("\n⏭️ Keine Generierung nötig")
|
||
return True
|
||
|
||
print(f"\n🚀 Generiere {num_tips} Ultimate Lotto 6aus49 Tipps...")
|
||
print("-" * 70)
|
||
|
||
try:
|
||
# Initialisiere Generator
|
||
generator = UltimateAIMLHybridGenerator(
|
||
self.data_file,
|
||
fast_mode=True
|
||
)
|
||
|
||
# Generiere Tipps
|
||
tips = generator.generate_ultimate_tips(num_tips=num_tips)
|
||
|
||
if not tips:
|
||
print("\n❌ Keine Tipps generiert")
|
||
return False
|
||
|
||
# Speichere Tipps
|
||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||
output_file = os.path.join(
|
||
self.tips_dir,
|
||
f"weekly_lotto_tips_{timestamp}.csv"
|
||
)
|
||
|
||
self._export_tips_to_csv(tips, output_file)
|
||
|
||
# Update Historie
|
||
history = self.load_history()
|
||
history["generations"].append({
|
||
"timestamp": datetime.now().isoformat(),
|
||
"num_tips": len(tips),
|
||
"file": os.path.basename(output_file),
|
||
"avg_confidence": sum(t['confidence'] for t in tips) / len(tips),
|
||
"avg_quality": sum(t['quality'] for t in tips) / len(tips)
|
||
})
|
||
self.save_history(history)
|
||
|
||
print("\n" + "=" * 70)
|
||
print("✅ TIPPS ERFOLGREICH GENERIERT")
|
||
print(f"📁 Datei: {os.path.basename(output_file)}")
|
||
print(f"📊 Anzahl: {len(tips)}")
|
||
print(f"🎯 Avg Confidence: {history['generations'][-1]['avg_confidence']:.4f}")
|
||
print(f"💎 Avg Quality: {history['generations'][-1]['avg_quality']:.4f}")
|
||
print("=" * 70)
|
||
|
||
# Sende Benachrichtigung
|
||
try:
|
||
# Finde besten Tipp (höchste Confidence)
|
||
best_tip = max(tips, key=lambda t: t.get('confidence', 0))
|
||
|
||
# Formatiere für Notification
|
||
best_tip_formatted = {
|
||
'numbers': best_tip.get('numbers', []),
|
||
'superzahl': best_tip.get('superzahl', 0),
|
||
'confidence': best_tip.get('confidence', 0),
|
||
'strategy': best_tip.get('strategy', 'UNKNOWN')
|
||
}
|
||
|
||
timestamp_formatted = datetime.now().strftime('%Y-%m-%d %H:%M')
|
||
self.notifier.send_tips_generated(tips, timestamp_formatted, best_tip_formatted)
|
||
except Exception as e:
|
||
print(f"⚠️ Benachrichtigung fehlgeschlagen: {e}")
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"\n❌ Fehler bei Generierung: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def _export_tips_to_csv(self, tips, filepath):
|
||
"""Exportiert Tips als CSV."""
|
||
import pandas as pd
|
||
|
||
rows = []
|
||
for tip in tips:
|
||
numbers_str = '-'.join([str(n) for n in tip['numbers']])
|
||
|
||
rows.append({
|
||
'Tip_Number': tip['tip_number'],
|
||
'Numbers': numbers_str,
|
||
'Superzahl': tip['superzahl'],
|
||
'Strategy': tip['strategy'],
|
||
'AI_Score': f"{tip['ai_score']:.4f}",
|
||
'Pattern_Weight': f"{tip['pattern_weight']:.4f}",
|
||
'Confidence': f"{tip['confidence']:.4f}",
|
||
'Quality': f"{tip['quality']:.4f}"
|
||
})
|
||
|
||
df_export = pd.DataFrame(rows)
|
||
df_export.to_csv(filepath, index=False)
|
||
print(f"\n💾 Tips exported to: {filepath}")
|
||
|
||
def show_history(self):
|
||
"""Zeigt Generierungs-Historie."""
|
||
history = self.load_history()
|
||
|
||
if not history["generations"]:
|
||
print("\n ℹ️ Noch keine Generierungen")
|
||
return
|
||
|
||
print("\n📊 GENERIERUNGS-HISTORIE")
|
||
print("=" * 70)
|
||
print(f"{'Nr':<4} {'Datum':<20} {'Tips':<6} {'Confidence':<12} {'Quality':<12} {'Datei'}")
|
||
print("-" * 70)
|
||
|
||
for i, gen in enumerate(reversed(history["generations"][-10:]), 1):
|
||
timestamp = datetime.fromisoformat(gen["timestamp"])
|
||
print(f"{i:<4} {timestamp.strftime('%Y-%m-%d %H:%M'):<20} "
|
||
f"{gen['num_tips']:<6} {gen['avg_confidence']:<12.4f} "
|
||
f"{gen['avg_quality']:<12.4f} {gen['file']}")
|
||
|
||
print("-" * 70)
|
||
print(f"Total: {len(history['generations'])} Generierungen")
|
||
|
||
|
||
def main():
|
||
"""Hauptfunktion."""
|
||
import argparse
|
||
|
||
parser = argparse.ArgumentParser(
|
||
description="Wöchentlicher Lotto 6aus49 Tipp-Generator"
|
||
)
|
||
parser.add_argument(
|
||
'--force',
|
||
action='store_true',
|
||
help='Generiere Tipps auch wenn nicht nötig'
|
||
)
|
||
parser.add_argument(
|
||
'--num-tips',
|
||
type=int,
|
||
default=10,
|
||
help='Anzahl Tipps zu generieren (default: 10)'
|
||
)
|
||
parser.add_argument(
|
||
'--history',
|
||
action='store_true',
|
||
help='Zeige nur Historie'
|
||
)
|
||
parser.add_argument(
|
||
'--data-dir',
|
||
type=str,
|
||
default="/Users/sebastianfrohlich/Library/Mobile Documents/com~apple~CloudDocs/Jupyter Notebooks/Lotto/data",
|
||
help='Daten-Verzeichnis'
|
||
)
|
||
|
||
args = parser.parse_args()
|
||
|
||
# Initialisiere
|
||
generator = WeeklyTipGenerator(args.data_dir)
|
||
|
||
# Zeige Historie wenn gewünscht
|
||
if args.history:
|
||
generator.show_history()
|
||
return
|
||
|
||
# Generiere Tipps
|
||
success = generator.generate_tips(
|
||
num_tips=args.num_tips,
|
||
force=args.force
|
||
)
|
||
|
||
# Zeige Historie
|
||
generator.show_history()
|
||
|
||
sys.exit(0 if success else 1)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|