FIRE DD-DATA-ENRICHMENT.md

Versione: 1.0 Data: 2025-10-29 Scopo: Descrivere l’architettura della pipeline di arricchimento dati, un sistema “plug-and-play” per pre-processare i dati di backtest con provider esterni (es. modelli AI). Documento Principale: FIRE 25.07 - ARCHITECTURE-OVERVIEW


1. Filosofia: Dati come “Ingredienti” Componibili

Le strategie di trading più sofisticate spesso richiedono più dei semplici dati OHLCV. Possono necessitare di previsioni da modelli AI, punteggi di sentiment da analisi di news, o dati macroeconomici.

L’architettura tradizionale, in cui la strategia è responsabile di calcolare tutto, è inefficiente e monolitica. La Pipeline di Arricchimento Dati di FIRE adotta un approccio diverso: i dati complessi vengono trattati come “ingredienti” che possono essere richiesti da una strategia e preparati da “fornitori” (provider) specializzati prima ancora che il backtest inizi.

Questo design si basa su tre principi chiave:

  1. Separazione delle Responsabilità: La strategia dichiara di cosa ha bisogno. I provider forniscono i dati. L’orchestratore gestisce il processo.
  2. Estensibilità (Plug-and-Play): Aggiungere un nuovo modello AI (es. Chronos, Prophet) non richiede di modificare l’architettura core, ma solo di creare un nuovo provider e registrarlo.
  3. Efficienza: I calcoli computazionalmente intensivi (come il forecasting “rolling”) vengono eseguiti una sola volta all’inizio, rendendo il ciclo di backtest barra-per-barra estremamente veloce.

2. Architettura del Flusso Dati: La Catena Asincrona

Il processo non avviene all’interno di un singolo componente, ma è orchestrato come una catena di eventi asincroni gestita a un livello superiore (il BacktestOrchestrator), garantendo che la UI rimanga sempre reattiva.

graph TD
    subgraph "UI Thread (Orchestrazione)"
        A(1. Backtest Richiesto) --> B{2. La strategia<br>richiede arricchimento?};
        B -- No --> E[5a. Avvia BacktestWorker<br>con dati grezzi];
        B -- Sì --> C(3. Avvia il primo<br>Enrichment Worker);
        C --> D{4. Altri provider<br>in coda?};
        D -- Sì --> C;
        D -- No --> F[5b. Avvia BacktestWorker<br>con dati arricchiti];
    end

    subgraph "Worker Threads (Esecuzione)"
        C --> W1(Enrichment Worker 1<br><i>(es. TimesFM)</i>);
        W1 -- Dati Arricchiti --> D;
        E --> W2(Backtest Worker);
        F --> W2;
    end

3. Componenti Chiave

  • BaseStrategy (Il Cliente): La strategia dichiara le sue dipendenze tramite l’attributo di classe data_enrichment_providers: List[str].
  • data_enrichment_registry.py (L’Elenco Telefonico): Un registro centrale che mappa i nomi dei provider (es. 'timesfm_forecast') alle classi dei worker che sanno come generare quei dati (es. TimesFMEnrichmentWorker).
  • Worker di Arricchimento (I Fornitori): Classi specializzate (es. TimesFMEnrichmentWorker) che ereditano da QRunnable. Il loro unico compito è ricevere un DataFrame e restituire, tramite il segnale finished, un nuovo DataFrame con le colonne aggiuntive.
  • BacktestOrchestrator (Il Direttore d’Orchestra): Questo componente gestisce l’intera pipeline asincrona. Legge le dipendenze della strategia, interroga il registro e avvia i worker di arricchimento in sequenza, passando l’output di uno come input del successivo.
  • BacktestWorker (L’Esecutore Finale): È stato semplificato. Ora riceve i dati finali (grezzi o arricchiti) e l’oggetto strategia, e si concentra esclusivamente sull’esecuzione del backtest barra-per-barra.

4. Guida Pratica per Sviluppatori di Strategie

Come Usare un Provider Esistente

Per utilizzare i dati di un provider, è sufficiente specificare il suo nome nella lista data_enrichment_providers della tua strategia.

from fire.strategies.base_strategy import BaseStrategy
 
class MiaStrategiaPredittiva(BaseStrategy):
    # Dichiaro che ho bisogno dei dati generati da 'timesfm_forecast'
    data_enrichment_providers = ['timesfm_forecast']
    
    def next(self):
        # Ora posso usare le proprietà API in modo sicuro
        if self.close > self.forecast:
            # ... la mia logica ...
            pass

Provider Disponibili Attualmente:

Nome ProviderColonne AggiunteDescrizione
timesfm_forecastforecast, forecast_lower_band, forecast_upper_bandGenera previsioni rolling a 10 periodi e un intervallo di confidenza all’80%.

5. Guida per Contributori: Come Creare un Nuovo Provider

Aggiungere un nuovo modello AI (es. Chronos) al sistema è un processo strutturato in 3 passi:

  1. Creare il Worker di Arricchimento:

    • Crea un nuovo file in fire/workers/enrichment/, ad esempio chronos_enrichment_worker.py.
    • La classe deve ereditare da QRunnable e avere una classe WorkerSignals interna.
    • Il costruttore deve accettare il DataFrame dei dati come input.
    • Il metodo run() deve contenere la logica per generare le nuove colonne (es. chronos_forecast).
    • Al termine, il worker deve emettere il segnale finished con un dizionario contenente il DataFrame arricchito: self.signals.finished.emit({"data": enriched_df}).
    • Deve emettere segnali progress durante i cicli lunghi.
  2. Registrare il Provider:

    • Apri fire/logic/data_enrichment_registry.py.
    • Importa la tua nuova classe worker.
    • Aggiungi una nuova voce al dizionario DATA_ENRICHMENT_PROVIDERS, associando un nome univoco (es. 'chronos_forecast') alla tua classe worker.
  3. Aggiornare BaseStrategy (Opzionale ma Consigliato):

    • Apri fire/strategies/base_strategy.py.
    • Aggiungi nuove proprietà @property per fornire un accesso semplificato alle nuove colonne generate dal tuo worker. Questo rende l’API più pulita e robusta per gli sviluppatori di strategie.

Una volta completati questi tre passi, qualsiasi strategia potrà richiedere il nuovo arricchimento semplicemente aggiungendo il nome del provider alla sua lista di dipendenze.