Strasmore Research
Learn am Matt ConnorBy Matt Connor · Updated 2026-08-08

Why Stocks Dey Gap Up or Down Overnight

Gap up or gap down na the distance from prior close to 9:30 open after 17.5 closed hours. See SPY gap size, widest Mondays, and stop risk.

Gap na the distance between where stock close for one trading session and where e open for the next one. Na jump for price chart wey no regular-hours trades happen between am.

Stocks dey gap up or down overnight for structural reason. Exchanges dey run 6.5-hour session, but the remaining 17.5 hours still bring earnings, news, overseas trading and thin extended-hours prints. Everything land together for the next morning open.

This page dey measure gaps; e no dey make unsupported claims about dem. E cover every SPY session for H1 2026, five household stocks alongside the index, plus one 8%-plus overnight move wey start to form before the bell.

Wetin be gap up or gap down?

Gap up: today opening price dey above yesterday regular-session close. Gap down: e dey below am. The open wey we dey talk about na the 9:30 a.m. ET open, wey the opening auction set. The auction dey gather overnight backlog of orders and clear everything for one price. Between the previous close and that auction, after-hours and premarket trading dey record real trades, but regular-session volume pass am by far. So official open na where full market weight first show, and na there dem dey measure the gap.

Price discovery no dey ever stop completely. Index futures dey trade almost round the clock. Overseas markets dey set levels while New York dey sleep. Premarket dey run from 4:00 a.m. ET. By 9:30, the auction no dey guess. E dey confirm a level wey overnight venues don already sketch.

How big normal overnight gap dey?

Every H1 2026 session for SPY, the S&P 500 ETF, split into overnight component (prior close to open) and intraday component (open to close):

QuerySPY, H1 2026: average absolute overnight gap vs average absolute intraday move
sessionsaverage absolute overnight gap pctaverage absolute intraday move pctgaps of half pct or more
1230.450.5341
The exact SQL behind every number
SELECT count() AS sessions,
       round(avg(abs(100 * (rth_open - prior_close) / prior_close)), 2) AS avg_abs_overnight_gap_pct,
       round(avg(abs(100 * (rth_close - rth_open) / rth_open)), 2) AS avg_abs_intraday_move_pct,
       countIf(abs(100 * (rth_open - prior_close) / prior_close) >= 0.5) AS gaps_of_half_pct_or_more
FROM (SELECT day, rth_open, rth_close, lagInFrame(rth_close) OVER (ORDER BY day) AS prior_close
    FROM (
        SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
               argMinIf(toFloat64(open), window_start, rth) AS rth_open,
               argMaxIf(toFloat64(close), window_start, rth) AS rth_close
        FROM (
            SELECT window_start, open, close,
                   toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
                   AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York') AS rth
            FROM global_markets.delayed_stocks_minute_aggs
            WHERE ticker = 'SPY'
              AND window_start >= '2025-12-29 04:00:00'
              AND window_start < '2026-07-01 08:00:00'
        )
        GROUP BY day
    ))
WHERE day >= '2026-01-01' AND prior_close > 0 AND isFinite(prior_close)
Run am yourself

Across 123 sessions, SPY average absolute overnight gap na 0.45%, compared with average absolute open-to-close move of 0.53%. The overnight jump wey person no fit trade nearly be the same size as the full tradeable day wey follow. Gap of half a percent or more happen 41 times, roughly one session out of three.

Stocks dey gap more on Mondays?

Monday opens get one reputation: weekend dey stretch the same market mechanics across 65 hours wey market close, instead of 17.5 hours. We fit test this folklore. We take every SPY session from January 2024 reach June 2026, arrange dem by weekday, then calculate average absolute gap and 90th percentile — the gap size wey only one out of every ten opens pass. If Monday na holiday, e push the weekend gap go Tuesday open, and we count am under Tuesday.

QuerySPY overnight gaps by weekday: every session, January 2024 through June 2026
day of di weeksessionsaverage absolute gap pctP90 absolute gap pct
Monday1190.521.11
Tuesday1310.360.73
Wednesday1270.390.92
Thursday1230.450.91
Friday1250.390.88
The exact SQL behind every number
SELECT ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'][dow] AS weekday,
       count() AS sessions,
       round(avg(abs(gap_pct)), 2) AS avg_abs_gap_pct,
       round(quantileDeterministic(0.9)(abs(gap_pct), toUInt64(toYYYYMMDD(day))), 2) AS p90_abs_gap_pct
FROM (
    SELECT day, toDayOfWeek(day) AS dow,
           100 * (rth_open - prior_close) / prior_close AS gap_pct
    FROM (
        SELECT day, rth_open, lagInFrame(rth_close) OVER (ORDER BY day) AS prior_close
        FROM (
            SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
                   argMinIf(toFloat64(open), window_start, rth) AS rth_open,
                   argMaxIf(toFloat64(close), window_start, rth) AS rth_close
            FROM (
            SELECT window_start, open, close,
                   toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
                   AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York') AS rth
                FROM global_markets.delayed_stocks_minute_aggs
                WHERE ticker = 'SPY'
                  AND window_start >= '2023-12-28 04:00:00'
                  AND window_start < '2026-07-01 08:00:00'
            )
            GROUP BY day
        )
    )
    WHERE day >= '2024-01-01' AND prior_close > 0 AND isFinite(prior_close)
)
WHERE dow <= 5
GROUP BY dow
ORDER BY dow
Run am yourself

The data still support the folklore. Monday average absolute gap across 119 Mondays na 0.52%, the widest among the five weekdays. Tuesday na 0.36%, Wednesday na 0.39%, Thursday na 0.45%, and Friday na 0.39%. The bigger gaps show the weekend effect more clearly: Monday 90th-percentile gap na 1.11%, compared with Tuesday 0.73%. The effect dey real but small. Monday open get wider distribution, but e no be different kind of market. And this data no show which direction the gap go.

The biggest gaps of H1 2026

The six biggest SPY overnight gaps for the half-year, plus wetin happen for the rest of each day:

QuerySPY six biggest overnight gaps for H1 2026: plus the same day's open-to-close move
sessionovernight gap pctrest of di day pct
April 8, 20262.6-0.08
March 3, 2026-1.650.77
March 23, 20261.47-0.41
January 20, 2026-1.46-0.57
June 23, 2026-1.42-0.02
June 15, 20261.380.37
The exact SQL behind every number
SELECT concat(monthName(day), ' ', toString(toDayOfMonth(day)), ', ', toString(toYear(day))) AS session,
       round(100 * (rth_open - prior_close) / prior_close, 2) AS overnight_gap_pct,
       round(100 * (rth_close - rth_open) / rth_open, 2) AS rest_of_day_pct
FROM (SELECT day, rth_open, rth_close, lagInFrame(rth_close) OVER (ORDER BY day) AS prior_close
    FROM (
        SELECT toDate(toTimeZone(window_start, 'America/New_York')) AS day,
               argMinIf(toFloat64(open), window_start, rth) AS rth_open,
               argMaxIf(toFloat64(close), window_start, rth) AS rth_close
        FROM (
            SELECT window_start, open, close,
                   toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
                   AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York') AS rth
            FROM global_markets.delayed_stocks_minute_aggs
            WHERE ticker = 'SPY'
              AND window_start >= '2025-12-29 04:00:00'
              AND window_start < '2026-07-01 08:00:00'
        )
        GROUP BY day
    ))
WHERE day >= '2026-01-01' AND prior_close > 0 AND isFinite(prior_close)
ORDER BY abs(overnight_gap_pct) DESC, day
LIMIT 6
Run am yourself

The biggest one happen for April 8, 2026: SPY open 2.6% away from the previous close, then e move -0.08% from open reach close. The whole repricing for that day happen before the first regular-hours trade. The practical lesson from gaps be say market fit reprice without you.

Number wey no get story na only half number. Every SPY-tagged headline wey publish between the April 7 close and the April 8 open:

QueryWetin cross the wire during SPY biggest overnight gap for H1 2026
ET publishedsourceheadline
Apr 08 03:28BenzingaDow Jones Surges Over 2% On US-Iran Ceasefire As Bullish April Seasonality Kicks
Apr 08 08:58BenzingaStock Market Today: S&P 500, Nasdaq Futures Surge As Trump Declares Ceasefire On
The exact SQL behind every number
SELECT formatDateTime(toTimeZone(published_utc, 'America/New_York'), '%b %d %H:%i') AS et_published,
       JSONExtractString(toString(publisher), 'name') AS source,
       substring(title, 1, 80) AS headline
FROM global_markets.stocks_news
WHERE published_utc >= toDateTime('2026-04-07 16:00:00', 'America/New_York')
  AND published_utc < toDateTime('2026-04-08 09:30:00', 'America/New_York')
  AND has(tickers, 'SPY')
ORDER BY published_utc
LIMIT 10
Run am yourself

Two headlines carry enter those hours wey market close. Both concern US-Iran ceasefire. Dem get timestamps Apr 08 03:28 ET and Apr 08 08:58 ET, before the bell, when market shut. The gap na the accounting entry for news wey arrive when you no fit trade.

Individual stocks dey gap pass index?

Index ETF dey hold hundreds of companies, and the different overnight surprises dey partly cancel each other. One stock alone no get that cushion. Five popular stocks beside SPY, for the same sessions:

QueryOvernight gaps by ticker, H1 2026: average absolute gap and the single biggest gap
tickersessionsaverage absolute gap pctbiggest gap pctday wey biggest gap happen
SPY1230.452.6April 8, 2026
KO1230.425.41April 28, 2026
AAPL1230.532.82May 1, 2026
MSFT1230.89-8.66January 29, 2026
NVDA1230.993.6April 8, 2026
TSLA1231.054.97April 8, 2026
The exact SQL behind every number
SELECT ticker,
       count() AS sessions,
       round(avg(abs(gap_pct)), 2) AS avg_abs_gap_pct,
       round(argMax(gap_pct, (abs(gap_pct), day)), 2) AS biggest_gap_pct,
       concat(monthName(argMax(day, (abs(gap_pct), day))), ' ', toString(toDayOfMonth(argMax(day, (abs(gap_pct), day)))), ', ', toString(toYear(argMax(day, (abs(gap_pct), day))))) AS biggest_gap_day
FROM (
    SELECT ticker, day, 100 * (rth_open - prior_close) / prior_close AS gap_pct
    FROM (
        SELECT ticker, day, rth_open,
               lagInFrame(rth_close) OVER (PARTITION BY ticker ORDER BY day) AS prior_close
        FROM (
            SELECT ticker, toDate(toTimeZone(window_start, 'America/New_York')) AS day,
                   argMinIf(toFloat64(open), window_start, rth) AS rth_open,
                   argMaxIf(toFloat64(close), window_start, rth) AS rth_close
            FROM (
                SELECT ticker, window_start, open, close,
                       toTimeZone(window_start, 'America/New_York') >= toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 09:30:00'), 'America/New_York')
                       AND toTimeZone(window_start, 'America/New_York') < toDateTime(concat(toString(toDate(toTimeZone(window_start, 'America/New_York'))), ' 16:00:00'), 'America/New_York') AS rth
                FROM global_markets.delayed_stocks_minute_aggs
                WHERE ticker IN ('SPY', 'KO', 'AAPL', 'MSFT', 'NVDA', 'TSLA')
                  AND window_start >= '2025-12-29 04:00:00'
                  AND window_start < '2026-07-01 08:00:00'
            )
            GROUP BY ticker, day
        )
    )
    WHERE day >= '2026-01-01' AND prior_close > 0 AND isFinite(prior_close)
)
GROUP BY ticker
ORDER BY indexOf(['SPY', 'KO', 'AAPL', 'MSFT', 'NVDA', 'TSLA'], ticker)
Run am yourself

Read the two columns separately. For the typical night, the ranking dey as you go expect: Tesla average 1.05% and Nvidia 0.99%, compared with SPY’s 0.45%. But Coca-Cola average 0.42%, below the index. This steady consumer mega-cap na quiet overnight instrument for most nights.

The tail column na where the cushion disappear. SPY’s biggest single gap for the half-year na 2.6% (April 8, 2026). All five individual stocks pass am: Coca-Cola 5.41%, Apple 2.82%, Nvidia 3.6%, Tesla 4.97%, and Microsoft, wey get the biggest one, -8.66% on January 29, 2026. Individual stocks no always dey noisier than the index on an average night, but their worst night dey far worse.

Wey dey watch gap form before bell

Make we rewind Microsoft January 29, 2026 gap. The previous session close at $481.72. Anything wey happen after that close happen when market don shut. By 4:00 a.m. ET, when premarket open, repricing don already happen:

QueryMSFT: how the January 29, 2026 gap take form, 30-minute premarket buckets
ET timepriceprevious closevs previous close pctpct below previous closeshares thousandscum shares millionscum pct of regular volume
04:00454481.72-5.755.751280.130.11
04:30451.32481.72-6.316.311370.260.23
05:00450.2481.72-6.546.541910.460.4
05:30449.13481.72-6.776.771110.570.5
06:00448.85481.72-6.826.821180.680.61
06:30446.2481.72-7.377.372640.950.84
07:00447.77481.72-7.057.053421.291.14
07:30449.22481.72-6.756.753051.61.41
08:00448.86481.72-6.826.8210102.612.31
08:30448.59481.72-6.886.885973.22.84
09:00439.74481.72-8.718.7116604.864.31
The exact SQL behind every number
WITH day_vol AS (
    SELECT sum(toFloat64(volume)) AS rth_vol
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'MSFT'
      AND window_start >= toDateTime('2026-01-29 09:30:00', 'America/New_York')
      AND window_start < toDateTime('2026-01-29 16:00:00', 'America/New_York')
),
prior AS (
    SELECT round(argMax(toFloat64(close), window_start), 2) AS prior_close
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'MSFT'
      AND window_start >= toDateTime('2026-01-28 09:30:00', 'America/New_York')
      AND window_start < toDateTime('2026-01-28 16:00:00', 'America/New_York')
),
buckets AS (
    SELECT toStartOfInterval(toTimeZone(window_start, 'America/New_York'), INTERVAL 30 minute) AS bucket,
           round(argMax(toFloat64(close), window_start), 2) AS price,
           sum(toFloat64(volume)) AS shares
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'MSFT'
      AND window_start >= toDateTime('2026-01-29 04:00:00', 'America/New_York')
      AND window_start < toDateTime('2026-01-29 09:30:00', 'America/New_York')
    GROUP BY bucket
)
SELECT formatDateTime(bucket, '%H:%i') AS et_time,
       price,
       (SELECT prior_close FROM prior) AS prior_close,
       round(100 * (price - (SELECT prior_close FROM prior)) / (SELECT prior_close FROM prior), 2) AS vs_prior_close_pct,
       round(abs(100 * (price - (SELECT prior_close FROM prior)) / (SELECT prior_close FROM prior)), 2) AS pct_below_prior_close,
       round(shares / 1000) AS shares_thousands,
       round(sum(shares) OVER (ORDER BY bucket) / 1000000, 2) AS cum_shares_millions,
       round(100 * sum(shares) OVER (ORDER BY bucket) / (SELECT rth_vol FROM day_vol), 2) AS cum_pct_of_regular_volume
FROM buckets
ORDER BY bucket
Run am yourself

The first premarket bucket, 04:00 ET, don already print $454, wey be 5.75% below the previous close, on 128 thousand shares. The next five hours move up and down. By the last premarket bucket (09:00 ET), price dey 8.71% below the close. The official open come land at -8.66%, almost exactly where 4.86 million overnight shares don already decide.

Look the last column: the whole premarket session carry 4.31% of the volume wey regular session go trade. Gap of this size fit get priced by small part of volume for dark market, then full market go confirm am by 9:30. Na because volume thin like this make spreads dey widest around the open.

Wetín options market charge for that night

Options dey show wetín market expect the move go be before e happen. A straddle, wey be call plus put for one strike and expiry, cost roughly wetín market think the stock fit move for any direction before expiry. Microsoft near-the-money straddles, wey dem quote for the last 15 minutes before January 28 close and wey expire two days later:

QueryMSFT straddle prices for the close before the gap: Jan 28, 2026, Jan 30 expiry
strike pricecall midput midstraddle costimplied move pct
$477.515.210.6725.875.37
$48013.811.9525.755.35
$482.512.6213.0725.695.33
$48511.4714.4225.895.37
The exact SQL behind every number
WITH prior AS (
    SELECT round(argMax(toFloat64(close), window_start), 2) AS prior_close
    FROM global_markets.delayed_stocks_minute_aggs
    WHERE ticker = 'MSFT'
      AND window_start >= toDateTime('2026-01-28 09:30:00', 'America/New_York')
      AND window_start < toDateTime('2026-01-28 16:00:00', 'America/New_York')
),
quotes AS (
    SELECT toFloat64(substring(ticker, 14, 8)) / 1000 AS strike,
           substring(ticker, 13, 1) AS cp,
           round(argMax((bid_price + ask_price) / 2, sip_timestamp), 2) AS mid
    FROM global_markets.cache_options_quotes
    WHERE ticker LIKE 'O:MSFT260130%'
      AND sip_timestamp >= toDateTime('2026-01-28 15:45:00', 'America/New_York')
      AND sip_timestamp < toDateTime('2026-01-28 16:00:00', 'America/New_York')
      AND bid_price > 0
      AND ask_price > 0
    GROUP BY ticker
)
SELECT concat('$', toString(strike)) AS strike_price,
       maxIf(mid, cp = 'C') AS call_mid,
       maxIf(mid, cp = 'P') AS put_mid,
       round(maxIf(mid, cp = 'C') + maxIf(mid, cp = 'P'), 2) AS straddle_cost,
       round(100 * (maxIf(mid, cp = 'C') + maxIf(mid, cp = 'P')) / (SELECT prior_close FROM prior), 2) AS implied_move_pct
FROM quotes
WHERE abs(strike - (SELECT prior_close FROM prior)) <= 5
GROUP BY strike
HAVING countIf(cp = 'C') > 0 AND countIf(cp = 'P') > 0
ORDER BY strike
Run am yourself

The strike wey near the $481.72 close, $482.5, close at $25.69 for the pair. Na 5.33% of the share price be that, and na the move market price for two full sessions, no be one night. The overnight gap alone come to -8.66%. Options market get one number, but the night pass am. The neighbouring strikes agree too (5.37% at $477.5, 5.37% at $485). So na consensus be this, no be one rogue quote.

Two mechanics dey follow for anybody wey hold options through a gap. Option no fit reprice while market dey shut. Time still dey work against long premium, and the whole move go show for the opening print. Once the event don happen, the uncertainty comot from the price too. Implied volatility dey collapse the morning after a release. Na why even if person call the direction correctly, long option still fit lose money. Days to expiry dey decide how sharply both things go affect am.

Types of gaps: the chart-pattern vocabulary

Traders dey label gaps based on where dem dey inside one longer move. The names na description, and dem dey apply am after the event. None of dem na forecast:

  • Common (area) gap, na small gap wey dey inside normal range, with no special news. Most SPY gaps wey dey below half percent na this type.
  • Breakaway gap, na when price jump comot from range or pass one level wey don hold for long time, usually with heavy volume.
  • Runaway (continuation) gap, na gap wey show for middle of trend, for the same direction wey the stock don already dey move.
  • Exhaustion gap, na gap wey move for the trend direction but show for the end of the run, after that price turn. On that day, e look exactly like runaway gap. Na later data go show the difference.

Na the last pair be the honest catch: the label depend on wetin happen next, so nobody fit name am in real time.

Wetin gaps mean for your orders

Three consequences dey follow from the fact say no regular-hours trading dey happen inside the gap:

  • Stop orders no dey stop the loss for the stop price. Stop go turn market order once the stock trade for or pass the trigger. If stock close for $50 and open for $44, $48 stop go trigger at the open and fill near $44, because the gap jump pass am completely. Stop guarantee say the order go try execute, no be the level; stop-limit order fit cap the price wey you accept, but e fit no fill at all.
  • Halts, no be gaps, na the market brake. Limit up-limit down (LULD) bands stop stock from printing more than a set percentage away from its recent average price—5% or 10% for most names, wider for low-priced ones, and twice as wide at the open and close. If the move persist outside the band, e trigger five-minute pause. Market-wide circuit breakers halt everything if the S&P 500 fall 7% (Level 1) or 13% (Level 2) from the prior close, and dem shut trading for the day at 20% (Level 3). None of these things prevent the gap; dem control wetin happen when trading resume.
  • "Gap fill" na description, no be timetable. Traders talk say gap “fills” when price return to the prior close. Nothing force am to happen, for any timeframe. SPY biggest gap day for the half move just -0.08% after the open: no fill, no fade, na just new level.

Overnight and intraday na statistically different markets. Na why how dem dey measure monthly returns fit change the answer, depending on whether dem count the overnight jumps.

FAQ

Stock dey gap up or down overnight because of wetin?

Market dey close for 17.5 hours out of every 24 hours, but information no dey stop. Earnings fit come out after market close. News fit break before market open. Overseas markets fit trade throughout the night. Opening auction dey match all the orders wey pile up, using one price. The difference between that price and the previous close na the gap.

How often overnight gaps dey happen?

Dem dey happen everywhere. For H1 2026, SPY average absolute overnight gap na 0.45%, and 41 out of 123 sessions open at least half a percent away from the previous close. Individual stocks fit move more. Tesla average 1.05%.

Stocks dey gap more on Mondays?

Small difference dey, yes. From January 2024 reach June 2026, SPY average absolute Monday gap na 0.52%, the widest among weekdays, compared with 0.36% on Tuesday. Weekend add more hours wey market close, but e no determine the direction.

Gaps always dey fill?

No. “Gap always dey fill” na trading folklore. Some gaps fill within hours, while others never return to the previous close. Treat any gap-fill statistic as description of past sessions, no be rule for the next session.

Wetin go happen to my stop-loss if stock gap down?

Stop go trigger when market open, and e go fill at any price wey market dey offer. That price fit dey far below the stop price because the gap get no trades inside am to catch the order.


Every number above come from stored query. Open the SQL under any panel, or split any ticker’s month into overnight and intraday moves for Strasmore terminal.

#gaps#market structure#opening auction#overnight moves