DD-DATA-CONNECTORS.md

Versione: 1.0 Data: 2025-10-15 Scopo: Descrivere l’architettura del sottosistema di gestione dei dati in FIRE, inclusa la logica di orchestrazione e il pattern per l’aggiunta di nuovi provider di dati (connettori). Documento Principale: FIRE 25.07 - ARCHITECTURE-OVERVIEW


1. Filosofia Architetturale

Il sottosistema di gestione dei dati è progettato per essere modulare, estensibile e disaccoppiato. L’obiettivo primario è isolare il resto dell’applicazione dalla complessità e dalle specificità di come e da dove vengono recuperati i dati di mercato. Questo si basa su tre pilastri:

  1. Interfaccia Unificata (AbstractDataConnector): Definisce un “contratto” standard che ogni provider di dati deve rispettare. Qualsiasi componente che necessita di dati interagisce con questa interfaccia astratta, non con un’implementazione concreta.

  2. Orchestrazione Centrale (DataManager): Agisce come unico punto di contatto (facade) per il resto dell’applicazione. Gestisce la priorità dei connettori, il failover (se un provider fallisce, prova con il successivo) e l’accesso alle loro capacità. Nessun componente UI deve mai istanziare o comunicare direttamente con un connettore.

  3. Discovery Automatico: I nuovi connettori aggiunti alla directory fire/connectors/ vengono scoperti e registrati automaticamente all’avvio dell’applicazione, senza necessità di registrazione manuale.


2. Il Pattern del “Connettore Auto-Descrittivo” (get_capabilities)

Un problema comune nelle applicazioni che si basano su API esterne è la gestione dei limiti imposti da tali API (es. limiti di rate, profondità dei dati storici). Inserire questa logica di limitazione nel codice della UI è un errore architetturale che crea forte accoppiamento e rende il codice fragile.

Per risolvere questo problema, FIRE adotta il pattern del “Connettore Auto-Descrittivo”.

2.1. La Soluzione

L’interfaccia AbstractDataConnector obbliga ogni connettore a implementare il metodo:

def get_capabilities(self) -> Dict[str, int]:

Questo metodo restituisce un dizionario che descrive i limiti di lookback (profondità storica) del provider per ogni timeframe.

  • Chiave (str): Il timeframe (es. “1h”, “5m”).
  • Valore (int): Il numero massimo di giorni di dati storici che il provider può fornire per quel timeframe.
  • Convenzione: Un valore di -1 indica che non ci sono limiti noti. Un dizionario vuoto indica che il provider non ha limiti predefiniti (come nel caso di LocalCSVConnector).

2.2. Il Flusso di Lavoro

Quando un componente UI (come il grafico di backtest) deve richiedere dati, il flusso è il seguente:

  1. La UI chiede al DataManager quali sono le capacità del provider attivo: caps = data_manager.get_active_provider_capabilities().
  2. La UI ottiene il limite per il timeframe selezionato: limit = caps.get(selected_timeframe).
  3. Se esiste un limite, la UI adatta i parametri della richiesta (in particolare, la start_date) per rispettarlo.
  4. Solo a questo punto la UI invia al DataManager la richiesta di dati, già validata e conforme ai limiti del provider.

Questo approccio sposta la responsabilità della conoscenza dei limiti dove deve essere: nel connettore stesso.


3. Guida Pratica: Come Aggiungere un Nuovo Connettore

Grazie al discovery automatico, aggiungere un nuovo provider di dati è un processo strutturato.

  1. Creare il File: Crea un nuovo file Python nella directory fire/connectors/, ad esempio mio_nuovo_connector.py.

  2. Implementare l’Interfaccia: La tua nuova classe deve ereditare da AbstractDataConnector e implementare tutti i suoi metodi astratti.

  3. Scrivere il Codice: Utilizza il seguente template come punto di partenza.

    # fire/connectors/mio_nuovo_connector.py
    from typing import Optional, Dict
    import pandas as pd
    from ..core.data.abstract_data_connector import AbstractDataConnector
     
    class MioNuovoConnector(AbstractDataConnector):
        @property
        def name(self) -> str:
            # Nome univoco che apparirà nelle impostazioni
            return "MioNuovoProvider"
     
        def get_capabilities(self) -> Dict[str, int]:
            # Definisci i limiti del tuo provider
            return {
                "1m": 30,
                "1h": 365,
                "1d": -1
            }
     
        def get_historical_data(self, ticker, start_date, end_date, timeframe) -> Optional[pd.DataFrame]:
            # ... Qui va la logica per chiamare la nuova API ...
            # ... e per formattare i dati in un DataFrame pandas ...
            # con le colonne [Open, High, Low, Close, Volume] e un DatetimeIndex.
            pass
     
        def check_availability(self) -> (bool, str):
            # (Opzionale) Aggiungi un controllo, es. per una API key.
            # Se non serve, puoi ometterlo e userà l'implementazione base.
            api_key = "..."
            if not api_key:
                return False, "API Key non configurata"
            return True, "Available"
  4. Configurare nelle Impostazioni: Avvia FIRE. Il tuo nuovo connettore apparirà automaticamente nella sezione “Data Providers” delle impostazioni. Abilitalo e impostane la priorità per iniziare a usarlo.


4. Riepilogo dei Connettori Esistenti

Nome ConnettoreDescrizioneCapacità Chiave (Limiti Intraday)
YahooFinanceProvider principale. Non richiede API key.1h: 365 giorni, 30m/15m/5m: 30 giorni, 1m: 7 giorni.
AlphaVantageProvider alternativo. Richiede API key.Tutti i timeframe intraday sono limitati a circa 60 giorni (assumendo un piano gratuito).
LocalCSVCarica dati da file .csv locali. Non ha limiti intrinseci.Nessun limite predefinito (get_capabilities restituisce {}).