01
Look-ahead bias
Se la soglia di un evento viene scelta guardando quanto rende, la soglia "conosce" già il futuro. Ogni backtest che segue è circolare, non predittivo.
Ricerca quantitativa · Python
FORGE è un motore open source per la scoperta sistematica di regole di trading algoritmico da dati storici di mercato. Prende una KPI table, ne estrae eventi con struttura temporale stabile, ne misura il potere predittivo e li mette alla prova in un backtest realistico — separando rigidamente ogni fase per non lasciare che il segnale "impari" il futuro prima del tempo.
>>> from forgedge import forge >>> kpi = pd.read_parquet("kpi_table.parquet") >>> # pipeline completa: dalla KPI table alle regole validate >>> result = forge(kpi, ticker="BTCUSDC", timeframe="1H") >>> # EDGE / PARTIAL-EDGE soltanto, con motivazione allegata >>> for contract, response in result.edges(): ... print(contract.alpha_id, response.verdict) rsi14_spread_ema9_25 EDGE bb_width_p20_break PARTIAL-EDGE
Il problema
Con abbastanza tempo, qualsiasi pattern può essere fatto sembrare un edge: basta scegliere le soglie giuste dopo aver visto i rendimenti. FORGE nasce per chiudere tre falle ricorrenti, una per una.
01
Se la soglia di un evento viene scelta guardando quanto rende, la soglia "conosce" già il futuro. Ogni backtest che segue è circolare, non predittivo.
02
Cercare il miglior orizzonte, il miglior take-profit e il miglior filtro sugli stessi dati usati per misurare il Profit Factor produce un PF che riflette il rumore del campione, non una struttura reale.
03
Un evento statisticamente predittivo non è automaticamente redditizio: fee, ordini limite non eseguiti e orizzonti da chiudere comunque cambiano tutto.
Pipeline a 5 moduli
Nessun modulo accede ai dati del successivo. Nessuna soglia viene ricalibrata dopo la scoperta. Il flusso va in una sola direzione: dalla KPI table al report finale.
Classifica ogni barra della KPI table per regime di mercato su 5 livelli, così che l'edge scoperto possa in seguito essere letto anche per dipendenza dal contesto.
regime, regime_stableScopre condizioni booleane dalla sola struttura temporale degli indicatori — frequenza, dispersione, stabilità mensile. Il rendimento futuro non entra mai in questo modulo.
list[EventCandidate]Prima esposizione al forward return. Orizzonte, direzione e take-profit non sono assunti: sono misurati per ogni evento e confermati su una coda out-of-sample mai toccata prima.
list[AlphaContract]Order mechanics, fee per lato, entrata a mercato o a limite, validazione walk-forward su finestre scorrevoli. Qui nasce il verdetto operativo.
EDGE / PARTIAL-EDGE / NON-EDGE + parametriDeduplica le regole scoperte, le ribacktesta su altri asset e le classifica per genericità. Produce una tabella piatta e un report HTML autocontenuto.
report.html (SVG inline, nessuna CDN)Tre concetti, tre confini
Un segnale di trading nasce solo dall'intersezione dei tre accertamenti — mai da uno solo di essi.
"Questa configurazione di mercato è stabile e ripetibile?"
Una condizione booleana su soglie distribuzionali — percentili calcolati sull'asset specifico, non valori assoluti — fissata prima di calcolare un solo rendimento futuro.
"Questo evento predice statisticamente un rendimento orientato?"
Orizzonte, direzione e take-profit derivati dai dati scansionando una grid e standardizzando contro una null di rotazione circolare — mai imposti dall'utente.
"Questo alpha è redditizio con meccaniche d'ordine reali?"
Backtest con fee, fill realistici e validazione walk-forward su finestre scorrevoli train/test — il verdetto finale, non una stima.
L'output finale
Rule Discovery integra gate hard e soft — Profit Factor, win rate, Sharpe deflazionato, dipendenza dal regime, consistenza walk-forward — in uno dei quattro esiti seguenti.
PF ≥ 2.0, win rate ≥ 55%, walk-forward consistency ≥ 50%, supera la null di rotazione a livello di sessione.
Supera i gate hard ma non tutti i gate EDGE: evidenza reale, non ancora operativamente solida.
PF < 1.5, mesi tutti negativi, o nessuna configurazione con fill rate adeguato.
Evidenza OOS troppo esigua per un giudizio con fiducia — non tradeable, ma non scartata: si rivaluta con più dati.
Cosa impedisce, non cosa promette
| Invariante | Cosa impedisce |
|---|---|
| Modulo 1 non vede mai il forward return | Look-ahead bias nella selezione dell'evento |
| Le soglie sono immutabili dopo la scoperta | Ottimizzazione delle soglie sul campione di valutazione |
| Orizzonte, direzione e take-profit sono derivati dai dati per ogni evento | Assunzioni economiche che precuociono il risultato |
| Il verdetto tradeable è vincolato al walk-forward OOS (Modulo 3) | Conferma a posteriori di una conclusione già scontata |
Quick start
FORGE dipende solo da numpy e pandas. Tutte le primitive statistiche — Spearman, t-test, regressione OU, FDR di Benjamini-Hochberg, beta incompleta — sono implementate in puro numpy: nessuna dipendenza da scipy, statsmodels o librerie ML.
from forgedge import forge kpi = pd.read_parquet("kpi_table.parquet") result = forge(kpi, ticker="BTCUSDC", timeframe="1H") print(result.summary()) # una riga per candidato + rule_verdict print(result.registry.summary()) # Modulo 4 — regole catalogate
from forgedge import forge_multi frames = {"BTCUSDC": btc, "ETHUSDC": eth} results, registry = forge_multi(frames, timeframe="1H") # GENERIC: la regola regge su ≥ 2/3 dei ticker df = registry.flat_table() html = registry.html_report(timeframe="1H") open("report.html", "w").write(html) # SVG inline, autocontenuto, nessuna CDN