Passa al contenuto principale

Fase 5 — Analisi tecnica e segnali di ingresso

La Fase 5 è eseguita dal microservizio decision-engine. Legge i ticker del ranking di sistema (AST_RANKING_DAILY, Fase 4) e per ciascuno esegue un'analisi tecnica multi-timeframe, producendo livelli operativi di ingresso: entry limit, stop loss e target di prezzo.

Frequenza: su richiesta manuale o tramite scheduler, dopo la Fase 4.


Scheda operativa

VoceDettaglio
ScopoAnalisi tecnica multi-timeframe e calcolo segnali di ingresso per ogni ticker nel ranking.
Punto di partenzaAST_RANKING_DAILY (Fase 4) + dati candlestick da cachemanager.
DeliverableSnapshot Redis (TTL 12h) con livelli operativi per ticker: entry, stop loss, TP1, TP2.
Microservizi coinvoltidecision-engine, cachemanager (candles), tickerscanner (input tickers).

Parametri di pilotaggio

ParametroTipoUso
datedata (YYYY-MM-DD)Score date del ranking da elaborare. Obbligatorio.
cachebooleanSe true, riusa i risultati già in cache Redis per i ticker già processati.
maxAtrPctnumeroFiltro: salta ticker con atr_14_pct > valore (default: 8%).
requireSma50booleanFiltro: salta ticker con prezzo < SMA50. Default: false.
requireSma200booleanFiltro: salta ticker con SMA50 < SMA200 (golden cross). Default: false.
maxLevelDistanceAtrnumeroDistanza massima (in ATR) tra prezzo corrente e zona supporto. Default: adattiva per tier.
limitinteroProcessa solo i primi N ticker del ranking.
concurrencyinteroParallelismo nell'elaborazione (default: 3, max: 6).

Elaborazione

Step 0: Pre-filtro (prima dell'analisi tecnica)

Prima di chiamare il motore di analisi, ogni ticker viene validato usando i metadati già presenti in reason_json di AST_RANKING_DAILY. Questo evita chiamate inutili al cachemanager.

RegolaEffetto
atr_14_pct mancanteSkip: nessuna base per il sizing
atr_14_pct > maxAtrPct (default 8%)Skip: troppo volatile, zone inaffidabili
requireSma50=true e price_gt_sma50 = falseSkip: prezzo sotto SMA50 (contro-trend)
requireSma200=true e sma50_gt_sma200 = falseSkip: golden cross non confermato

I ticker scartati non consumano slot di concorrenza e vengono loggati ("pre-filter: X passed, Y skipped").

Tier di volatilità e parametri adattativi

Il valore atr_14_pct dal reason_json di Fase 4 viene usato per tarare automaticamente i parametri dell'analisi:

Tieratr_14_pctmaxLevelDistanceAtrvolatilityKflagAtrK
LOW< 1.5%21.01.1
NORMAL1.5% – 4%31.21.3
HIGH≥ 4%41.51.6

I parametri adattativi possono essere sovrascritti con query string esplicita.


Step 1: Costruzione zone (supporti e resistenze)

I dati candlestick vengono scaricati dal cachemanager su 4 timeframe in sequenza:

TimeframeFinestraScopo
1dayultimi 120 giorniAnalisi zone primarie
1weekultimi 365 giorniConferma struttura di lungo periodo
1hultimi 14 giorniZone recenti e dettaglio ravvicinato
1minultima sessioneConferma intraday del prezzo

Per ogni timeframe il motore individua le zone di prezzo significative:

  1. Calcolo ATR(20) sulla finestra di candele
  2. Rilevamento swing (massimi e minimi locali) con finestra swingWindow = 3
  3. Clustering per prezzo: pivot vicini entro eps = ATR × clusterMultiplier vengono raggruppati
  4. Scoring zone: ogni zona riceve un punteggio basato su:
    • reaction — ampiezza del rimbalzo futuro rispetto all'ATR
    • timeWeight — peso temporale (recente=1.0, medio=0.6, vecchio=0.3)
    • score = Σ(reaction_i × timeWeight_i)
  5. Filtri: mantenute solo le zone con touches ≥ 2, score ≥ 1, nelle ultime 60 candele

Le zone di tutti i timeframe vengono poi unite e prioritizzate (daily > hourly) in supports e resistances.


Step 2: Conferma trend (EMA)

Sul timeframe 1h (finestra 28 giorni, 800 candele), il motore verifica la struttura di trend:

  • EMA20 > EMA50 → uptrend strutturale (trendOk = true)
  • ≥ 8 delle ultime 12 candele chiudono sopra EMA20 → trend sostenuto nel recente

Step 3: Rilevamento pattern flag + breakout

Sulla stessa finestra oraria, viene analizzato il pattern tecnico:

CondizioneDescrizione
Flag OKRange ultime 20 candele < max(flagAtrK × ATR, 0.25% del prezzo). Volume compresso rispetto all'impulso precedente.
Breakout OKPrezzo supera il massimo della flag con volume ≥ media 20 periodi × volMult (1.2).
Pullback OKPrezzo ritocca il livello di breakout con volume decrescente.
Setup validotrendOk AND flagOk AND (breakoutOk OR pullbackOk)

Step 4: Calcolo livelli di ingresso

Il motore produce due tipologie di livello per ogni ticker:

Retracement (ingresso su supporto)

entryLimit  = support.low + 0.55 × support.width
stopLoss = min(support.low − 0.2 × ATR, entry − volatilityK × ATR)
takeProfit1 = prossima resistenza (se disponibile)
takeProfit2 = entry + 5 × ATR

Breakout (ingresso su rottura di resistenza)

entryLimit  = resistance.high + 0.25 × ATR
stopLoss = min(resistance.low − 0.2 × ATR, entry − volatilityK × ATR)
takeProfit1 = prossima resistenza sopra il breakout
takeProfit2 = entry + 5 × ATR

Il volatilityK è adattivo in base al tier di volatilità (1.0 / 1.2 / 1.5).


Step 5: Guardrail (controllo qualità del livello)

Prima di marcare un livello come actionable = true, vengono applicati due controlli minimi:

GuardrailCondizione minima
Stop minimoentry − stopLoss ≥ 1.0 × ATR (stop troppo stretto = rumore di mercato)
TP2 minimotakeProfit2 − entry ≥ 3.0 × ATR (risk/reward insufficiente)

Se un guardrail fallisce, il livello è marcato actionable = false con relativa motivazione.


Step 6: Retry con parametri rilassati

Se per un ticker non viene trovata una zona di supporto valida ("support not available"), il motore tenta automaticamente un secondo passaggio con parametri più permissivi:

ParametroStandardRilassato
lookbackDays120180
minTouches21
minScore10
minRecentBars60180
swingWindow32

Deliverable

I risultati vengono salvati in Redis con chiave spot-finder:0:{userId}:{date} (TTL: 12 ore).

Struttura del risultato per ticker

{
"ticker": "AAPL",
"currentPrice": 175.50,
"levels": {
"retracement": {
"entryLimit": 171.60,
"stopLoss": 168.00,
"takeProfit1": 180.50,
"takeProfit2": 189.75,
"risk": 3.60,
"actionable": true
},
"breakout": {
"entryLimit": 182.40,
"stopLoss": 170.00,
"takeProfit1": 185.20,
"takeProfit2": 194.25,
"risk": 12.40,
"actionable": false,
"reason": "stop too tight vs ATR"
}
}
}

Come interpretare i risultati

actionable: true — Condizioni strutturali favorevoli

Un livello è operabile quando:

  1. La zona di supporto (o resistenza) ha sufficiente storia di touchpoint con reazione documentata
  2. Il rapporto rischio/rendimento soddisfa entrambi i guardrail ATR
  3. Il prezzo corrente è abbastanza vicino alla zona (maxLevelDistanceAtr)

Questo non garantisce il successo dell'operazione: indica che le condizioni strutturali sono soddisfatte.

actionable: false — Perché scartare il segnale

MotivazioneInterpretazione
"stop too tight vs ATR"Il rischio assoluto è troppo basso rispetto alla volatilità del titolo. Lo stop verrebbe raggiunto per rumore normale di mercato.
"tp2 too tight vs ATR"Il potenziale guadagno non giustifica il rischio. Risk/reward insufficiente.
"no support found"Nessuna zona di supporto recente entro maxLevelDistanceAtr × ATR dal prezzo corrente. Tipico in mercati in forte momentum.

Retracement vs Breakout

RetracementBreakout
QuandoPrezzo vicino a una zona supportoPrezzo ha appena rotto una resistenza con volume
RischioMinore (entry nella zona di valore)Maggiore (entry sopra resistenza)
RewardMaggiore (più spazio fino alle resistenze)Minore (entry già in area di potenziale resistenza)
Pattern richiestotrendOk + flagOk + pullbackOktrendOk + flagOk + breakoutOk
R/R tipico1:3 – 1:51:2 – 1:3

ATR e sizing della posizione

L'ATR (Average True Range a 20 periodi) è il denominatore comune di tutti i calcoli:

  • Stop loss — mai inferiore a 1× ATR dall'entry (guardrail minimo)
  • Take profit 2 — sempre ≥ 5× ATR dall'entry
  • Risk per azione = entry − stopLoss in punti

Regola pratica: Il rischio percentuale per operazione si calcola come risk / currentPrice. Esempio: risk = 3.60, price = 175 → rischio = 2.1% per azione. Il sizing della posizione si adatta a partire da questo valore in funzione del rischio massimo del portafoglio.


Microservizi coinvolti

MicroservizioRuolo
tickerscannerFonte dati: lista ticker da AST_RANKING_DAILY via GET /fundamentals/ranking/daily
cachemanagerFonte dati: candlestick multi-timeframe via GET /candles
decision-engineOrchestrazione, analisi tecnica, calcolo livelli, persistenza Redis
schedulerAvvio automatico schedulato (opzionale)

Avvio manuale e monitoraggio

Avvio job asincrono (pipe virtuale 0 = ranking daily)

POST /decision-engine/spot-finder/0?date=2026-03-04&cache=true

Risposta immediata:

{
"ok": true,
"type": "async",
"jobId": "spot_1772616440778_rpzknl",
"stats": {
"status": "running",
"total": 87,
"processed": 0
}
}

Polling stato job

GET /decision-engine/spot-finder/jobs/spot_1772616440778_rpzknl

Risposta a completamento:

{
"ok": true,
"status": "completed",
"total": 87,
"processed": 87,
"ok": 71,
"errorCount": 16,
"cachedUsed": true,
"cachedCount": 30
}

Lettura risultati

GET /decision-engine/spot-finder/latest/0?date=2026-03-04

Restituisce lo snapshot Redis più recente per pipeId=0 e la data specificata.


Errori comuni e recovery

ErroreCausa probabileRecovery
total: 0 dopo il jobscore_date non ha dati in AST_RANKING_DAILYVerificare che la Fase 4 sia stata eseguita per quella data: GET /tickerscanner/fundamentals/ranking/daily?score_date=...
"support not available" per molti tickerMercato in forte trend senza pullback — nessuna zona di supporto vicinaNormale in momentum estremo. Aumentare maxLevelDistanceAtr oppure considerare solo i segnali di breakout.
errorCount elevatoTimeout cachemanager (dati storici non disponibili)Verificare che cachemanager sia operativo. Rilanciare con cache=true per riutilizzare i risultati già salvati.
Job bloccato su runningCrash del container durante l'elaborazioneRilanciare con cache=true: i ticker già processati vengono recuperati da Redis, quelli mancanti vengono rielaborati.