BtcSpotDualTimeframeMomentumConfluenceLong
Ipotesi
BTC Spot Dual-Timeframe Momentum Confluence, LONG-ONLY 1x (BTCUSDT.BINANCE_SPOT, Primary 4H + Confirm 1D, Solo Long Quando BOTH Timeframe Puntano UP, FLAT Cash Altrimenti, Exit ATR-Trailing + Daily-Regime-Break, Parametri Source-Optimised Mantenuti)
Ipotesi
Un port per account LONG-ONLY, 1x, CASH della migliore strategia promossa della factory (BtcDualTimeframeMomentumConfluenceLS, Sharpe 1.99, trade 458, +$4,774 su 29 giorni di paper) su BTCUSDT.BINANCE_SPOT, creato specificamente come FIRST LIVE-TRADING CANDIDATE perché il venue live è solo spot. Meccanismo invariato, puro-OHLCV, single-instrument: gamba FAST = segno del rendimento trailing a 18 barre su barre 4-HOUR; gamba SLOW = segno del rendimento trailing a 15 barre su barre DAILY (letto via on_extra_bar come gamba di contesto, mai una barriera di sync). Entrambe devono AGREE. L'unico cambiamento strutturale che l'account CASH forza è il collasso di {LONG/FLAT/SHORT} in {LONG/FLAT}: dove il parent futures va SHORT su confluenza joint-down, la versione spot mantiene 100% USDT. Tutto il resto è preservato verbatim: trailing stop ATR(14) a 3.033x ATR dall'estremo corrente, exit per regime break giornaliero, sizing vol-scaled capital-relative (risk_pct 1.011% / distanza stop 3.033xATR), cap di max-nozionale 49.7%, e l'esatto vettore di parametri selezionato dall'ottimizzazione sorgente (fast_lookback 18, slow_lookback 15, trail_atr_mult 3.033). Tre tunables, nessun dato supplementare, nessuno short, nessuna leva. Modifiche al codice specifiche per spot: venue BINANCE_SPOT CASH (nessun moltiplicatore di leva in position_size), size_precision 5 / price_precision 2, min_notional $10, vendite dimensionate solo sulla quantità base detenuta. Dati verificati presenti: barre BTCUSDT.BINANCE_SPOT 4-HOUR e 1-DAY corrono continuamente da 2017-08-17 (~9 anni, ~19,800 barre 4H).
Ipotesi
Porting diretto del parent futures promosso BtcDualTimeframeMomentumConfluenceLS sul venue spot, perché il venue live previsto è solo spot. Meccanismo preservato verbatim: le stesse due gambe momentum, lo stesso gate AGREE-o-flat, lo stesso trailing stop ATR(14) 3.033x dall'estremo corrente, lo stesso exit per regime break giornaliero, lo stesso sizing vol-scaled risk_pct / distanza-stop con cap di nozionale 49.7%, e l'esatto vettore di parametri selezionato dall'ottimizzazione sorgente (fast_lookback 18, slow_lookback 15, trail_atr_mult 3.033). L'account CASH forza esattamente un cambiamento strutturale, come specificato dall'ipotesi: {LONG,FLAT,SHORT} collassa in {LONG,FLAT} — should_enter restituisce BUY solo su joint-up e None altrimenti, quindi joint-down è 100% USDT piuttosto che uno short. Modifiche specifiche per spot: venue BINANCE_SPOT con leva 1.0 e nessun termine di leva in position_size, size_precision 5 / price_precision 2 (BTCUSDT spot), min_notional alzato a $10, e tutti gli exit instradati attraverso il close_position reduce-only del template base così un SELL può solo cedere la quantità base detenuta (uno short spot nudo è impossibile per costruzione, e la guardia _would_open_spot_short del base non viene mai triggerata). calculate_signal restituisce il rendimento 4H a 18 barre continuo ogni barra (varia di barra in barra); il gate di confluenza discreto vive in should_enter, come richiesto. Il costo per barra è O(1): il ATR usa una finestra fissa di 15 barre e il rendimento fast è una singola lookup indicizzata, quindi non c'è lavoro di history-scaling. Un caveat onesto per l'Analista: il costo round-trip spot è ~0.20% contro ~0.10% sul parent futures, quindi l'edge per trade deve superare il doppio dell'attrito — la struttura di exit trend-following (trail + regime break, nessun take-profit fisso) è ciò che rende la durata media abbastanza lunga perché ciò sia plausibile, ma è la metrica da monitorare per prima.
Implementazione
LONG-ONLY 1x BTCUSDT spot (BINANCE_SPOT, CASH) dual-timeframe momentum confluence. Gamba FAST = segno del rendimento trailing a 18 barre su barre 4-HOUR (primary); gamba SLOW = segno del rendimento trailing a 15 barre su barre 1-DAY, consumata via on_extra_bar come gamba di contesto su timeframe più lento (timeframe diverso, quindi la barriera di allineamento cross-leg del template base non differisce mai il segnale 4H). Entrambe le gambe devono puntare UP per mantenere BTC; joint-down (dove il parent futures shorta) e disaccordo significano entrambi mantenere 100% USDT. Exit: trailing stop ATR(14) a 3.033x ATR sotto il picco corrente della posizione, OR la gamba daily che gira al ribasso sotto il long (regime break su timeframe superiore). Il sizing è vol-scaled e capital-relative: equity * 1.011% / (3.033 * ATR), cappato al 49.7% del saldo USDT in nozionale, con moltiplicatore di leva NO (l'account CASH non può prendere a prestito), quantizzato a size_precision 5 e rifiutato sotto il min notional spot $10. Tre tunables, puro OHLCV, nessun dato supplementare, nessuno short.
Risultati di verifica
O usa self._atr (corrente) nel confronto del trail di should_exit per matchare esattamente il parent, o dichiara esplicitamente nella descrizione che il trail è ancorato alla barra di ingresso ATR così l'analista non attribuisce la divergenza dal parent al cambio di venue.
Risultati di verifica
Il ATR del trailing-stop è FROZEN all'ingresso (self._entry_atr, catturato in should_enter / all'adozione della posizione) e mai aggiornato, quindi la distanza del trail è 3.033 x ATR-at-entry piuttosto che 3.033 x ATR(14) corrente. Il parent futures promosso (BtcDualTimeframeMomentumConfluenceLS4H) fa ratchet del suo trail con il CURRENT ATR ogni barra. La formulazione dell'ipotesi ('trailing stop ATR(14) a 3.033x ATR dall'estremo corrente') è soddisfatta in entrambi i casi, e poiché _extreme è monotono il livello di stop sale ancora solo verso l'alto, quindi questo non è un difetto di correttezza — ma su un'espansione di vol dopo l'ingresso lo stop effettivo è più stretto di quello del parent, che è una reale differenza comportamentale dalla strategia che si dichiara di portare 'verbatim'.
Risultati di verifica
Imposta lo stato del trade dal fill (on_order_filled / prima barra con una posizione aperta) piuttosto che dentro should_enter, o resettalo in modo difensivo all'inizio di calculate_signal prima della lookup della posizione.
Risultati di verifica
should_enter() muta lo stato del trade (_in_long = True, _extreme, _entry_atr) BEFORE che il template base ha dimensionato l'ordine e applicato il gate di min-nozionale. Se position_size() restituisce 0 o il check di min-nozionale $10 scarta l'ingresso, la strategia resta flaggata come in-long con un trail armato mentre è flat. In pratica questo si auto-ripara sulla barra successiva (calculate_signal vede che position è None e resetta i flag, e should_exit non viene mai raggiunto mentre flat), quindi non c'è un bug comportamentale osservabile — ma l'invariante è fragile se il path di exit viene mai cambiato.
Risultati di verifica
Nessuna correzione richiesta per correttezza. Se si vuole il consumo esatto stessa barra, ricalcola _slow_dir lazily da self._extra_bars[...] dentro calculate_signal invece di cacharlo in on_extra_bar.
Risultati di verifica
Latenza di una barra sulla gamba daily: la barra DAILY e l'ultima barra 4H del giorno condividono lo stesso timestamp di chiusura. Se il motore consegna prima la barra primaria 4H, _maybe_process_primary() viene eseguito e timbra _last_processed_ts, e l'aggiornamento _slow_dir della barra daily (che arriva allo stesso ts) viene consumato solo dalla barra NEXT 4H. Questo è conservativo (può solo ritardare un segnale, mai leakare dati futuri), ma significa che l'exit per regime break giornaliero può attivarsi fino a 4 ore dopo la chiusura daily in circa metà dei casi, e la parità backtest/paper dipende dal fatto che l'ordine di consegna sia stabile.
Risultati di verifica
Implementazione fedele, ma tre cose che l'analista dovrebbe valutare sulla storia completa: (1) il round-trip spot è ~0.20% contro ~0.10% del parent futures, quindi lo stesso edge lordo netta circa la metà — il sandbox mostra già commissioni al 10.03% del lordo; (2) il vettore dei parametri (fast 18 / slow 15 / trail 3.033) è stato selezionato da una run di ottimizzazione su un set di venue DIFFERENT, mix di timeframe e direzione (LONG/SHORT futures), quindi questo è un trasferimento out-of-sample, non una configurazione ottimizzata — lo Sharpe nel sandbox è 0.527 con sharpe_ci_low -0.233 e information_ratio -0.760 contro il benchmark, ossia un book BTC solo long che sottoperforma rispetto al mantenimento di BTC sulla finestra smoke; (3) eliminare la gamba short rimuove circa metà della popolazione di trade del parent (250 trade, tutti long, esposizione 43.6%), quindi lo Sharpe realizzato dovrebbe essere previsto ben al di sotto del 1.99 del parent piuttosto che vicino ad esso. La prima cosa da verificare sul backtest reale: avg_trade_return_pct contro il pavimento spot 0.25% (il sandbox mostra 0.82%, ma quella finestra esclude 2017 ed è solo 2401 giorni) e se il terzile di vol 'normale' (-8.77% nel sandbox) resta negativo sulla storia completa.
Revisione Backtest
314 trade chiusi su 3146 giorni (2017-08 → 2026-03), metrics_reliable=true, entry_diag 314/314 ingressi inviati con 0 scartati.
Revisione Backtest
I trade implementano l'ipotesi: tutti 314 LONG / 0 short (corretto collasso CASH del LONG/FLAT/SHORT del parent), max nozionale/equity 0.50 contro il cap 0.497, durata media 4d8h ed esposizione 43.6% che riproduce il parent futures.
Revisione Backtest
avg_trade_return_pct 1.20% contro un round trip ~0.20% BINANCE_SPOT; commissioni solo 8.97% del lordo, impatto 4.33% — non fee-marginal.
Revisione Backtest
max_drawdown 10.3% (sotto il default spot 15%), PF 1.41, payoff 2.07 su un hit rate 40.4% (forma del trend corretta), terzile di vol stressato +28.0%.
Revisione Backtest
Concentrazione estrema: i primi 10 di 314 trade = 93.8% della somma del rendimento per trade, i primi 20 = 141% (trade 21–314 netti negativi).
Revisione Backtest
Solo 6/10 anni di calendario positivi — esattamente al pavimento rigido — ed entrambi gli anni recenti negativi (2025 −10.5%, 2026 −9.9%).
Revisione Backtest
Sharpe 0.664 con sharpe_ci_low 0.0042 e PSR 0.924 (<0.95): già marginale prima della barra di selezione a ~225 tentativi.
Revisione Backtest
La preoccupazione di QA parzialmente confermata: il terzile di vol 'normale' resta negativo (−7.70%, 16.1% DD), information_ratio −0.757, alpha solo +2.4%/anno — sottoperforma rispetto al mantenimento di BTC, e benchmark_meaningful=true quindi tale shortfall è reale.
Revisione Backtest
I parametri sono un trasferimento out-of-sample da un altro set di venue/direzione — non tunati piuttosto che overfittati, ma anche non testati qui.
Stratmill è uno strumento di ricerca e paper trading, non una consulenza finanziaria né un broker. I risultati di backtest e paper trading sono ipotetici. Il trading comporta un rischio di perdita.