1. Filosofia: “Dichiara i Parametri, Lascia che FIRE Costruisca la UI”

Per trasformare uno script di backtesting in uno strumento flessibile, i parametri hardcoded devono essere eliminati. FIRE adotta un approccio dichiarativo: la strategia definisce quali sono i suoi parametri, e il framework si occupa di generare automaticamente una finestra di dialogo per permettere all’utente di modificarli.

Questo disaccoppia la logica della strategia dalla sua interfaccia di configurazione, rendendo il sistema modulare e facilmente estensibile.

2. Definire i Parametri (self.add_parameter)

Per rendere un valore configurabile, devi “dichiararlo” usando il metodo self.add_parameter all’interno del costruttore (__init__) della tua strategia.

Sintassi

self.add_parameter(name, default, type, label, **kwargs)
  • name (str): Obbligatorio. Il nome della variabile interna. Sarà la chiave per accedere al valore in self.params. Es: 'ema_length'.
  • default (any): Obbligatorio. Il valore di default del parametro.
  • type (str): Obbligatorio. Il tipo di input da mostrare nella UI. Valori supportati:
    • 'int': Campo numerico intero (QSpinBox).
    • 'float': Campo numerico con decimali (QDoubleSpinBox).
    • 'bool': Casella di controllo (QCheckBox).
    • 'color': Selettore di colore (ColorPickerLabel).
    • 'select': Menu a tendina (QComboBox).
    • 'str': Campo di testo (QLineEdit).
  • label (str): Etichetta leggibile da mostrare nella UI. Se omesso, viene generato dal name (es. ema_length Ema Length).
  • **kwargs: Argomenti opzionali specifici per tipo.
    • Per int e float: min, max, step.
    • Per float: decimals.
    • Per select: options=['EURUSD', 'GBPUSD'].

3. Usare i Parametri nella Strategia

Una volta dichiarati, i valori correnti dei parametri sono sempre disponibili nel dizionario self.params.

Dove usarli?

Accedi a self.params all’interno dei metodi init() e next() per influenzare la logica e la visualizzazione della tua strategia.

Esempio Completo: SlingShotStrategy

# In fire/strategies/slingshot_strategy.py
 
class SlingShotStrategy(BaseStrategy):
    def __init__(self):
        super().__init__()
        self.name = "TAPLOT SlingShot"
        
        # --- Dichiarazione dei parametri ---
        self.add_parameter("ema_length", 4, type="int", min=1, label="EMA Length")
        self.add_parameter("show_ema", True, type="bool", label="Show EMA Line?")
        self.add_parameter("paint_bar", True, type="bool", label="Paint Bar?")
        self.add_parameter("bar_color", "#FFD700", type="color", label="Bar Color")
 
    def init(self):
        # --- Uso dei parametri ---
        ema_len = self.params["ema_length"]
        show_ema = self.params["show_ema"]
        
        self.ema_high_series = self.data['high'].ewm(span=ema_len, adjust=False).mean()
        
        if show_ema:
            self.plot(self.ema_high_series, name=f"EMA High ({ema_len})", ...)
 
    def next(self):
        # ...
        if is_slingshot:
            # --- Uso dei parametri ---
            if self.params["paint_bar"]:
                self.set_bar_color(self.params["bar_color"])

4. Il Flusso Dati Dietro le Quinte (Architettura)

  1. Apertura Dialogo: L’utente clicca il pulsante “⚙️” nel BacktestTabWidget.
  2. Lettura Configurazione: Il widget chiama strategy.get_parameters_config() per ottenere le definizioni dei parametri. Legge anche eventuali valori salvati in precedenza da SettingsManager.
  3. Costruzione UI: Il StrategySettingsDialog riceve queste definizioni e costruisce dinamicamente il form con i widget appropriati (QSpinBox, QCheckBox, etc.).
  4. Conferma Utente: L’utente modifica i valori e preme “OK”.
  5. Salvataggio: Il BacktestTabWidget recupera i nuovi valori dal dialogo e li salva in SettingsManager in un file JSON, garantendo la persistenza tra le sessioni.
  6. Rilancio: Il BacktestTabWidget emette un segnale per rieseguire il backtest.
  7. Iniezione Parametri: Il BacktestOrchestrator intercetta la richiesta, carica l’istanza della strategia, legge i parametri salvati da SettingsManager e li “inietta” nella strategia chiamando strategy.update_parameters(saved_params).
  8. Esecuzione: La strategia viene eseguita dal BacktestEngine con i nuovi valori.