Strasmore Research
Deep Dives · Matt ConnorBy Matt Connor · · Updated 2026-08-08

I gap azionari vengono sempre colmati? I dati

I gap azionari non si colmano sempre entro un orizzonte fisso. Scopri i tassi di fill nella stessa sessione e dopo 5, 20 e 60 sessioni, con il SQL.

I gap azionari vengono sempre colmati? Non entro un orizzonte abbastanza breve da consentire un’operazione, e l’affermazione resiste soprattutto quando nessuno ne specifica uno. Un gap è la distanza tra l’apertura odierna e la chiusura della sessione regolare di ieri; un fill si verifica quando il prezzo torna a scambiare attraverso quella chiusura precedente. L’intera tesi dipende quindi da quanto a lungo il lettore è disposto ad aspettare.

Cosa si considera un gap e cosa si considera un fill

Un gap si misura confrontando l’apertura con la chiusura precedente. La sessione di ieri si è conclusa a un certo prezzo, quella di oggi è iniziata a un altro, e la differenza è il gap. Non è la distanza dal massimo o dal minimo intraday di ieri. Quello è un obiettivo diverso e molto più facile da raggiungere. Confondere i due concetti è il modo in cui un “gap” finisce silenziosamente per chiudersi entro l’ora di pranzo in una giornata ordinaria. Gap piccoli compaiono in quasi ogni sessione: gli scambi in altri fusi orari, le modifiche agli indici, le notizie su singoli titoli e gli aggiustamenti ex-dividend modificano il fair value mentre il mercato USA è chiuso. Perché le azioni aprono in gap overnight spiega da dove nasce questa rivalutazione overnight.

Un fill è il primo momento in cui il titolo torna a scambiare attraverso il prezzo di chiusura precedente. Questa definizione è incompleta se non si indica una scadenza. Su un orizzonte illimitato, un titolo liquido attraversa prima o poi quasi ogni livello indicato dal lettore. Questo rende l’affermazione “i gap vengono sempre colmati” non falsificabile, anziché vera. Ogni numero riportato di seguito ha un orizzonte esplicito.

Un unico campione viene utilizzato in tutta la pagina: otto titoli large-cap statunitensi, giornate di gap da gennaio 2021 a febbraio 2026, fill verificati rispetto ai massimi e ai minimi a un minuto della sessione regolare. I gap inferiori allo 0,25% sono esclusi perché soggetti ad arrotondamento.

I gap azionari vengono sempre colmati nella stessa giornata?

Partiamo dall’ampiezza. Raggruppiamo ogni gap in base alla sua dimensione e verifichiamo se il prezzo di chiusura precedente è stato nuovamente toccato prima della fine della stessa sessione.

QueryTasso di chiusura dei gap nella stessa sessione per dimensione del gap, otto large cap, 2021–2026
L'esatto SQL dietro ogni numero
WITH sessions AS
(
    SELECT
        ticker,
        toDate(toTimeZone(window_start, 'America/New_York')) AS d,
        argMin(toFloat64(open), window_start)                AS session_open,
        argMax(toFloat64(close), window_start)               AS session_close,
        toFloat64(max(high))                                 AS session_high,
        toFloat64(min(low))                                  AS session_low
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'AMZN', 'JPM', 'KO', 'WMT', 'XOM')
      AND window_start >= '2021-01-01'
      AND window_start <  '2026-07-01'
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) >= 570
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) < 960
    GROUP BY ticker, d
),
gapped AS
(
    SELECT
        d,
        session_open,
        session_high,
        session_low,
        lagInFrame(session_close) OVER (PARTITION BY ticker ORDER BY d ASC
            ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS prior_close
    FROM sessions
),
measured AS
(
    SELECT
        abs(100 * (session_open / prior_close - 1)) AS gap_pct,
        toUInt8(if(session_open > prior_close,
                   session_low  <= prior_close,
                   session_high >= prior_close))    AS filled_same_session
    FROM gapped
    WHERE prior_close > 0
      AND d <= toDate('2026-02-28')
      AND abs(100 * (session_open / prior_close - 1)) >= 0.25
)
SELECT
    multiIf(gap_pct < 0.5, '0.25 to 0.5%',
            gap_pct < 1,   '0.5 to 1%',
            gap_pct < 2,   '1 to 2%',
            gap_pct < 4,   '2 to 4%',
                           '4% or more')         AS gap_bucket,
    count()                                      AS gap_days,
    round(100 * avg(filled_same_session), 1)     AS same_session_fill_pct
FROM measured
GROUP BY gap_bucket
ORDER BY min(gap_pct) ASC
Run this yourself

I gap più piccoli del campione, compresi tra lo 0,25% e lo 0,5%, si sono chiusi nella stessa sessione nel 74.6% dei casi, su 2381 occorrenze. I gap pari o superiori al 4% si sono chiusi nella stessa sessione nel 14.8% dei casi. La pendenza del grafico contiene gran parte della lezione: più piccolo è il gap, più spesso il titolo torna ad attraversarlo durante la giornata. In altri termini, i gap piccoli sono rumore e il rumore tende a invertirsi.

Quanto tempo impiega un gap a essere colmato?

Estendendo la scadenza, il tasso di fill può soltanto aumentare. Una finestra più lunga aggiunge fill e non ne elimina mai. La domanda è quanta parte del totale arrivi così tardi da non essere utile.

QueryQuota di gap ≥1% chiusi in base al tempo di attesa
L'esatto SQL dietro ogni numero
WITH sessions AS
(
    SELECT
        ticker,
        toDate(toTimeZone(window_start, 'America/New_York')) AS d,
        argMin(toFloat64(open), window_start)                AS session_open,
        argMax(toFloat64(close), window_start)               AS session_close,
        toFloat64(max(high))                                 AS session_high,
        toFloat64(min(low))                                  AS session_low
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'AMZN', 'JPM', 'KO', 'WMT', 'XOM')
      AND window_start >= '2021-01-01'
      AND window_start <  '2026-07-01'
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) >= 570
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) < 960
    GROUP BY ticker, d
),
paths AS
(
    SELECT
        d,
        session_open,
        session_high,
        session_low,
        lagInFrame(session_close) OVER (PARTITION BY ticker ORDER BY d ASC
            ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)                                                          AS prior_close,
        min(session_low)  OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 4 FOLLOWING)   AS low_5,
        max(session_high) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 4 FOLLOWING)   AS high_5,
        min(session_low)  OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 19 FOLLOWING)  AS low_20,
        max(session_high) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 19 FOLLOWING)  AS high_20,
        min(session_low)  OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 59 FOLLOWING)  AS low_60,
        max(session_high) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 59 FOLLOWING)  AS high_60
    FROM sessions
),
gaps AS
(
    SELECT
        session_open > prior_close AS gap_up,
        prior_close,
        session_low,
        session_high,
        low_5,
        high_5,
        low_20,
        high_20,
        low_60,
        high_60
    FROM paths
    WHERE prior_close > 0
      AND d <= toDate('2026-02-28')
      AND abs(100 * (session_open / prior_close - 1)) >= 1
),
flags AS
(
    SELECT arrayJoin([
        (1, '1 session',   toUInt8(if(gap_up, session_low <= prior_close, session_high >= prior_close))),
        (2, '5 sessions',  toUInt8(if(gap_up, low_5  <= prior_close, high_5  >= prior_close))),
        (3, '20 sessions', toUInt8(if(gap_up, low_20 <= prior_close, high_20 >= prior_close))),
        (4, '60 sessions', toUInt8(if(gap_up, low_60 <= prior_close, high_60 >= prior_close)))
    ]) AS f
    FROM gaps
)
SELECT
    tupleElement(f, 2)                        AS horizon,
    count()                                   AS gaps_measured,
    round(100 * avg(tupleElement(f, 3)), 1)   AS filled_pct
FROM flags
GROUP BY horizon
ORDER BY min(tupleElement(f, 1)) ASC
Run this yourself

Su 2191 gap pari o superiori all’1%, 34% sono stati colmati nella stessa sessione e 88.7% risultavano colmati entro 60 sessions. È il secondo dato quello citato di solito, lasciando però implicito l’orizzonte. Sessanta sessioni equivalgono più o meno a tre mesi di trading: un periodo lungo per una posizione basata su una dislocazione di un solo giorno. Un gap che viene colmato il giorno 47, dopo che il titolo si è mosso prima in modo significativo nella direzione opposta, conta comunque come colmato in quella statistica.

Gap di rumore e gap informativi sono due popolazioni diverse

Un gap in una giornata tranquilla, con volumi ordinari, è un piccolo aggiustamento dei prezzi. Un gap successivo a una notizia sugli utili o a un’offerta di acquisizione incorpora un cambiamento nel valore della società. In questo caso non esiste più un vecchio prezzo verso cui tornare. Il volume distingue abbastanza bene i due casi: quando l’intero mercato vuole scambiare una rivalutazione, si osservano molti più prints rispetto al turnover normale.

QueryTasso di chiusura dei gap in base all’intensità dei volumi del giorno del gap
L'esatto SQL dietro ogni numero
WITH sessions AS
(
    SELECT
        ticker,
        toDate(toTimeZone(window_start, 'America/New_York')) AS d,
        argMin(toFloat64(open), window_start)                AS session_open,
        argMax(toFloat64(close), window_start)               AS session_close,
        toFloat64(max(high))                                 AS session_high,
        toFloat64(min(low))                                  AS session_low,
        sum(toFloat64(volume))                               AS session_volume
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'AMZN', 'JPM', 'KO', 'WMT', 'XOM')
      AND window_start >= '2021-01-01'
      AND window_start <  '2026-07-01'
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) >= 570
      AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
           + toMinute(toTimeZone(window_start, 'America/New_York'))) < 960
    GROUP BY ticker, d
),
paths AS
(
    SELECT
        d,
        session_open,
        session_high,
        session_low,
        session_volume,
        lagInFrame(session_close) OVER (PARTITION BY ticker ORDER BY d ASC
            ROWS BETWEEN 1 PRECEDING AND CURRENT ROW)                                                         AS prior_close,
        avg(session_volume) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN 21 PRECEDING AND 2 PRECEDING) AS normal_volume,
        min(session_low)  OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 19 FOLLOWING) AS low_20,
        max(session_high) OVER (PARTITION BY ticker ORDER BY d ASC ROWS BETWEEN CURRENT ROW AND 19 FOLLOWING) AS high_20
    FROM sessions
),
measured AS
(
    SELECT
        session_volume / normal_volume AS volume_ratio,
        toUInt8(if(session_open > prior_close, session_low <= prior_close, session_high >= prior_close)) AS filled_same_session,
        toUInt8(if(session_open > prior_close, low_20 <= prior_close, high_20 >= prior_close))           AS filled_20_sessions
    FROM paths
    WHERE prior_close > 0
      AND normal_volume > 0
      AND d >= toDate('2021-03-01')
      AND d <= toDate('2026-02-28')
      AND abs(100 * (session_open / prior_close - 1)) >= 1
)
SELECT
    multiIf(volume_ratio < 1.5, 'Under 1.5x normal',
            volume_ratio < 3,   '1.5x to 3x normal',
                                '3x or more')        AS volume_regime,
    count()                                          AS gap_days,
    round(100 * avg(filled_same_session), 1)         AS same_session_fill_pct,
    round(100 * avg(filled_20_sessions), 1)          AS within_20_sessions_fill_pct
FROM measured
WHERE isFinite(volume_ratio)
GROUP BY volume_regime
ORDER BY min(volume_ratio) ASC
Run this yourself

I gap pari o superiori all’1% con volumi inferiori a 1,5 volte il turnover normale del titolo si sono chiusi nella stessa sessione nel 35.9% dei casi. Gap della stessa dimensione con volumi pari o superiori a tre volte il normale si sono chiusi nella stessa sessione nel 15.3% dei casi e nel 45.8% entro 20 sessioni, su 59 casi complessivi. Il gruppo ad alto volume comprende i gap sugli utili e quelli legati a operazioni societarie. Fare la media dei due gruppi in un unico numero non descrive correttamente nessuno dei due.

Perché i primi minuti della sessione distorcono le statistiche sui gap

Un fill registrato alle 9:31 è un dato fragile. Il prezzo di apertura nasce da un’asta, cioè da un unico incrocio aggregato che stabilisce un prezzo per tutti gli ordini rimasti in coda durante la notte. La nostra spiegazione dell’asta di apertura illustra il funzionamento del meccanismo. Nei minuti successivi a quell’incrocio, gli spread quotati sono ai livelli più ampi della giornata e un singolo print di piccole dimensioni può determinare un massimo o un minimo al quale non è mai stato scambiato un volume significativo. Gli spread si ampliano all’apertura spiega perché la liquidità quotata sia così ridotta in quel momento.

Il grafico seguente mostra l’andamento rilevato sul tape del paniere: l’ampiezza media high-low a un minuto, in basis point (un basis point equivale a un centesimo di punto percentuale), per intervalli di quindici minuti, fino al 2025.

QueryRange medio a un minuto e volumi per ora del giorno, 2025
L'esatto SQL dietro ogni numero
SELECT
    formatDateTime(toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 15 MINUTE), '%H:%i') AS et_time,
    round(10000 * avg(toFloat64(high) / toFloat64(low) - 1), 1) AS avg_range_bps,
    round(avg(toFloat64(volume)) / 1000, 1)                     AS avg_volume_k
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('AAPL', 'MSFT', 'NVDA', 'AMZN', 'JPM', 'KO', 'WMT', 'XOM')
  AND window_start >= '2025-01-01'
  AND window_start <  '2026-01-01'
  AND toFloat64(low) > 0
  AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
       + toMinute(toTimeZone(window_start, 'America/New_York'))) >= 570
  AND (toHour(toTimeZone(window_start, 'America/New_York')) * 60
       + toMinute(toTimeZone(window_start, 'America/New_York'))) < 960
GROUP BY et_time
ORDER BY et_time ASC
Run this yourself

Il primo intervallo presenta in media 24.4 bps di escursione al minuto, contro 6.9 bps nell’intervallo 12:30, su 303.9 migliaia di azioni al minuto contro 69.6 migliaia. Un fill registrato nel primo intervallo si basa sui prezzi meno affidabili della giornata. I dati sui fill nella stessa sessione riportati sopra includono quei minuti, il che li rende leggermente più elevati. La stessa cautela vale per ogni statistica sui fill intraday, compresa questa.

Cosa verificare prima di considerare un gap come un’operazione

  1. L’orizzonte. Un tasso di fill senza una scadenza non è una statistica.
  2. La popolazione. Occorre sapere se i gap legati alle notizie sono stati separati da quelli delle giornate tranquille e come è stata tracciata la distinzione.
  3. La misurazione. Occorre sapere se i fill sono stati verificati rispetto a escursioni realmente scambiate e se sono stati inclusi i primi minuti della sessione.
  4. I sopravvissuti. Occorre sapere se il campione include soltanto titoli ancora scambiati oggi, eliminando così silenziosamente i gap che non sono mai stati colmati.

La formulazione corretta è più circoscritta dello slogan. I gap piccoli, con volumi ordinari, spesso rientrano rapidamente. I gap ampi, accompagnati da volumi elevati, riflettono una rivalutazione e rimangono spesso aperti per mesi. Per una vista aggiornata sui titoli che stanno aprendo in gap, la pagina titoli con i maggiori movimenti della settimana monitora la settimana corrente. La pagina come i mercati recuperano dai crolli applica la stessa disciplina sull’orizzonte ai drawdown degli indici.

FAQ

I gap azionari vengono sempre colmati?

No. Nel campione analizzato, 88.7% dei gap pari o superiori all’1% è tornato a scambiare attraverso la chiusura precedente entro 60 sessions. Questo lascia una quota effettiva di gap non colmati dopo circa tre mesi di trading. La versione con “sempre” funziona soltanto se non si impone alcun limite temporale; a quel punto, però, non è più verificabile.

Quanto tempo serve per colmare un gap?

Dipende dal gap. In questo campione, 34% dei gap pari o superiori all’1% è stato colmato nella stessa sessione. I fill rimanenti si distribuiscono nelle settimane e nei mesi successivi. I gap piccoli si concentrano nella fascia dei fill intraday, mentre quelli associati a volumi elevati sono i più lenti.

Qual è la differenza tra un common gap e un breakaway gap?

La terminologia dei grafici distingue i gap in base al contesto. Un common gap si apre in una giornata ordinaria, con volumi ordinari e senza notizie specifiche. Un breakaway gap si apre invece con volumi elevati e nuove informazioni, spesso al di fuori di un range di prezzo in cui il titolo si era mosso per un certo periodo. La distinzione basata sui volumi mostrata nel pannello precedente è una versione misurabile dello stesso concetto.

Perché le statistiche sui gap fill variano così tanto tra le fonti?

Quattro scelte possono modificare sensibilmente il dato: l’orizzonte del fill, il paniere di titoli, il periodo analizzato e il fatto che il gap sia misurato rispetto alla chiusura precedente oppure al massimo e al minimo precedenti. Un tasso di fill citato senza uno di questi quattro elementi non può essere confrontato con un altro.


Come sono stati misurati questi numeri

Le sessioni sono costruite utilizzando barre a un minuto all’interno degli orari di trading regolare, secondo l’ora di New York. Il prezzo di apertura è l’open della prima barra della sessione regolare, la chiusura è il close dell’ultima barra, mentre il massimo e il minimo della giornata sono gli estremi di tali barre. Ogni gap è misurato rispetto alla chiusura della sessione precedente dello stesso ticker.

Gli orizzonti di 5, 20 e 60 sessioni includono la giornata del gap. Le giornate di gap terminano alla fine di febbraio 2026, mentre il tape prosegue fino a giugno 2026. Ogni gap nel pannello degli orizzonti dispone quindi di almeno sessanta sessioni successive e nessuno viene classificato come non colmato per mancanza di dati.

Nel terzo pannello, il volume normale è il volume medio della sessione regolare nelle 20 sessioni che terminano due giorni prima del gap. In questo modo, la giornata del gap e quella precedente restano escluse dal proprio benchmark.

Il paniere comprende otto titoli large-cap liquidi. I titoli meno liquidi aprono in gap più spesso e presentano dinamiche di fill diverse. Questi tassi non possono quindi essere estesi agli small cap senza ripetere lo stesso test su di essi.

Ogni pannello qui riportato è accompagnato dall’SQL esatto sottostante. Per eseguire lo stesso test su un ticker che segui, formula la domanda in inglese semplice sul terminale Strasmore.

#gaps#gap fill#opening auction#overnight returns#technical analysis