Calcolatore del libro · C07
C07 — Il Criterio eseguibile: domande senza risposta e metro del caso
Calcolatore 7 — Il Criterio, eseguibile
Quaderno del capitolo «Il Criterio» di La matematica di chi perde.
Una lista di controllo che gira. Inserisci quello che sai di una proposta — periodo, numero di operazioni, percentuale di vincite, costi dichiarati — e ti restituisce due cose: le domande che restano senza risposta, e quale percentuale di tentativi casuali avrebbe prodotto un risultato altrettanto buono.
È la versione automatica del capitolo, e sta in una pagina.
Le righe marcate PROVA sono quelle da cambiare: cambiale e riesegui per vedere l'effetto. Il resto — comprese le righe marcate NON TOCCARE — serve a mantenere il risultato confrontabile con quello stampato nel libro.
Espandi lo script di questo passo
from math import ceil, erf, sqrt
import matplotlib.pyplot as plt
import numpy as np
from cvbook import seed_for
from cvbook.lingua import t1. Cosa sai della proposta
Compila quello che sai. Lascia None dove non ti è stato detto: è proprio quello il dato più informativo del quaderno.
Espandi lo script di questo passo
# PROVA / TRY: l'intero dizionario qui sotto è da riscrivere con la proposta
# che vuoi valutare — è il punto del quaderno, non un'eccezione alla regola.
PROPOSTA = {
# 1. I dati
"fonte_dichiarata": None, # es. "Binance, dump giornalieri" oppure None
"data_di_estrazione": None, # es. "2026-03-01" oppure None
"periodo_dal": "2015-01-01", # oppure None
"periodo_al": "2026-01-01", # oppure None
# 2. Il metodo
"regole_descritte": True, # si potrebbe ricostruire la procedura?
"soglie_dichiarate": True,
"costi_dichiarati": 0.0005, # frazione per operazione, oppure None
# 3. I limiti
"peggior_periodo_dichiarato": True,
"durata_peggior_periodo": True,
# 4. I fallimenti
"varianti_provate_dichiarate": None, # quante ne ha provate? None = non lo dice
"operazioni_in_perdita_mostrate": False,
# 5. La forza dell'evidenza
"numero_operazioni": 400,
"quota_vincenti": 0.58,
"risultato_finale": 6.0, # capitale finale, in volte
"durata_anni": 11,
# e la domanda che non e' nelle cinque
"come_guadagna": "vendita di un corso",
}2. Le cinque domande, contate
Output
punteggio: 3.0 su 5 senza risposta → 1. i dati: manca la fonte, la data di estrazione senza risposta → 4. i fallimenti: non si sa quante idee sono state scartate senza risposta → 5. l'evidenza: nessun confronto con il caso Probabilmente in buona fede, ma non ha verificato quanto crede. E la domanda che non e' fra le cinque: come guadagna? → vendita di un corso
Espandi lo script di questo passo
def valuta(p: dict) -> tuple[float, list[str]]:
punteggio, mancanti = 0.0, []
# 1. I dati
dati = [p["fonte_dichiarata"], p["data_di_estrazione"], p["periodo_dal"], p["periodo_al"]]
presenti = sum(x is not None for x in dati)
punteggio += presenti / len(dati)
if presenti < len(dati):
mancanti.append(t("1. i dati: manca ", "1. the data: missing ") + ", ".join(
n for n, x in zip(
t(("la fonte", "la data di estrazione", "l'inizio del periodo", "la fine del periodo"),
("the source", "the extraction date", "the start of the period", "the end of the period")),
dati) if x is None))
# 2. Il metodo
metodo = [p["regole_descritte"], p["soglie_dichiarate"], p["costi_dichiarati"] is not None]
punteggio += sum(bool(x) for x in metodo) / len(metodo)
if not all(metodo):
mancanti.append(t("2. il metodo: non si potrebbe rieseguire cosi' com'e' descritto",
"2. the method: it couldn't be rerun as described"))
# 3. I limiti
limiti = [p["peggior_periodo_dichiarato"], p["durata_peggior_periodo"]]
punteggio += sum(bool(x) for x in limiti) / len(limiti)
if not all(limiti):
mancanti.append(t("3. i limiti: non dice dove smette di funzionare",
"3. the limits: it doesn't say where it stops working"))
# 4. I fallimenti
fallimenti = [p["varianti_provate_dichiarate"] is not None,
bool(p["operazioni_in_perdita_mostrate"])]
punteggio += sum(fallimenti) / len(fallimenti)
if not all(fallimenti):
mancanti.append(t("4. i fallimenti: non si sa quante idee sono state scartate",
"4. the failures: unknown how many ideas were discarded"))
# 5. La forza dell'evidenza
evidenza = [p["numero_operazioni"] is not None, p.get("confronto_col_caso", False)]
punteggio += sum(bool(x) for x in evidenza) / len(evidenza)
if not evidenza[1]:
mancanti.append(t("5. l'evidenza: nessun confronto con il caso",
"5. the evidence: no comparison against chance"))
return punteggio, mancanti
punteggio, mancanti = valuta(PROPOSTA)
print(t(f"punteggio: {punteggio:.1f} su 5\n", f"score: {punteggio:.1f} out of 5\n"))
for m in mancanti:
print(t(" senza risposta → ", " unanswered → ") + m)
if punteggio < 3:
print(t("\nSotto le tre risposte su cinque non stai guardando conoscenza: "
"stai guardando un'inserzione.",
"\nBelow three answers out of five you're not looking at knowledge: "
"you're looking at an advertisement."))
elif punteggio < 4.5:
print(t("\nProbabilmente in buona fede, ma non ha verificato quanto crede.",
"\nProbably in good faith, but hasn't verified as much as it believes."))
else:
print(t("\nHa fatto il lavoro. Adesso puoi cominciare a valutare il merito.",
"\nIt did the work. Now you can start evaluating the merit."))
print(t(f"\nE la domanda che non e' fra le cinque: come guadagna? "
f"→ {PROPOSTA['come_guadagna']}",
f"\nAnd the question that isn't among the five: how does it make money? "
f"→ {PROPOSTA['come_guadagna']}"))3. Quale percentuale di tentativi casuali avrebbe fatto altrettanto
La domanda decisiva, e quella che quasi nessuno pone.
Istogramma della quota di operazioni vincenti ottenuta da 20.000 sequenze prive di vantaggio, con l'asse orizzontale da 40 a 60% e il conteggio fino a circa 1.600. La campana e' centrata su 50%; una riga verticale nera segna il 58% dichiarato dalla proposta in esame, che cade nella coda destra ed e' raggiunto per caso nello 0,09% dei casi.
Output
dichiarate 232 vittorie su 400 operazioni (58%) con una moneta equa capita nel 0.09% dei casi Non sappiamo quante varianti siano state provate. Assumi che siano state parecchie: e' l'ipotesi realistica. con 5 varianti: almeno una ci arriva nel 0.4% dei casi con 20 varianti: almeno una ci arriva nel 1.8% dei casi con 100 varianti: almeno una ci arriva nel 8.6% dei casi
Espandi lo script di questo passo
N_PROVE = 20_000 # PROVA / TRY: 2000 (veloce) · 20000 · 100000 (coda più precisa)
rng = np.random.default_rng(seed_for("calc-criterio"))
# NON TOCCARE / DO NOT CHANGE: il seme fissa l'istogramma e la percentuale
# citati nel testo; con N_PROVE già a 20.000 il seme conta pochissimo, ma la
# regola resta la stessa di tutto il libro: non si cambia dopo aver visto il numero.
# The seed fixes the histogram and the percentage quoted in the text; with
# N_PROVE already at 20,000 the seed barely matters, but the rule stays the
# same as the rest of the book: you don't change it after seeing the number.
n = PROPOSTA["numero_operazioni"]
vinte = int(round(PROPOSTA["quota_vincenti"] * n))
esiti = rng.binomial(n, 0.5, N_PROVE)
quota_caso = float((esiti >= vinte).mean())
with avvio.figura("schermo"):
fig, ax = plt.subplots()
ax.hist(esiti / n * 100, bins=50)
ax.axvline(PROPOSTA["quota_vincenti"] * 100, linewidth=2.5, color="black")
ax.set_xlabel(t("Quota di operazioni vincenti (%)", "Share of winning trades (%)"))
ax.set_ylabel(t(f"Su {N_PROVE:,} sequenze prive di vantaggio",
f"Out of {N_PROVE:,} sequences with no edge"))
plt.show()
print(t(f"dichiarate {vinte} vittorie su {n} operazioni ({PROPOSTA['quota_vincenti']:.0%})",
f"claimed {vinte} wins out of {n} trades ({PROPOSTA['quota_vincenti']:.0%})"))
print(t(f"con una moneta equa capita nel {quota_caso:.2%} dei casi",
f"with a fair coin this happens in {quota_caso:.2%} of cases"))
if PROPOSTA["varianti_provate_dichiarate"]:
tentativi = PROPOSTA["varianti_provate_dichiarate"]
print(t(f"con {tentativi} varianti provate, almeno una ci arriva nel "
f"{1 - (1 - quota_caso) ** tentativi:.1%} dei casi",
f"with {tentativi} variants tried, at least one gets there in "
f"{1 - (1 - quota_caso) ** tentativi:.1%} of cases"))
else:
print(t("\nNon sappiamo quante varianti siano state provate. Assumi che siano "
"state parecchie: e' l'ipotesi realistica.",
"\nWe don't know how many variants were tried. Assume there were "
"quite a few: it's the realistic assumption."))
for tentativi in (5, 20, 100):
print(t(f" con {tentativi:3d} varianti: almeno una ci arriva nel "
f"{1 - (1 - quota_caso) ** tentativi:5.1%} dei casi",
f" with {tentativi:3d} variants: at least one gets there in "
f"{1 - (1 - quota_caso) ** tentativi:5.1%} of cases"))4. Il campione basta?
Output
vantaggio medio implicito per operazione: 0.449% operazioni necessarie per dimostrarlo: 277 operazioni dichiarate: 400 → il campione e' sufficiente: servirebbero 0.7 volte le operazioni dichiarate costi dichiarati: 0.05% per operazione vantaggio al netto di costi realistici (0,12%): 0.379% per operazione
Espandi lo script di questo passo
def quantile_normale(p: float) -> float:
basso, alto = -10.0, 10.0
for _ in range(200):
mezzo = (basso + alto) / 2
if 0.5 * (1 + erf(mezzo / sqrt(2))) < p:
basso = mezzo
else:
alto = mezzo
return (basso + alto) / 2
vantaggio_implicito = (PROPOSTA["risultato_finale"] ** (1 / n)) - 1
oscillazione = 0.03 # ipotesi prudente sull'oscillazione per operazione
servono = int(ceil(((quantile_normale(0.95) + quantile_normale(0.80))
* oscillazione / max(vantaggio_implicito, 1e-9)) ** 2))
print(t(f"vantaggio medio implicito per operazione: {vantaggio_implicito:.3%}",
f"implied average edge per trade: {vantaggio_implicito:.3%}"))
print(t(f"operazioni necessarie per dimostrarlo: {servono:,}",
f"trades needed to prove it: {servono:,}"))
print(t(f"operazioni dichiarate: {n:,}",
f"trades claimed: {n:,}"))
print(t(f"→ il campione e' {'sufficiente' if n >= servono else 'INSUFFICIENTE'}: "
f"servirebbero {servono / max(n, 1):.1f} volte le operazioni dichiarate",
f"→ the sample is {'sufficient' if n >= servono else 'INSUFFICIENT'}: "
f"it would take {servono / max(n, 1):.1f} times the claimed trades"))
costi = PROPOSTA["costi_dichiarati"]
if costi is not None:
print(t(f"\ncosti dichiarati: {costi:.2%} per operazione",
f"\nstated costs: {costi:.2%} per trade"))
print(t(f"vantaggio al netto di costi realistici (0,12%): "
f"{vantaggio_implicito - (0.0012 - costi):.3%} per operazione",
f"edge net of realistic costs (0.12%): "
f"{vantaggio_implicito - (0.0012 - costi):.3%} per trade"))Cosa fare da domani
Prendi tre cose che ti sono passate davanti nell'ultimo mese: un video, un post, la pubblicità di un corso. Compila PROPOSTA per ciascuna e segna il punteggio.
Non aspettarti di scoprire dei truffatori. Scoprirai qualcosa di più utile e più scomodo: che nella maggior parte dei casi non c'è materiale sufficiente nemmeno per compilare la tabella. E quando non c'è materiale per le domande, non stai valutando una proposta debole: stai valutando una proposta vuota, e il tuo lavoro è finito in trenta secondi.
Riproducibilità e download
Eseguito il 2026-08-27 dal quaderno del repository
Il quaderno
calc_07_criterio.ipynb16,5 KB
sha256 ba42129238a88eb466bd374ad2474c23c098ee097971203dfd3cf261b04ecc7b
calc_07_criterio.py12,7 KB
sha256 d18ca449670115337641aaafc7f813b8dad9da9d6cd4e92ab2b4be6fd14af623