◆FORGEfeature-oriented rule generation engine
GitHub ↗ PyPI ↗

Ricerca quantitativa · Python

Ogni pattern
merita un verdetto onesto.

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.

5
moduli in pipeline
0
dipendenze oltre numpy/pandas
4
verdetti possibili
MIT
licenza

Il problema

"Avrebbe funzionato nel passato" è la frase più pericolosa della ricerca quant.

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

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.

02

Ottimizzazione in-sample

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

Statistica ≠ operatività

Un evento statisticamente predittivo non è automaticamente redditizio: fee, ordini limite non eseguiti e orizzonti da chiudere comunque cambiano tutto.

Pipeline a 5 moduli

Ogni modulo risponde a una sola domanda, e passa avanti solo un artefatto formale.

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.

0

Market Context classificazione del regime

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.

Output → regime, regime_stable
1

Event Discovery nessun forward return

Scopre condizioni booleane dalla sola struttura temporale degli indicatori — frequenza, dispersione, stabilità mensile. Il rendimento futuro non entra mai in questo modulo.

Output → list[EventCandidate]
2

Alpha Discovery target derivato dai dati

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.

Output → list[AlphaContract]
3

Rule Discovery backtest realistico

Order mechanics, fee per lato, entrata a mercato o a limite, validazione walk-forward su finestre scorrevoli. Qui nasce il verdetto operativo.

Output → EDGE / PARTIAL-EDGE / NON-EDGE + parametri
4

Rule Registry generalizzazione cross-ticker

Deduplica le regole scoperte, le ribacktesta su altri asset e le classifica per genericità. Produce una tabella piatta e un report HTML autocontenuto.

Output → tabella + report.html (SVG inline, nessuna CDN)

Tre concetti, tre confini

Evento, Alpha, Regola: dal mercato al segnale, senza scorciatoie.

Un segnale di trading nasce solo dall'intersezione dei tre accertamenti — mai da uno solo di essi.

"Questa configurazione di mercato è stabile e ripetibile?"

Evento

Una condizione booleana su soglie distribuzionali — percentili calcolati sull'asset specifico, non valori assoluti — fissata prima di calcolare un solo rendimento futuro.

Gate → ConsistencyGate (frequenza, dispersione, no forward return)

"Questo evento predice statisticamente un rendimento orientato?"

Alpha

Orizzonte, direzione e take-profit derivati dai dati scansionando una grid e standardizzando contro una null di rotazione circolare — mai imposti dall'utente.

Gate → direction ≠ "undetermined" (unico gate hard)

"Questo alpha è redditizio con meccaniche d'ordine reali?"

Regola

Backtest con fee, fill realistici e validazione walk-forward su finestre scorrevoli train/test — il verdetto finale, non una stima.

Gate → EDGE / PARTIAL-EDGE / NON-EDGE / INSUFFICIENT-DATA

L'output finale

Mai un punteggio black-box. Sempre un verdetto motivato.

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.

EDGE

PF ≥ 2.0, win rate ≥ 55%, walk-forward consistency ≥ 50%, supera la null di rotazione a livello di sessione.

PARTIAL-EDGE

Supera i gate hard ma non tutti i gate EDGE: evidenza reale, non ancora operativamente solida.

NON-EDGE

PF < 1.5, mesi tutti negativi, o nessuna configurazione con fill rate adeguato.

INSUFFICIENT-DATA

Evidenza OOS troppo esigua per un giudizio con fiducia — non tradeable, ma non scartata: si rivaluta con più dati.

Cosa impedisce, non cosa promette

Quattro invarianti che la pipeline non può violare.

InvarianteCosa 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

Dalla KPI table alle regole validate, in una chiamata.

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.

$ pip install forgedge
single ticker
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
multi-ticker + report
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