# ==============================================================================
# PROGETTO: LOTTO AVENGERS 2026 - BACKTEST TAVOLA SETTENARIA (v7.0 - Coppie Complete)
# Regola d'oro rispettata: NESSUNA cancellazione di codice per risparmio spazio.
#
# Test scientifici con z-score:
# TEST A: "Numero Secco" - 1 numero specifico tra i mancanti
# TEST B: "Ambo Secco" - 2 numeri specifici tra i mancanti (primi 2 in ordine)
# TEST C: "Baseline Dinamica Corretta" - tutti i mancanti con probabilità corretta per attivazione
# TEST D: "Tutte le Coppie" - testa TUTTE le coppie possibili tra i mancanti
# ==============================================================================
import math
import urllib.request
import urllib.error
from collections import defaultdict
from itertools import combinations
# ------------------------------------------------------------------------------
# CONFIGURAZIONE GLOBALE
# ------------------------------------------------------------------------------
RUOTE = {
"BA": "Bari", "CA": "Cagliari", "FI": "Firenze", "GE": "Genova",
"MI": "Milano", "NA": "Napoli", "PA": "Palermo", "RO": "Roma",
"TO": "Torino", "VE": "Venezia", "NZ": "Nazionale"
}
URL_BASE = "https://huggingface.co/spaces/AI-tom/backtester-con-rilevamento-parametri-x-training/raw/main/LottoJarvis_Cloud/1_Data/archivi_estrazioni/"
MIN_TRIGGER = 2
MAX_DELAY = 3
# ------------------------------------------------------------------------------
# 1. GENERATORE DELLE FAMIGLIE SETTENARIE
# ------------------------------------------------------------------------------
def genera_famiglie_settenarie():
famiglie_uniche = []
numeri_visitati = set()
for n in range(1, 91):
if n in numeri_visitati:
continue
famiglia = []
current = n
while current not in famiglia:
famiglia.append(current)
numeri_visitati.add(current)
current = (current * 7) % 90
if current == 0:
current = 90
famiglie_uniche.append({
"id": f"Famiglia_di_{n}",
"numeri_ordinati": tuple(sorted(famiglia)),
"numeri_set": set(famiglia),
"lunghezza": len(famiglia)
})
print(f"[INFO] Generate {len(famiglie_uniche)} famiglie settenarie uniche.")
return famiglie_uniche
# ------------------------------------------------------------------------------
# 2. DOWNLOADER DA HUGGING FACE
# ------------------------------------------------------------------------------
def scarica_estrazioni_da_url(url, nome_ruota):
estrazioni = []
print(f"\n[INFO] Scaricamento dati per ruota: {nome_ruota}")
try:
headers = {'User-Agent': 'LottoAvengers-Final/7.0'}
req = urllib.request.Request(url, headers=headers)
with urllib.request.urlopen(req, timeout=30) as response:
contenuto = response.read().decode('utf-8')
lines = contenuto.strip().split('\n')
lines.reverse()
righe_valide = 0
for line in lines:
line = line.strip()
if not line:
continue
parti = line.split('.')
if len(parti) == 5:
try:
numeri = [int(x.strip()) for x in parti]
if all(1 <= n <= 90 for n in numeri):
estrazioni.append({"numeri": numeri})
righe_valide += 1
except ValueError:
continue
print(f"[INFO] Caricate {righe_valide} estrazioni valide per {nome_ruota}.")
return estrazioni
except Exception as e:
print(f"[ERRORE] {nome_ruota}: {e}")
return []
# ------------------------------------------------------------------------------
# 3. CALCOLI PROBABILISTICI
# ------------------------------------------------------------------------------
def comb(n, k):
"""Calcola il coefficiente binomiale C(n,k)"""
if k < 0 or k > n:
return 0
if k == 0 or k == n:
return 1
k = min(k, n - k)
result = 1
for i in range(k):
result = result * (n - i) // (i + 1)
return result
def prob_almeno_2_in_1_estrazione(n_giocati):
"""Probabilità di fare almeno ambo giocando n_giocati numeri in UNA estrazione."""
if n_giocati < 2:
return 0.0
totale = comb(90, 5)
p_zero = comb(n_giocati, 0) * comb(90 - n_giocati, 5) / totale
p_uno = comb(n_giocati, 1) * comb(90 - n_giocati, 4) / totale
return 1.0 - p_zero - p_uno
def prob_almeno_1_in_3_estrazioni():
"""Probabilità che 1 numero specifico esca in almeno 1 di 3 estrazioni."""
return 1.0 - math.pow(85/90, 3)
def prob_ambo_2_numeri_in_3_estrazioni():
"""Probabilità che 2 numeri specifici escano insieme (ambo) in almeno 1 di 3 estrazioni."""
p_ambo_1_estrazione = comb(2, 2) * comb(88, 3) / comb(90, 5)
return 1.0 - math.pow(1.0 - p_ambo_1_estrazione, 3)
def z_score(p_empirica, p_teorica, n_campioni):
"""Calcola lo z-score per testare la significatività statistica."""
if n_campioni == 0:
return 0.0
std_dev = math.sqrt(p_teorica * (1.0 - p_teorica) / n_campioni)
if std_dev == 0:
return 0.0
return (p_empirica - p_teorica) / std_dev
# ------------------------------------------------------------------------------
# 4. MOTORE DI BACKTEST v7.0 (4 test)
# ------------------------------------------------------------------------------
def esegui_backtest_v7(estrazioni, famiglie, min_trigger=2, max_delay=3):
statistiche = defaultdict(lambda: {
"attivazioni": 0,
"test_A_successi": 0,
"test_B_successi": 0,
"test_C_successi": 0,
"test_C_prob_teoriche": [], # Lista delle probabilità teoriche per ogni attivazione
"test_D_coppie_totali": 0,
"test_D_coppie_vincenti": 0,
"test_D_prob_teoriche_coppie": [] # Lista delle probabilità teoriche per ogni coppia
})
for i in range(len(estrazioni) - max_delay):
estrazione_corrente = set(estrazioni[i]["numeri"])
for fam in famiglie:
numeri_presenti = estrazione_corrente.intersection(fam["numeri_set"])
if len(numeri_presenti) >= min_trigger:
statistiche[fam["id"]]["attivazioni"] += 1
numeri_mancanti_ordinati = sorted(list(fam["numeri_set"] - estrazione_corrente))
n_mancanti = len(numeri_mancanti_ordinati)
test_A_ok = False
test_B_ok = False
test_C_ok = False
# TEST D: genera tutte le coppie possibili tra i mancanti
if n_mancanti >= 2:
coppie_possibili = list(combinations(numeri_mancanti_ordinati, 2))
statistiche[fam["id"]]["test_D_coppie_totali"] += len(coppie_possibili)
# Per ogni coppia, calcola la probabilità teorica
for coppia in coppie_possibili:
prob_coppia = prob_ambo_2_numeri_in_3_estrazioni()
statistiche[fam["id"]]["test_D_prob_teoriche_coppie"].append(prob_coppia)
for j in range(1, max_delay + 1):
estrazione_futura = set(estrazioni[i + j]["numeri"])
n_colpiti = len(set(numeri_mancanti_ordinati).intersection(estrazione_futura))
# TEST A
if not test_A_ok and n_mancanti > 0 and numeri_mancanti_ordinati[0] in estrazione_futura:
test_A_ok = True
# TEST B
if not test_B_ok and n_mancanti >= 2:
if numeri_mancanti_ordinati[0] in estrazione_futura and \
numeri_mancanti_ordinati[1] in estrazione_futura:
test_B_ok = True
# TEST C
if not test_C_ok and n_colpiti >= 2:
test_C_ok = True
# TEST D: controlla quante coppie vincono in questa estrazione
if n_mancanti >= 2:
for coppia in coppie_possibili:
if coppia[0] in estrazione_futura and coppia[1] in estrazione_futura:
statistiche[fam["id"]]["test_D_coppie_vincenti"] += 1
if test_A_ok:
statistiche[fam["id"]]["test_A_successi"] += 1
if test_B_ok:
statistiche[fam["id"]]["test_B_successi"] += 1
if test_C_ok:
statistiche[fam["id"]]["test_C_successi"] += 1
# TEST C: calcola la probabilità teorica corretta per questa attivazione
if n_mancanti >= 2:
prob_C = 1.0 - math.pow(1.0 - prob_almeno_2_in_1_estrazione(n_mancanti), max_delay)
statistiche[fam["id"]]["test_C_prob_teoriche"].append(prob_C)
return statistiche
# ------------------------------------------------------------------------------
# 5. ANALISI RISULTATI PER RUOTA
# ------------------------------------------------------------------------------
def analizza_risultati_ruota_v7(nome_ruota, statistiche, famiglie, max_delay):
p_teorica_1num = prob_almeno_1_in_3_estrazioni()
p_teorica_ambo_secco = prob_ambo_2_numeri_in_3_estrazioni()
print(f"\n{'='*130}")
print(f" RUOTA: {nome_ruota.upper()} | Finestra: {max_delay} estrazioni")
print(f"{'='*130}")
print(f"Baselines teoriche CASUALI:")
print(f" - TEST A (1 numero secco): {p_teorica_1num:.2%}")
print(f" - TEST B (ambo 2 numeri secchi): {p_teorica_ambo_secco:.3%}")
print(f" - TEST C (baseline dinamica): calcolata per ogni attivazione")
print(f" - TEST D (tutte le coppie): calcolata per ogni coppia\n")
print(f"{'Famiglia':<18} | {'Attiv.':<6} | {'TestA%':<8} | {'zA':<6} | {'TestB%':<8} | {'zB':<6} | {'TestC%':<8} | {'zC':<6} | {'TestD%':<8} | {'zD':<6}")
print("-" * 135)
totali = {"attivazioni": 0, "A_succ": 0, "B_succ": 0, "C_succ": 0, "C_prob": [],
"D_coppie_tot": 0, "D_coppie_vin": 0, "D_prob": []}
for fam in famiglie:
fid = fam["id"]
stats = statistiche[fid]
att = stats["attivazioni"]
if att == 0:
continue
# TEST A
p_A = stats["test_A_successi"] / att
z_A = z_score(p_A, p_teorica_1num, att)
# TEST B
p_B = stats["test_B_successi"] / att
z_B = z_score(p_B, p_teorica_ambo_secco, att)
# TEST C - Baseline corretta
if len(stats["test_C_prob_teoriche"]) > 0:
p_teorica_C_media = sum(stats["test_C_prob_teoriche"]) / len(stats["test_C_prob_teoriche"])
p_C = stats["test_C_successi"] / att
z_C = z_score(p_C, p_teorica_C_media, att) if p_teorica_C_media > 0 else 0.0
else:
p_C = 0.0
z_C = 0.0
p_teorica_C_media = 0.0
# TEST D - Tutte le coppie
if stats["test_D_coppie_totali"] > 0:
p_teorica_D_media = sum(stats["test_D_prob_teoriche_coppie"]) / len(stats["test_D_prob_teoriche_coppie"])
p_D = stats["test_D_coppie_vincenti"] / stats["test_D_coppie_totali"]
z_D = z_score(p_D, p_teorica_D_media, stats["test_D_coppie_totali"]) if p_teorica_D_media > 0 else 0.0
else:
p_D = 0.0
z_D = 0.0
p_teorica_D_media = 0.0
print(f"{fid:<18} | {att:<6} | {p_A*100:>6.2f}% | {z_A:>+5.2f} | {p_B*100:>6.3f}% | {z_B:>+5.2f} | {p_C*100:>6.2f}% | {z_C:>+5.2f} | {p_D*100:>6.3f}% | {z_D:>+5.2f}")
totali["attivazioni"] += att
totali["A_succ"] += stats["test_A_successi"]
totali["B_succ"] += stats["test_B_successi"]
totali["C_succ"] += stats["test_C_successi"]
totali["C_prob"].extend(stats["test_C_prob_teoriche"])
totali["D_coppie_tot"] += stats["test_D_coppie_totali"]
totali["D_coppie_vin"] += stats["test_D_coppie_vincenti"]
totali["D_prob"].extend(stats["test_D_prob_teoriche_coppie"])
print("-" * 135)
if totali["attivazioni"] > 0:
att_tot = totali["attivazioni"]
p_A_tot = totali["A_succ"] / att_tot
z_A_tot = z_score(p_A_tot, p_teorica_1num, att_tot)
p_B_tot = totali["B_succ"] / att_tot
z_B_tot = z_score(p_B_tot, p_teorica_ambo_secco, att_tot)
if len(totali["C_prob"]) > 0:
p_teorica_C_tot = sum(totali["C_prob"]) / len(totali["C_prob"])
p_C_tot = totali["C_succ"] / att_tot
z_C_tot = z_score(p_C_tot, p_teorica_C_tot, att_tot) if p_teorica_C_tot > 0 else 0.0
else:
p_C_tot = 0.0
z_C_tot = 0.0
p_teorica_C_tot = 0.0
if totali["D_coppie_tot"] > 0:
p_teorica_D_tot = sum(totali["D_prob"]) / len(totali["D_prob"])
p_D_tot = totali["D_coppie_vin"] / totali["D_coppie_tot"]
z_D_tot = z_score(p_D_tot, p_teorica_D_tot, totali["D_coppie_tot"]) if p_teorica_D_tot > 0 else 0.0
else:
p_D_tot = 0.0
z_D_tot = 0.0
p_teorica_D_tot = 0.0
print(f"{'TOTALE RUOTA':<18} | {att_tot:<6} | {p_A_tot*100:>6.2f}% | {z_A_tot:>+5.2f} | {p_B_tot*100:>6.3f}% | {z_B_tot:>+5.2f} | {p_C_tot*100:>6.2f}% | {z_C_tot:>+5.2f} | {p_D_tot*100:>6.3f}% | {z_D_tot:>+5.2f}")
print(f"{'='*130}")
return totali
# ------------------------------------------------------------------------------
# 6. REPORT GLOBALE FINALE
# ------------------------------------------------------------------------------
def report_globale_v7(totale_globale, num_ruote, max_delay):
p_teorica_1num = prob_almeno_1_in_3_estrazioni()
p_teorica_ambo_secco = prob_ambo_2_numeri_in_3_estrazioni()
print("\n" + "#" * 130)
print(" # RIEPILOGO GLOBALE FINALE v7.0 - TAVOLA SETTENARIA (Test Completo su Tutte le Coppie)")
print(" # Analisi scientifica con z-score - Lotto Avengers 2026")
print(f" # Ruote analizzate: {num_ruote} | Finestra: {max_delay} estrazioni")
print(" #" * 65)
att = totale_globale["attivazioni"]
if att > 0:
# TEST A
p_A = totale_globale["A_succ"] / att
z_A = z_score(p_A, p_teorica_1num, att)
# TEST B
p_B = totale_globale["B_succ"] / att
z_B = z_score(p_B, p_teorica_ambo_secco, att)
# TEST C
if len(totale_globale["C_prob"]) > 0:
p_teorica_C = sum(totale_globale["C_prob"]) / len(totale_globale["C_prob"])
p_C = totale_globale["C_succ"] / att
z_C = z_score(p_C, p_teorica_C, att) if p_teorica_C > 0 else 0.0
else:
p_C = 0.0
z_C = 0.0
p_teorica_C = 0.0
# TEST D
if totale_globale["D_coppie_tot"] > 0:
p_teorica_D = sum(totale_globale["D_prob"]) / len(totale_globale["D_prob"])
p_D = totale_globale["D_coppie_vin"] / totale_globale["D_coppie_tot"]
z_D = z_score(p_D, p_teorica_D, totale_globale["D_coppie_tot"]) if p_teorica_D > 0 else 0.0
else:
p_D = 0.0
z_D = 0.0
p_teorica_D = 0.0
print(f" # ATTIVAZIONI TOTALI: {att}")
print(f" # COPPIE TESTATE TOTALI: {totale_globale['D_coppie_tot']}")
print(f" #")
print(f" # TEST A (1 numero secco):")
print(f" # Empirico: {p_A:.2%} | Teorico: {p_teorica_1num:.2%} | z-score: {z_A:+.2f}")
print(f" #")
print(f" # TEST B (ambo 2 numeri secchi - primi 2 in ordine):")
print(f" # Empirico: {p_B:.3%} | Teorico: {p_teorica_ambo_secco:.3%} | z-score: {z_B:+.2f}")
print(f" #")
print(f" # TEST C (baseline dinamica corretta):")
print(f" # Empirico: {p_C:.2%} | Teorico: {p_teorica_C:.2%} | z-score: {z_C:+.2f}")
print(f" #")
print(f" # TEST D (TUTTE le coppie tra i mancanti):")
print(f" # Empirico: {p_D:.3%} | Teorico: {p_teorica_D:.3%} | z-score: {z_D:+.2f}")
print(" #")
print(" # INTERPRETAZIONE DEGLI Z-SCORE:")
print(" # |z| < 1.96 → Nessun effetto statisticamente significativo (caso puro)")
print(" # |z| > 1.96 → Significativo al 95%")
print(" # |z| > 2.58 → Significativo al 99%")
print(" # |z| > 3.29 → Significativo al 99.9%")
print(" #")
# Giudizio finale
z_scores = [abs(z_A), abs(z_B), abs(z_C), abs(z_D)]
z_max = max(z_scores)
if z_max < 1.96:
print(" # CONCLUSIONE FINALE:")
print(" # Tutti e quattro i test mostrano z-score dentro la soglia di significatività.")
print(" # La Tavola Settenaria si comporta ESATTAMENTE come il CASO PURO.")
print(" # La tesi di mattia73 è CONFIRMATA: 'È geometria, non previsione.'")
elif z_max > 3.29:
print(" # CONCLUSIONE FINALE:")
print(" # ALMENO UN TEST mostra uno scarto ALTAMENTE SIGNIFICATIVO (p < 0.001).")
print(" # Questo risultato meriterebbe approfondimenti ulteriori.")
elif z_max > 1.96:
print(" # CONCLUSIONE FINALE:")
print(" # ALMENO UN TEST mostra uno scarto statisticamente significativo.")
print(" # Da verificare con campioni indipendenti per escludere fluttuazioni.")
else:
print(" # CONCLUSIONE FINALE:")
print(" # Risultati al limite della significatività. Non conclusivi.")
print(" #" * 65)
# ------------------------------------------------------------------------------
# 7. PUNTO DI INGRESSO (MAIN)
# ------------------------------------------------------------------------------
if __name__ == "__main__":
print("="*130)
print(" LOTTO AVENGERS 2026 - BACKTEST TAVOLA SETTENARIA (v7.0 - Test Completo su Tutte le Coppie)")
print(" Test scientifici con z-score: Numero Secco | Ambo Secco | Baseline Corretta | Tutte le Coppie")
print("="*130)
famiglie = genera_famiglie_settenarie()
totale_globale = {"attivazioni": 0, "A_succ": 0, "B_succ": 0, "C_succ": 0, "C_prob": [],
"D_coppie_tot": 0, "D_coppie_vin": 0, "D_prob": []}
num_ruote_analizzate = 0
print(f"\n[FASE UNICA] Analisi multi-ruota con finestra di {MAX_DELAY} estrazioni in corso...")
for codice_ruota, nome_ruota in RUOTE.items():
url_ruota = f"{URL_BASE}estrazioni-{codice_ruota}.txt"
estrazioni = scarica_estrazioni_da_url(url_ruota, nome_ruota)
if len(estrazioni) > MAX_DELAY:
statistiche = esegui_backtest_v7(estrazioni, famiglie, min_trigger=MIN_TRIGGER, max_delay=MAX_DELAY)
risultati = analizza_risultati_ruota_v7(nome_ruota, statistiche, famiglie, MAX_DELAY)
totale_globale["attivazioni"] += risultati["attivazioni"]
totale_globale["A_succ"] += risultati["A_succ"]
totale_globale["B_succ"] += risultati["B_succ"]
totale_globale["C_succ"] += risultati["C_succ"]
totale_globale["C_prob"].extend(risultati["C_prob"])
totale_globale["D_coppie_tot"] += risultati["D_coppie_tot"]
totale_globale["D_coppie_vin"] += risultati["D_coppie_vin"]
totale_globale["D_prob"].extend(risultati["D_prob"])
num_ruote_analizzate += 1
if num_ruote_analizzate > 0:
report_globale_v7(totale_globale, num_ruote_analizzate, MAX_DELAY)
print("\n[INFO] Analisi finale v7.0 completata. Buona ricerca, Lotto Avengers! 🚀")