Passa al contenuto principale

Fase 3 — Ranking personalizzato per utente

La Fase 3 prende i dati di sistema prodotti dalla Fase 2 e li personalizza per ogni utente, applicando pesi customizzati e filtri definiti dall'utente stesso.

Frequenza: giornaliera, dopo il completamento della Fase 2.

Il processo produce due tabelle distinte:

  • daily_scores — indicatori tecnici e score calcolati con pesi di default, organizzata per (symbol, score_date). Non è legata a nessun utente o pipe specifico.
  • scores_daily — score ricalcolati con i pesi personalizzati dell'utente, organizzata per (symbol, score_date, user_id, pipe_id). Ogni combinazione utente/pipe produce una classifica indipendente.

Il risultato finale è la lista "best-of" del giorno per utente e pipe.


Scheda operativa

VoceDettaglio
ScopoProdurre ranking utente/pipe personalizzati.
Punto di partenzadaily_scores + configurazioni utente (scoring_models, filtri).
Deliverablescores_daily per (symbol, score_date, user_id, pipe_id).
Microservizi coinvoltitickerscanner, scheduler (trigger), potenzialmente authservice/datahub per contesto utente.

Parametri di pilotaggio

ParametroTipoUso
userIdnumeroIdentifica il perimetro utente da processare.
pipeIdnumeroSeleziona la strategia/pipeline utente.
targetDate/score_datedataData di riferimento dello scoring.
filtersoggettoRegole inclusione/esclusione simboli.
weightsoggettoPesi custom sui componenti di score.
modenormal/forceRicalcolo idempotente o rigenerazione completa.

Concetto di "Pipe"

Una pipe è una configurazione di scoring indipendente. Ogni utente può avere più pipe, ognuna con pesi e filtri diversi per strategia:

Esempio pipeLogica
Pipe 1 — DefaultPesi di sistema, nessun filtro
Pipe 2 — ValueValuation al 60%, quality al 40%, esclude momentum
Pipe 3 — ETF MomentumSolo ETF, risk 50%, momentum 50%
Pipe 4 — GrowthQuality al 50%, momentum al 30%, esclude settori ciclici

Ogni pipe produce una classifica separata e indipendente.

Nota su pipeId=0

Il pipeId=0 è riservato al sistema e non è una pipe utente. Identifica il ranking globale di sistema generato dalla Fase 4 (AST_RANKING_DAILY), che il decision-engine usa come sorgente quando elabora segnali su tutti i simboli senza una configurazione utente specifica. Le pipe utente iniziano sempre da 1.


Pesi personalizzati

L'utente può ridefinire il peso di ogni componente di score nella formula del total_score. I pesi devono sommare a 1.

ComponenteDefault (azioni)Default (ETF)Personalizzabile
valuation_score30%0%
quality_score40%0%
risk_score20%50%
momentum_score10%50%

I pesi possono essere definiti anche a un livello più granulare:

  • Momentum long vs short — quanto peso dare al momentum di lungo vs breve periodo
  • Volume score — quanto peso dare alla componente di volume nel momentum
  • Market risk — quanto peso dare al rischio di mercato corrente nel risk score

I pesi sono salvati nella tabella scoring_models con versioning, in modo da poter ricostruire esattamente come è stato calcolato uno score in qualsiasi data passata.


Filtri utente

I filtri permettono di escludere o includere titoli in base a criteri specifici. Ogni filtro è una condizione su un campo di universe o daily_scores.

Esempi di filtri tipici:

FiltroTipoEsempio
SettoreInclusioneSolo Technology, Healthcare
ETFEsclusioneEscludi is_etf = 1
CapitalizzazioneSoglia minimaSolo market_cap > 1B USD
LiquiditàSoglia minimaSolo dollar_vol_20d > 500k USD
Score minimoSogliaSolo total_score > 60
PaeseInclusione/EsclusioneSolo USA
VolatilitàSoglia massimaSolo atr_14_pct < 5%

I filtri vengono applicati prima del ranking, in modo da escludere i titoli non conformi dalla classifica finale.


Output: due tabelle distinte

daily_scores — score di sistema (non legata all'utente)

Chiave primaria: (symbol, score_date).

Viene scritta una volta sola per ogni simbolo e data, indipendentemente da chi ha avviato il job. Se il job viene rieseguito per la stessa data, i record vengono aggiornati (upsert).

CampoDescrizione
pricePrezzo di chiusura alla data
ret_1d / ret_5d / ret_20d / ret_60dRendimenti su 1, 5, 20, 60 giorni
sma_10 / sma_20 / sma_50 / sma_200Medie mobili semplici
sma_20_slope / sma_50_slopePendenza delle SMA (trend direction)
atr_14Average True Range 14 giorni (volatilità assoluta)
atr_14_pctATR normalizzato sul prezzo (volatilità relativa %)
rsi_14RSI 14 giorni
avg_gap_20Gap overnight medio su 20 giorni
max_dd_60Drawdown massimo su 60 giorni
dollar_vol_20dVolume in dollari medio su 20 giorni
valuation_scoreComponente valutazione
quality_scoreComponente qualità
risk_scoreRisk strutturale
momentum_scoreMomentum di lungo periodo
momentum_short_scoreMomentum di breve periodo
momentum_volume_scoreComponente volume del momentum
total_scoreScore totale
growth_probabilityProbabilità di crescita (0–100)
momentum_jsonDettaglio completo del calcolo momentum
scores_jsonScore accessori (market_score, market_risk_score, short_risk_score)

scores_daily — score personalizzati per utente/pipe

Chiave primaria: (symbol, score_date, user_id, pipe_id).

Per ogni combinazione utente/pipe viene salvata una riga con gli score ricalcolati usando i pesi configurati dall'utente.

CampoDescrizione
total_scoreScore totale ricalcolato con i pesi dell'utente
valuation_scoreComponente valutazione
quality_scoreComponente qualità
risk_scoreRisk strutturale
momentum_scoreMomentum di lungo periodo (ricalcolato con pesi utente)
momentum_score_shortMomentum di breve periodo
volume_scoreScore volume
market_scoreScore mercato
market_risk_scoreRisk di mercato corrente
short_risk_scoreRisk composito breve = structural×60% + market×40%
growth_probabilityProbabilità di crescita (0–100)
model_idID del modello di scoring usato (scoring_models)
model_versionVersione del modello (per riproducibilità storica)

Come leggere i risultati

Recupero per data

GET /tickerscanner/fundamentals/scores-daily/by-user/:pipeId/:scoreDate

Restituisce tutti i simboli con il loro score personalizzato per la pipe e la data richiesta, già ordinati per total_score decrescente.

Conteggio disponibilità date

GET /tickerscanner/fundamentals/scores-daily/counts/:pipeId

Restituisce le date per cui sono disponibili dati di scoring per quella pipe. Utile per popolare un selettore di date nel frontend.


Audit e riproducibilità

Per garantire che i risultati del passato siano sempre riproducibili:

  • Ogni riga di scores_daily è collegata al model_id del modello di pesi usato
  • La tabella scoring_models conserva la versione storica dei pesi con valid_from e valid_to
  • Se l'utente cambia i propri pesi, una nuova versione del modello viene creata e le righe future useranno la nuova versione

Fase successiva

L'output di questa fase (scores_daily) è disponibile alle watchlist personalizzate degli utenti nel frontend. Parallelamente, se non ancora eseguita, può essere avviata la Fase 4: Ranking di sistema, che parte dalla stessa sorgente (daily_scores) ma produce un ranking globale indipendente dall'utente.


Avvio manuale

POST /tickerscanner/fundamentals/user-daily-scores

Body:

{
"userId": 1,
"pipeId": 0,
"targetDate": "2026-03-15"
}

Body con pipe specifica:

{
"userId": 1,
"pipeId": 2,
"targetDate": "2026-03-15"
}

Risponde subito con un jobId. Lo stato del job può essere monitorato con:

GET /tickerscanner/fundamentals/user-daily-score-jobs

Errori comuni e recovery

ErroreCausa probabileRecovery
scores_daily vuota per una dataFase 3 non eseguita o Fase 2 non ancora completataVerificare che daily_scores esista per la data; poi avviare il job
Score identici per tutti gli utentiPesi personalizzati non configuratiVerificare la configurazione in scoring_models per userId/pipeId
Job completato ma nessun simbolo scrittoNessun simbolo supera i filtri configuratiAllentare i filtri utente (es. abbassare min_total_score)
Risultati non aggiornati dopo modifica pesiVecchi dati in scores_daily non rigeneratiRieseguire con mode=force per sovrascrivere i dati esistenti
pipeId non trovataPipe non configurata per l'utenteCreare la configurazione pipe in scoring_models prima di eseguire