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:
- Segnali Tecnici Standard: Pattern predefiniti e configurabili (es. “Volume Anomalo”, “RSI Ipervenduto”).
- Segnali da Strategie Personali: Eventi di
buy()osell()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 chiamabuy()osell()sull’ultima candela disponibile, garantendo che la logica eseguita sia identica a quella del backtester principale.
- Responsabilità: È il componente chiave per garantire la coerenza con il backtester. Esegue una simulazione completa ma leggera del ciclo
-
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
- Configurazione (UI): L’utente configura i segnali tramite
SignalConfigDialog. L’universo di ticker viene ricevuto dinamicamente dalWatchlist Manager. - Orchestrazione (Thread Principale): Al click su “Analizza Ora”, lo
ScannerTabWidgetraccoglie la configurazione attiva e la lista di ticker, quindi istanzia e avvia loScannerWorker. - Esecuzione (Thread in Background): Lo
ScannerWorkerinizia il suo ciclo: a. Itera su ogni ticker della watchlist. b. Per ogni ticker, richiede i dati storici alDataManager. 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 nelSignalEngine. d. Esegue le Strategie Personali: Per ogni strategia custom, usa loStrategyLoaderper caricarla, crea un’istanza delMockBacktestEnginee lancia la simulazione. e. Aggrega tutti i segnali trovati in una lista. - Comunicazione (Segnale): L’worker emette segnali di progresso e un segnale
finishedcon la lista completa dei risultati. - Visualizzazione (UI):
a. Lo
ScannerTabWidgetriceve i risultati e aggiorna il suo modello dati (SignalResultsModel), popolando la tabella. b. Se l’utente fa doppio click su una riga, emette un segnaleticker_selected_for_chartingche viene intercettato daMainWindowper 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.
-
Definire il Segnale (
signal_engine.py):- Apri
fire/synapses/scanner/signal_engine.py. - Aggiungi una nuova voce al dizionario
AVAILABLE_SIGNALScon una chiave univoca, unname(per la UI) e unafunction(il nome del metodo da implementare). - Se il segnale ha parametri, aggiungi una chiave
paramscon la loro definizione (key, name, type, default).
- Apri
-
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
stringadescrittiva se il segnale viene trovato, altrimentiNone.
- Nello stesso file, crea un nuovo metodo statico con il nome specificato in
-
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.
- Scrivere la Strategia: Crea una classe che eredita da
BaseStrategye implementa la logica ininit()enext(). - 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. - 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.