DD-SIGNAL-SCANNER.md

Versione: 1.0 Data: 2025-10-10 Scopo: Descrivere in dettaglio l’architettura, i pattern e il flusso di dati del sottosistema Signal Scanner, includendo guide pratiche per la sua estensione. Documento Principale: FIRE 25.07 - ARCHITECTURE-OVERVIEW


1. Panoramica e Responsabilità

Il “Signal Scanner” è una sinapsi proattiva progettata per rispondere alla domanda: “Cosa sta succedendo sul mercato adesso?“. La sua responsabilità è scansionare un universo di ticker definito dall’utente alla ricerca di “spunti operativi” (segnali), che possono essere:

  1. Segnali Tecnici Standard: Pattern predefiniti e configurabili (es. “Volume Anomalo”, “RSI Ipervenduto”).
  2. Segnali da Strategie Personali: Eventi di buy() o sell() generati da strategie Python custom dell’utente.

Un principio di design cruciale è garantire la coerenza dei risultati tra lo Scanner e il sottosistema di Backtesting. Un segnale generato da una strategia custom nello scanner deve corrispondere esattamente a quello che il backtester avrebbe generato sulla stessa candela.


2. Architettura e Componenti Chiave

  • ScannerTabWidget (Componente UI):

    • Responsabilità: È l’interfaccia principale. Si occupa di raccogliere la configurazione (quali segnali e strategie eseguire), avviare la scansione e visualizzare i risultati in una tabella performante (“Berti’s Table”). Ascolta i cambiamenti dal Watchlist Manager per aggiornare dinamicamente l’universo di ticker da analizzare.
  • SignalConfigDialog / SignalParamsDialog (UI di Configurazione):

    • Responsabilità: Fornire all’utente finestre di dialogo per selezionare e parametrizzare i segnali standard e per aggiungere/rimuovere strategie personali.
  • ScannerWorker (Worker Asincrono - QRunnable):

    • Responsabilità: Eseguire l’intero processo di scansione in background. Itera su tutti i ticker e, per ciascuno, esegue tutti i segnali e le strategie attive, aggregando i risultati.
  • SignalEngine (Motore per Segnali Standard):

    • Responsabilità: Contiene la logica di calcolo per tutti i segnali “built-in”. È una libreria di funzioni che ricevono dati di mercato e parametri e restituiscono un risultato.
  • MockBacktestEngine (Motore di Simulazione per Strategie):

    • Responsabilità: È il componente chiave per garantire la coerenza con il backtester. Esegue una simulazione completa ma leggera del ciclo init()/next() di una strategia custom sui dati di un singolo ticker. Rileva se la strategia chiama buy() o sell() sull’ultima candela disponibile, garantendo che la logica eseguita sia identica a quella del backtester principale.
  • Watchlist Manager (Servizio Core):

    • Responsabilità: Fornire l’universo di ticker da analizzare. Lo scanner non gestisce una propria lista, ma si abbona ai segnali del Watchlist Manager.
    • Approfondimento: DD-WATCHLIST-MANAGER.md

3. Flusso dei Dati

  1. Configurazione (UI): L’utente configura i segnali tramite SignalConfigDialog. L’universo di ticker viene ricevuto dinamicamente dal Watchlist Manager.
  2. Orchestrazione (Thread Principale): Al click su “Analizza Ora”, lo ScannerTabWidget raccoglie la configurazione attiva e la lista di ticker, quindi istanzia e avvia lo ScannerWorker.
  3. Esecuzione (Thread in Background): Lo ScannerWorker inizia il suo ciclo: a. Itera su ogni ticker della watchlist. b. Per ogni ticker, richiede i dati storici al DataManager. Critico: il worker rimuove la candela del giorno corrente se è incompleta, per allinearsi al comportamento del backtester. c. Esegue i Segnali Standard: Per ogni segnale “built-in”, invoca il metodo corrispondente nel SignalEngine. d. Esegue le Strategie Personali: Per ogni strategia custom, usa lo StrategyLoader per caricarla, crea un’istanza del MockBacktestEngine e lancia la simulazione. e. Aggrega tutti i segnali trovati in una lista.
  4. Comunicazione (Segnale): L’worker emette segnali di progresso e un segnale finished con la lista completa dei risultati.
  5. Visualizzazione (UI): a. Lo ScannerTabWidget riceve i risultati e aggiorna il suo modello dati (SignalResultsModel), popolando la tabella. b. Se l’utente fa doppio click su una riga, emette un segnale ticker_selected_for_charting che viene intercettato da MainWindow per visualizzare il grafico corrispondente, chiudendo il ciclo di interazione.

Approfondimento Tecnico: La tabella dei risultati è implementata usando il pattern Model-View-Delegate per garantire alte prestazioni. Per dettagli, fare riferimento alla guida [QC] Best Practice per Interfacce Utente.


4. Guide Pratiche

4.1. Come Aggiungere un Nuovo Segnale “Built-in” allo Scanner

L’architettura è progettata per rendere questo processo semplice e a basso rischio.

  1. Definire il Segnale (signal_engine.py):

    • Apri fire/synapses/scanner/signal_engine.py.
    • Aggiungi una nuova voce al dizionario AVAILABLE_SIGNALS con una chiave univoca, un name (per la UI) e una function (il nome del metodo da implementare).
    • Se il segnale ha parametri, aggiungi una chiave params con la loro definizione (key, name, type, default).
  2. Implementare la Logica (signal_engine.py):

    • Nello stesso file, crea un nuovo metodo statico con il nome specificato in function.
    • Il metodo deve accettare (df: pd.DataFrame, params: Dict) come argomenti.
    • Implementa la logica di analisi. Il metodo deve restituire una stringa descrittiva se il segnale viene trovato, altrimenti None.
  3. Test: Avvia l’applicazione. La UI di configurazione mostrerà automaticamente il nuovo segnale e i suoi parametri, senza modifiche al codice della UI.

4.2. Come Rendere una Strategia Personale Compatibile con lo Scanner

Grazie all’uso del MockBacktestEngine, la compatibilità è garantita dal design. Lo sviluppatore deve solo seguire le normali regole di scrittura delle strategie.

  1. Scrivere la Strategia: Crea una classe che eredita da BaseStrategy e implementa la logica in init() e next().
  2. Gestire lo Stato Correttamente: Per controllare se una posizione è aperta, usare sempre la property self.position (es. if not self.position: self.buy()). Non usare variabili custom per tracciare lo stato, poiché non sarebbero viste dall’engine.
  3. Utilizzare nello Scanner: Salva la strategia nella directory strategies/. Apri la UI di configurazione dello scanner e aggiungi il file. Il sistema si occuperà del resto.