Proposta eccellente. Apprezzo molto il modo in cui hai sintetizzato le nostre scoperte in una nuova ipotesi di trading chiara, misurabile e innovativa.
Questo è esattamente il ciclo di ricerca che volevamo stabilire: Osservazione → Ipotesi → Prototipo → Test.
Valutazione della Proposta: MomentumStrategy_v3_BandWidthFilter
- Ipotesi Solida: L’idea di usare l’ampiezza delle bande come proxy per la “confidenza” del modello è un’intuizione da trader quantitativo professionista. Stai aggiungendo una seconda dimensione all’analisi: non ci chiediamo più solo “cosa prevede il modello?”, ma anche “quanto è sicuro di ciò che prevede?“. Filtrare i segnali per agire solo nei momenti di alta confidenza è una tecnica robusta per migliorare la qualità dei trade.
- Gestione del Rischio Integrata: L’inclusione di uno stop loss percentuale, oltre al time exit, introduce un meccanismo di gestione del rischio ancora più disciplinato. Questo è un passo avanti fondamentale rispetto alla V2 e dovrebbe contribuire a tagliare le perdite in modo ancora più efficace.
- Parametrizzazione Chiara: Hai già identificato i parametri chiave da ottimizzare, il che rende la strategia un framework flessibile per la ricerca futura.
Decisione: Proposta approvata. Procediamo con la traduzione e il test.
Come per la strategia precedente, il codice che hai fornito è per il framework backtesting.py. Procedo a “tradurlo” per il nostro framework quantum-core / FIRE, in modo da poterlo eseguire nel nostro ambiente.
I punti principali della traduzione sono:
- Adattare il calcolo degli indicatori al nostro
init(). - Usare
self.iper l’accesso ai dati. - Implementare la logica di stop loss, che richiede di memorizzare il prezzo di entrata all’interno della strategia stessa.
Delta modifiche: +68 / -0 (file nuovo)
Ecco il codice tradotto per il nuovo file fire/strategies/momentum_strategy_v3_band_width_filter.py.
# VERSION: v1.0 - fire/strategies/momentum_strategy_v3_band_width_filter.py
# RESP: Strategia di momentum che filtra gli ingressi in base alla confidenza del modello (ampiezza delle bande).
# DEPS: BaseStrategy, pandas, numpy.
# TODO: N/A
from fire.strategies.base_strategy import BaseStrategy
import pandas as pd
import numpy as np
class MomentumStrategy_v3_BandWidthFilter(BaseStrategy):
"""
MomentumStrategy_v3_BandWidthFilter
-----------------------------------
Strategia basata sul modello TimesFM, che combina il segnale direzionale
(`forecast_h5 > close`) con un filtro sull'incertezza predittiva
(misurata come ampiezza delle bande di confidenza).
Logica:
- Entra long se il forecast a 5 periodi è maggiore del prezzo corrente
E l'ampiezza della banda di confidenza è tra le più basse (alta confidenza).
- Esce dopo un numero fisso di barre (`hold_period`) O se si verifica uno stop loss.
Obiettivo:
Sfruttare le previsioni del modello solo nei momenti di alta sicurezza statistica.
"""
# --- Parametri Configurabili ---
hold_period = 5
forecast_horizon = 5
band_width_quantile = 0.3 # Soglia per "alta confidenza" (es. 30° percentile)
stop_loss_pct = 0.02 # Stop loss del 2%
def init(self):
"""
Inizializzazione: calcola gli indicatori derivati e li aggiunge al DataFrame.
"""
# Nomi delle colonne dinamici
forecast_col = f'forecast_h{self.forecast_horizon}'
lower_col = f'forecast_lower_h{self.forecast_horizon}'
upper_col = f'forecast_upper_h{self.forecast_horizon}'
required_cols = [forecast_col, lower_col, upper_col]
if not all(col in self.data.columns for col in required_cols):
raise ValueError(f"Colonne necessarie {required_cols} non trovate.")
# Calcola l'ampiezza della banda e la aggiunge come colonna
self.data["band_width"] = self.data[upper_col] - self.data[lower_col]
# Calcola la soglia statica per il filtro di confidenza
self.bandwidth_threshold = self.data["band_width"].quantile(self.band_width_quantile)
# Variabile di stato per lo stop loss
self.entry_price = 0.0
print(f"[Strategy] MomentumStrategy_v3_BandWidthFilter Inizializzata.")
print(f" - Hold Period: {self.hold_period} barre")
print(f" - Stop Loss: {self.stop_loss_pct*100:.1f}%")
print(f" - Soglia Confidenza (Band Width): < {self.bandwidth_threshold:.4f}")
def next(self):
"""
Logica di trading eseguita ad ogni barra.
"""
# --- 1. Gestione dell'Uscita (se in posizione) ---
if self.position:
# Condizione di Time Exit
time_exit_triggered = self.trade_bars >= self.hold_period
# Condizione di Stop Loss
stop_loss_triggered = self.close < self.entry_price * (1 - self.stop_loss_pct)
if time_exit_triggered:
self.sell()
return
if stop_loss_triggered:
self.sell()
return
# --- 2. Gestione dell'Ingresso (se non in posizione) ---
if not self.position:
forecast_col = f'forecast_h{self.forecast_horizon}'
# Recupera i valori per la barra corrente
forecast = self.data[forecast_col].iloc[self.i]
band_width = self.data["band_width"].iloc[self.i]
# Controlla se i dati sono validi
if np.isnan(forecast) or np.isnan(band_width):
return
# Applica i filtri di ingresso
is_bullish = forecast > self.close
is_high_confidence = band_width < self.bandwidth_threshold
if is_bullish and is_high_confidence:
self.buy()
# Memorizza il prezzo di entrata per lo stop loss
self.entry_price = self.closeRiepilogo della Traduzione
- Calcolo degli Indicatori: In
init(), ho replicato la tua logica calcolandoband_widthcome nuova colonna del DataFrame. Ho calcolatobandwidth_thresholdcome valore statico basato sul quantile dell’intera serie. Questo è un approccio semplice e veloce. - Gestione dello Stato: Ho aggiunto
self.entry_price = 0.0ininit()per memorizzare il prezzo di entrata, necessario per la logica di stop loss. - Logica di
next():- La logica è stata divisa in due blocchi chiari: gestione dell’uscita e gestione dell’ingresso.
- La logica di uscita ora controlla sia il
time exit(usandoself.trade_bars) sia lostop loss(confrontandoself.closeconself.entry_price). - La logica di ingresso, eseguita solo se non si è in posizione, applica il doppio filtro (direzione + confidenza) che hai progettato.
- Quando un ordine
buyviene eseguito, il prezzo di chiusura corrente viene salvato inself.entry_price.
Prossimi Passi
Il codice è pronto per il test. Seguiamo il tuo piano:
- Salva questo file come
fire/strategies/momentum_strategy_v3_band_width_filter.py. - Esegui un backtest su AAPL (o un altro ticker a tua scelta).
- Forniscimi il report completo delle metriche e il trade log.
Confronteremo i risultati con quelli della MomentumStrategyV2TimeExit per vedere se la nostra ipotesi (più qualità, meno trade) è stata confermata.