Aggiunge il meta-modello, il database locale e la pipeline di ricerca della guida
Il bot ora ha un secondo parere prima di ogni ingresso: un classificatore GBDT (scritto in C#, senza dipendenze native) addestrato sugli esiti dei segnali passati con triple-barrier e meta-labeling, validato con CPCV, PBO e Sharpe deflazionato contando tutte le configurazioni provate. Il modello non propone mai operazioni: può solo rifiutarne una sotto la probabilità minima o ridurne la size, e si sospende da solo quando le feature dal vivo derivano da quelle di addestramento. Senza un campione promosso il bot opera come prima. Perché tutto questo serve, e nell'ordine in cui è stato fatto: - I log del giro reale sul testnet mostravano zero barre chiuse in tre giorni: il decodificatore saltava l'oggetto annidato dei kline. Corretto con test di regressione. Lo stesso giro restava a 1499/1500 barre di riscaldamento perché Binance ne serve al massimo 1500 per richiesta: il client ora pagina e il motore chiede quante ne servono davvero. - Il log è diventato una tabella `;` con data, livello, sorgente, evento ed eccezione (grep `;ERR;` trova ogni errore), con rotazione a dimensione impostabile dalla finestra. Anche decisions.csv/executions.csv/trades.csv hanno intestazione stabile, id monotoni e colonna `motivazione`, e vengono scritti anche in SQLite. - La configurazione vive in Documenti\Encelado (con migrazione dal file accanto all'eseguibile), le credenziali restano in LocalAppData, il database in %ProgramData%\Encelado: tre cartelle per tre ruoli diversi. - In modalità demo gli ordini partono davvero sul testnet (dryRun spento di fabbrica): è l'unico modo di provare il percorso di esecuzione come in produzione. - Lo strumento di backtest copre le fasi 0-4 della guida: qualità dei dati, baseline buy&hold/SMA con PSR e DSR, Engle-Granger + Johansen + Kalman con costo di break-even, dataset e addestramento del meta-modello, DQN su molti seed. Ogni tabella è CSV `;` con motivazione, e la promozione a campione avviene solo se il modello supera i criteri della Fase 3. Sui dati disponibili nessuna coppia supera quei criteri, quindi nessun campione è stato promosso: il bot resta sulla sola regola statistica, che a sua volta non regge fuori campione. Il risultato è documentato, non nascosto. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"_comment": "Encelado — arbitraggio statistico su coppie cointegrate, Binance Futures USDⓈ-M. Il bot non prende posizione sulla direzione del mercato: è long una gamba e short l'altra nel rapporto che il test di cointegrazione produce, e scommette solo sul fatto che la distanza fra le due si richiuda.",
|
||||
|
||||
"_misura": "IMPORTANTE — che cosa dice il backtest, e perché dryRun parte ATTIVO. Misurato su 6,6 anni di barre da un minuto (2020-2026) di ETHUSDT, BTCUSDT, SOLUSDT e AVAXUSDT, ripiegate su 5m, 15m, 30m, 1h e 4h, con commissione taker 4 bps più 1 bp di slippage per lato. Il risultato: su 5m nessuna combinazione di soglie supera nemmeno i filtri di taratura; su 15m e 1h la ricerca a griglia trova combinazioni che rendono in taratura e in verifica, ma NESSUNA delle prime dieci resta positiva sulla terza fetta, quella che non entra mai nella scelta. Con i valori qui sotto, sulle quattro coppie misurabili, la conferma dà tre risultati negativi e uno positivo del +0,40% su una sola operazione. La ragione di fondo è che il test di cointegrazione passa solo l'8-13% del tempo, quindi in sei anni una coppia produce qualche decina di operazioni: troppo poche per distinguere un margine reale da una serie fortunata. Questi valori sono i meglio supportati fra quelli provati, non una strategia dimostrata. Falla girare in dry-run finché non hai visto coi tuoi occhi come si comporta sul tuo conto. Lo strumento è in tools/Encelado.Backtest: 'backtest basket --data <cartella>' rifa la scelta da capo sui tuoi dati.",
|
||||
"_misura": "IMPORTANTE — che cosa dice il backtest, e perché dryRun parte ATTIVO. Misurato su 6,6 anni di barre da un minuto (2020-2026) di ETHUSDT, BTCUSDT, SOLUSDT e AVAXUSDT, ripiegate su 5m, 15m, 30m, 1h e 4h, con commissione taker 4 bps più 1 bp di slippage per lato. Il risultato: su 5m nessuna combinazione di soglie supera nemmeno i filtri di taratura; su 15m e 1h la ricerca a griglia trova combinazioni che rendono in taratura e in verifica, ma NESSUNA delle prime dieci resta positiva sulla terza fetta, quella che non entra mai nella scelta. Con i valori qui sotto, sulle quattro coppie misurabili, la conferma dà tre risultati negativi e uno positivo del +0,40% su una sola operazione. La ragione di fondo è che il test di cointegrazione passa solo l'8-13% del tempo, quindi in sei anni una coppia produce qualche decina di operazioni: troppo poche per distinguere un margine reale da una serie fortunata. Questi valori sono i meglio supportati fra quelli provati, non una strategia dimostrata: per questo la configurazione di fabbrica punta alla TESTNET, dove gli ordini partono davvero ma i soldi sono finti. Lo strumento è in tools/Encelado.Backtest: 'backtest basket --data <cartella>' rifà la scelta da capo sui tuoi dati.",
|
||||
|
||||
"binance": {
|
||||
"_testnet": "true = testnet (denaro finto, stesse API). Metterlo a false opera con denaro reale. Le chiavi dei due ambienti sono diverse e vengono salvate separatamente.",
|
||||
@@ -39,8 +39,8 @@
|
||||
"_postOnly": "Solo maker (GTX). Fa risparmiare la commissione ma un ordine che non esegue lascia una gamba scoperta, che costa molto di più. Lasciare false se non hai misurato il tuo tasso di riempimento.",
|
||||
"postOnlyEntries": false,
|
||||
|
||||
"_dryRun": "ATTIVO DI FABBRICA, e la ragione è nella nota _misura qui sopra. Calcola e registra tutto, non invia nessun ordine. Toglilo solo dopo aver visto in Stato che le tue coppie passano davvero il test di cointegrazione.",
|
||||
"dryRun": true,
|
||||
"_dryRun": "Calcola e registra tutto, non invia nessun ordine. Spento di fabbrica: in testnet i soldi sono finti e la prova più vicina alla produzione è quella con gli ordini veri sul conto di prova — eseguiti, rifiutati, parzialmente riempiti, con le stesse regole di lotto e di margine. Accendilo per osservare una configurazione nuova senza toccare nemmeno il conto di prova. Sul conto reale resta comunque la conferma esplicita all'avvio.",
|
||||
"dryRun": false,
|
||||
|
||||
"_reconcile": "Ogni quanto il bot ricontrolla conto, posizioni e ordini contro Binance. È anche quando recupera le barre che lo stream non ha consegnato e chiude le coppie rimaste con una gamba sola.",
|
||||
"reconcileSeconds": 20,
|
||||
@@ -96,7 +96,7 @@
|
||||
"_level": "trace | debug | info | warn | error | none. Ogni rifiuto che ferma un ordine viene scritto a 'info' o sopra, quindi 'debug' serve per il flusso dati, non per capire perché il bot non ha operato.",
|
||||
"level": "info",
|
||||
|
||||
"_directory": "Dove salvare tutti gli output. Relativa all'eseguibile, oppure un percorso assoluto. Si cambia anche da Impostazioni.",
|
||||
"_directory": "Dove salvare tutti gli output. Relativa alla cartella della configurazione (Documenti\\Encelado), oppure un percorso assoluto. Si cambia anche da Impostazioni.",
|
||||
"directory": "logs",
|
||||
|
||||
"console": false,
|
||||
@@ -104,8 +104,8 @@
|
||||
"maxFileSizeMb": 32,
|
||||
"maxFiles": 10,
|
||||
|
||||
"_analysis": "decisions.csv ha una riga per ogni barra valutata con spread, z-score e calibrazione; executions.csv una riga per ogni segnale arrivato agli ordini, con il verdetto del risk engine. Si uniscono su decisionId.",
|
||||
"tradeJournal": "trades.jsonl",
|
||||
"_analysis": "Tutte le tabelle usano il separatore ; e hanno una colonna motivazione che spiega in italiano il perché della riga. decisions.csv ha una riga per ogni barra valutata con spread, z-score e calibrazione; executions.csv una riga per ogni segnale arrivato agli ordini, con il verdetto del risk engine; trades.csv una riga per ogni evento d'ordine. decisions ed executions si uniscono su decisionId.",
|
||||
"tradeJournal": "trades.csv",
|
||||
"decisionLog": "decisions.csv",
|
||||
"executionLog": "executions.csv",
|
||||
|
||||
@@ -114,6 +114,26 @@
|
||||
"bufferedLines": 5000
|
||||
},
|
||||
|
||||
"storage": {
|
||||
"_note": "Il database locale (SQLite): barre canoniche, dataset, modelli, validazioni, journal e drift. Vuoto = %ProgramData%\\Encelado\\encelado.db, una cartella di sistema separata sia da Documenti (dove sta la configurazione) sia dai dati utente (dove stanno le chiavi).",
|
||||
"enabled": true,
|
||||
"databasePath": ""
|
||||
},
|
||||
|
||||
"ml": {
|
||||
"_note": "Il meta-modello (meta-labeling): un classificatore addestrato sugli esiti dei segnali passati che dice se un ingresso proposto dalla regola statistica ha probabilità di ripagare i costi. Non propone mai operazioni: può solo rifiutarne una o ridurne la size. Si addestra con lo strumento tools/Encelado.Backtest (comandi dataset, train) e vive nel database locale come 'campione' della coppia; senza campione queste voci non fanno nulla.",
|
||||
"enabled": true,
|
||||
"_minProbability": "Sotto questa probabilità predetta l'ingresso viene rifiutato. 0.55 significa: opero solo quando il modello vede un vantaggio, anche piccolo, rispetto a lanciare una moneta.",
|
||||
"minProbability": 0.55,
|
||||
"_sizeByProbability": "Con true la size è proporzionale alla convinzione del modello (2·Φ(z)−1, López de Prado), fra minSizeFraction e 1; con false è tutto o niente.",
|
||||
"sizeByProbability": true,
|
||||
"minSizeFraction": 0.25,
|
||||
"_drift": "Ogni driftCheckBars segnali valutati le feature live vengono confrontate con quelle di addestramento (PSI e Kolmogorov-Smirnov). Una feature con PSI ≥ driftPsiAlert è 'in deriva'; con driftAlertsToSuspend feature in deriva il modello viene sospeso fino alla ricalibrazione successiva e il bot torna alla sola regola statistica. 0 = mai sospendere, solo registrare.",
|
||||
"driftCheckBars": 50,
|
||||
"driftPsiAlert": 0.25,
|
||||
"driftAlertsToSuspend": 3
|
||||
},
|
||||
|
||||
"_pairs": "Il paniere della guida. Ogni coppia si legge come ln(A) − β·ln(B): A è la gamba su cui si misura lo spread, B quella di copertura. Il test di cointegrazione decide da solo, a ogni ricalibrazione, se una coppia è operabile: quelle che non passano restano in elenco e non vengono aperte. Sui dati disponibili passano il test solo l'8-17% del tempo, quindi il bot resta fermo a lungo — è il comportamento previsto.",
|
||||
|
||||
"_parametri": "I valori qui sotto vengono dalla ricerca a griglia (tools/Encelado.Backtest, comando 'basket'), non dalla guida. Le differenze rispetto alla guida sono tre e sono tutte misurate: zWindow 1500 invece di 100, entryZ 2.5 invece di 2.0, stopZ 6.0 invece di 3.5. La prima è la più importante: con una finestra vicina all'emivita del rientro (30-40 barre) la media mobile insegue lo scostamento e lo assorbe, e il margine sparisce prima ancora delle commissioni.",
|
||||
|
||||
Reference in New Issue
Block a user