Smart Data Pipeline & Cache Architecture
1. Filosofia: Sovranità del Dato
In un software finanziario professionale, fidarsi ciecamente dei dati forniti dai provider è un rischio. Molti provider (es. Yahoo Finance) forniscono dati storici già rettificati (Adjusted) per default, nascondendo la storia reale dei prezzi (es. i “gap” dovuti agli split).
La Smart Data Pipeline di FIRE inverte questo paradigma:
- Storage RAW: Salviamo su disco sempre e solo i dati Grezzi (RAW). Se il provider non ce li dà, li calcoliamo inversamente.
- Metadati Separati: Salviamo gli eventi corporativi (Split, Dividendi) in un file separato.
- Rettifica On-Demand: L’applicazione applica la rettifica matematica in memoria solo quando l’utente lo richiede (Toggle ADJ/RAW).
Questo approccio garantisce che il database locale di FIRE sia “puro” e agnostico rispetto alle preferenze di visualizzazione momentanee.
2. Ontologia dei Dati
FIRE classifica ogni dataset storico secondo una tassonomia rigorosa definita nel campo data_nature dei metadati.
| Tipo (Enum) | Descrizione | Comportamento DataManager |
|---|---|---|
RAW | Dati grezzi storici. I prezzi riflettono il valore di mercato reale al momento dello scambio. | ✅ Ideale. FIRE può applicare rettifiche matematiche se sono presenti eventi (Split). |
ADJUSTED | Dati già rettificati dal provider. Non è possibile risalire al prezzo originale con certezza assoluta. | 🔒 Locked. Il sistema forza la modalità “Adjusted”. Il toggle RAW è disabilitato o ininfluente. |
UNKNOWN | Dati di origine ignota (es. CSV importato manualmente senza metadati). | ⚠️ As-Is. I dati vengono mostrati come sono. Non vengono applicate rettifiche automatiche. |
3. Architettura di Storage: Il Pattern “Sidecar”
Per ogni richiesta dati (es. Ticker NVDA, Timeframe 1d), FIRE crea nella directory market_data_cache due file gemelli:
3.1. Il File Dati (.csv)
Contiene le serie temporali numeriche.
- Formato: CSV (ottimizzato per leggibilità/debug) o Parquet (futuro, per performance).
- Contenuto: Colonne Standard
Open, High, Low, Close, Volume. - Invariante: I valori qui dentro sono sempre normalizzati a RAW.
3.2. Il File Metadati (.meta.json)
Il “passaporto” del dato. Contiene le informazioni necessarie per interpretare e trasformare il CSV.
Esempio Reale (NVDA_1d.meta.json):
{
"ticker": "NVDA",
"interval": "1d",
"last_updated": "2025-12-10T10:00:00",
"data_nature": "RAW",
"events_source": "provider_api",
"splits": {
"1718026200": { // Timestamp Unix
"date": 1718026200,
"numerator": 10.0,
"denominator": 1.0,
"splitRatio": "10:1"
}
},
"dividends": { ... }
}4. Algoritmi di Rettifica
Il cuore matematico della pipeline gestisce due flussi opposti.
4.1. Reverse Adjustment (Normalizzazione in Scrittura)
- Quando: Al momento del download dal Provider (es. Yahoo).
- Problema: Yahoo invia prezzi Adjusted anche se chiediamo Raw, ma ci invia anche i metadati dello Split.
- Soluzione: Calcoliamo il Raw originale per salvarlo pulito.
Dove (es. 10/1 = 10).
4.2. Forward Adjustment (Rettifica in Lettura)
- Quando: Quando il
DataManagerserve i dati alla UI/Worker e il flaguse_adjusted=True. - Logica: Si applica la rettifica a tutte le candele antecedenti la data dello split.
5. Flusso Dati (Data Flow)
5.1. Scrittura (Download & Cache)
graph LR A[Yahoo API] -->|JSON Mixed| B[YahooConnector] B -->|Extract Splits| C{Has Splits?} C -- Yes --> D[Reverse Adj Logic] C -- No --> E[Pass Through] D --> F[Tuple: DF_RAW + Meta] E --> F F --> G[DataManager] G -->|Write| H[(Disk: .csv + .json)]
5.2. Lettura (Fetch & Serve)
graph LR A[Worker Request] -->|Args: use_adj=True| B[DataManager] B -->|Check| C[(Disk Cache)] C -->|Load| D[DF_RAW + Meta] D --> E{User wants Adj?} E -- Yes --> F{Nature == RAW?} F -- Yes --> G[Apply Math / Ratio] G --> H[Return DF_ADJ] E -- No --> I[Return DF_RAW]
6. Thread Safety & Determinismo
Per garantire la stabilità in ambiente multithreaded (Qt), la pipeline adotta rigorosamente il Snapshot Pattern.
- Configurazione: La preferenza globale (
SettingsManager.use_adjusted_prices) è gestita come Singleton. - Snapshot: Quando un Worker viene creato, copia il valore booleano della preferenza nel suo costruttore.
- Esecuzione: Durante il
run(), il Worker passa questo valore “congelato” alDataManagertramite il parametrouse_adjusted_override.
Regola d’Oro: Un Worker non deve mai leggere SettingsManager direttamente durante l’esecuzione. Deve usare solo i valori passati al suo __init__.