Strasmore Research
Learn Matt ConnorBy Matt Connor

Are 0DTE Options High Risk? What the Greeks Say

Are 0DTE options high risk? Gamma and theta per dollar of premium for a same-day SPY contract versus a month-out one, and how far SPY must move to double it.

Are 0DTE options high risk? Mechanically, yes: a same-day contract carries the gamma and theta of a month-long option compressed into one session, and its premium can double or go to zero on a move SPY makes in an ordinary week. The instrument, though, is rarely what empties a retail account. Position size is. The numbers below come from real SPY contracts traded in June 2026.

What makes a 0DTE option riskier than a longer-dated one?

A 0DTE option is a contract on its final trading day (DTE is days to expiry; the primer on what 0DTE options are covers the basics). Three things change when a contract has hours rather than weeks left.

There is no time to recover. A 30-day contract can absorb a move against it and wait; a same-day contract cannot, and every dollar of an at-the-money 0DTE premium is time value that reaches zero at the close.

Gamma is concentrated. Delta is an option's sensitivity to a $1 move in the underlying; gamma is the rate at which delta changes as the underlying moves. Close to expiry, gamma piles up at the strike, and a small SPY move can swing a contract's delta from near 0 to near 1 (option gamma explained has the mechanics).

Theta is enormous relative to the premium. Theta is the value an option loses per day from time alone; on a same-day contract it is the whole premium by definition (option theta covers the curve over a contract's life).

The first panel prices this. It takes every at-the-money SPY call (strike within a quarter of a percent of SPY's close) on every June 2026 session, groups the contracts by days to expiry, and averages what they cost and how far SPY had to move to earn the premium back.

QueryWhat an at-the-money SPY call cost, by days to expiry (June 2026)
dte_bucketavg_premiumbreakeven_move_pctdouble_move_pctdelta_move_pct
1 day (next session)3.020.410.810.79
2-5 days4.770.641.291.25
6-10 days6.70.91.81.73
11-20 days9.021.222.432.31
21-45 days14.271.923.843.56
The exact SQL behind every number
WITH atm_calls AS
(
    SELECT
        days_to_expiry              AS dte,
        toFloat64(option_close)     AS premium,
        toFloat64(underlying_close) AS spot,
        toFloat64(delta)            AS dlt
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND lower(toString(option_type)) IN ('call', 'c')
      AND date >= toDate('2026-06-01')
      AND date <  toDate('2026-07-01')
      AND days_to_expiry > 0
      AND days_to_expiry <= 45
      AND iv_converged = 1
      AND volume > 0
      AND option_close > 0
      AND toFloat64(delta) BETWEEN 0.2 AND 0.8
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.0025
)
SELECT
    multiIf(dte <= 1,  '1 day (next session)',
            dte <= 5,  '2-5 days',
            dte <= 10, '6-10 days',
            dte <= 20, '11-20 days',
                       '21-45 days')                   AS dte_bucket,
    round(avg(premium), 2)                             AS avg_premium,
    round(avg(premium / spot) * 100, 2)                AS breakeven_move_pct,
    round(avg(premium / spot) * 200, 2)                AS double_move_pct,
    round(avg(premium / (dlt * spot)) * 100, 2)        AS delta_move_pct
FROM atm_calls
GROUP BY dte_bucket
ORDER BY min(dte)
Run this yourself

A contract with one calendar day left cost $3.02 on average, 0.41% of SPY's price, against $14.27 (1.92%) for a contract 21 to 45 days out. The breakeven_move_pct column is how far above the strike SPY has to close at expiry for the call to be worth what it cost, and double_move_pct is twice that. The delta_move_pct column is the first-order version for today: the SPY move at which the contract's current delta alone earns or loses the whole premium. For the next-day contract that is 0.79%; for the month-out contract, 3.56%. Hold both against the daily SPY moves in the expiry-day panel further down.

How far does SPY have to move to double or zero a 0DTE premium?

Per dollar of premium is the fair comparison, since a cheap contract with large greeks and an expensive one with small greeks can carry the same dollar exposure. The next panel divides gamma and theta by the premium for the same June 2026 contracts and expresses each rung as a multiple of the 21-to-45-day rung.

QueryGamma and theta per dollar of premium, by days to expiry (June 2026)
dte_bucketgamma_per_premium_dollartheta_pct_per_daygamma_ratio_vs_month_outtheta_ratio_vs_month_out
1 day (next session)0.029551.831.828.7
2-5 days0.009317109.4
6-10 days0.00476.95.13.9
11-20 days0.00233.92.52.2
21-45 days0.00091.811
The exact SQL behind every number
WITH atm_calls AS
(
    SELECT
        days_to_expiry          AS dte,
        toFloat64(option_close) AS premium,
        toFloat64(gamma)        AS gma,
        toFloat64(theta)        AS tht
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND lower(toString(option_type)) IN ('call', 'c')
      AND date >= toDate('2026-06-01')
      AND date <  toDate('2026-07-01')
      AND days_to_expiry > 0
      AND days_to_expiry <= 45
      AND iv_converged = 1
      AND volume > 0
      AND option_close > 0
      AND toFloat64(delta) BETWEEN 0.2 AND 0.8
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.0025
),
ladder AS
(
    SELECT
        multiIf(dte <= 1,  '1 day (next session)',
                dte <= 5,  '2-5 days',
                dte <= 10, '6-10 days',
                dte <= 20, '11-20 days',
                           '21-45 days')       AS dte_bucket,
        min(dte)                               AS dte_lo,
        avg(gma / premium)                     AS gamma_raw,
        avg(abs(tht) / premium) * 100          AS theta_raw
    FROM atm_calls
    GROUP BY dte_bucket
)
SELECT
    dte_bucket,
    round(gamma_raw, 4)                                                                   AS gamma_per_premium_dollar,
    round(theta_raw, 1)                                                                   AS theta_pct_per_day,
    round(gamma_raw / (SELECT gamma_raw FROM ladder WHERE dte_bucket = '21-45 days'), 1)  AS gamma_ratio_vs_month_out,
    round(theta_raw / (SELECT theta_raw FROM ladder WHERE dte_bucket = '21-45 days'), 1)  AS theta_ratio_vs_month_out
FROM ladder
ORDER BY dte_lo
Run this yourself

Per dollar of premium, the next-day contract carried 0.0295 of gamma against 0.0009 for the month-out contract, a ratio of 31.8 to 1. Theta ran 51.8% of the premium per day on the next-day contract and 1.8% on the month-out one, 28.7 to 1.

The doubling and zeroing arithmetic at the close comes from the payoff alone. A call is worth SPY's close minus the strike, or nothing. Bought at the money, it is worth double when SPY closes two premiums above the strike (0.81% of SPY's price for the next-day contract) and worth zero when SPY closes at or below the strike. Flat is enough. The month-out contract needs a 3.84% finish above its strike to double at expiry, with weeks for SPY to get there and the option to sell along the way. Same payoff, different clock; the greeks are what the clock does to the price in between.

Why gamma concentrates at the strike

Gamma peaks where the underlying sits and falls away on either side, and the closer the expiry, the sharper the peak. The panel expresses gamma as the change in delta from a 1% SPY move (gamma times SPY's price, divided by 100), averaged per half-percent step from the money across June 2026. It uses out-of-the-money calls above the spot price and out-of-the-money puts below it, which carry the same gamma at the same strike.

QueryDelta change from a 1% SPY move, by distance from the strike (June 2026)
moneynessnext_day_delta_shiftmonth_out_delta_shift
-2%0.0780.071
-1.5%0.1310.077
-1%0.2240.081
-0.5%0.3720.087
0%0.4970.092
+0.5%0.3880.097
+1%0.2110.098
+1.5%0.0940.097
+2%0.0420.095
The exact SQL behind every number
SELECT
    concat(if(half_pct > 0, '+', ''), toString(half_pct / 2), '%')  AS moneyness,
    round(avgIf(gma * spot / 100, dte <= 1), 3)                      AS next_day_delta_shift,
    round(avgIf(gma * spot / 100, dte BETWEEN 21 AND 45), 3)         AS month_out_delta_shift
FROM
(
    SELECT
        toInt32(round((toFloat64(strike_price) / toFloat64(underlying_close) - 1) * 200)) AS half_pct,
        days_to_expiry                                                                     AS dte,
        toFloat64(gamma)                                                                   AS gma,
        toFloat64(underlying_close)                                                        AS spot
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND date >= toDate('2026-06-01')
      AND date <  toDate('2026-07-01')
      AND ((days_to_expiry > 0 AND days_to_expiry <= 1) OR days_to_expiry BETWEEN 21 AND 45)
      AND iv_converged = 1
      AND volume > 0
      AND option_close > 0
      AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) < 0.0225
      AND ((lower(toString(option_type)) IN ('call', 'c') AND strike_price >= underlying_close)
        OR (lower(toString(option_type)) IN ('put', 'p')  AND strike_price <  underlying_close))
)
GROUP BY half_pct
HAVING countIf(dte <= 1) > 0 AND countIf(dte BETWEEN 21 AND 45) > 0
ORDER BY half_pct
Run this yourself

At the strike, a 1% move shifted the next-day contract's delta by 0.497 and the month-out contract's by 0.092. Two percent above the money the figures were 0.042 and 0.095. One line is a spike, the other a plateau. A same-day contract near the strike has a directional exposure that is rewritten with every few dollars of SPY movement, the concentration behind pin risk at expiration.

What a month of same-day SPY calls actually did

The greeks describe the price locally. For whole outcomes, the next panel follows one contract per expiry: for each June 2026 SPY expiration it takes the call whose strike sat closest to SPY's close on the session before expiry, records that evening's closing price (the price on the screen at the next open, before any gap), then values the contract at the expiry close: SPY's closing price minus the strike, or zero if SPY finished at or below the strike, which is all a call is worth once the clock runs out.

QueryAn at-the-money SPY call: prior close versus value at the expiry close, every June 2026 expiry
21 rows (showing 20)
expiry_dateexpiry_labelpremium_prior_closevalue_at_expirypct_of_premium_leftspy_move_pct
2026-06-01Mon Jun 12.50.58230.12
2026-06-02Tue Jun 22.712.63970.4
2026-06-03Wed Jun 31.6200-1.2
2026-06-04Thu Jun 43.993.56890.53
2026-06-05Fri Jun 52.9800-2.54
2026-06-08Mon Jun 83.953.72940.46
2026-06-09Tue Jun 92.7500-0.41
2026-06-10Wed Jun 103.6100-1.74
2026-06-11Thu Jun 115.4416.483032.3
2026-06-12Fri Jun 123.53.45990.4
2026-06-15Mon Jun 153.4811.913421.54
2026-06-16Tue Jun 162.2200-0.42
2026-06-17Wed Jun 172.2300-0.69
2026-06-18Thu Jun 180.890.941060.18
2026-06-22Mon Jun 223.1500-0.44
2026-06-23Tue Jun 232.7800-1.16
2026-06-24Wed Jun 242.752.2800.3
2026-06-25Thu Jun 252.6800-0.61
2026-06-26Fri Jun 263.6100-0.2
2026-06-29Mon Jun 293.869.762531.31
The exact SQL behind every number
WITH spy_by_day AS
(
    SELECT
        toDate(date)                             AS d,
        medianExact(toFloat64(underlying_close)) AS spot
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND date >= toDate('2026-06-01')
      AND date <  toDate('2026-07-01')
      AND underlying_close > 0
    GROUP BY d
),
last_sessions AS
(
    SELECT
        toDate(expiration_date) AS exp_date,
        max(toDate(date))       AS prior_session
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND expiration_date >= toDate('2026-06-01')
      AND expiration_date <  toDate('2026-07-01')
      AND date >= toDate('2026-05-22')
      AND date <  expiration_date
      AND volume > 0
    GROUP BY exp_date
),
atm AS
(
    SELECT
        toDate(g.expiration_date)                                                                                AS exp_date,
        argMin(toFloat64(g.strike_price), abs(toFloat64(g.strike_price) - toFloat64(g.underlying_close)))        AS strike,
        argMin(toFloat64(g.option_close), abs(toFloat64(g.strike_price) - toFloat64(g.underlying_close)))        AS premium_before,
        argMin(toFloat64(g.underlying_close), abs(toFloat64(g.strike_price) - toFloat64(g.underlying_close)))    AS spy_before
    FROM global_markets.options_greeks AS g
    INNER JOIN last_sessions AS ls
        ON ls.exp_date = toDate(g.expiration_date) AND ls.prior_session = toDate(g.date)
    WHERE g.underlying_symbol = 'SPY'
      AND lower(toString(g.option_type)) IN ('call', 'c')
      AND g.date >= toDate('2026-05-22')
      AND g.date <  toDate('2026-07-01')
      AND g.volume > 0
      AND g.option_close > 0
    GROUP BY exp_date
)
SELECT
    toString(a.exp_date)                                                                   AS expiry_date,
    concat(formatDateTime(a.exp_date, '%a %b '), toString(toDayOfMonth(a.exp_date)))       AS expiry_label,
    round(a.premium_before, 2)                                                             AS premium_prior_close,
    round(greatest(s.spot - a.strike, 0.0), 2)                                             AS value_at_expiry,
    round(greatest(s.spot - a.strike, 0.0) / a.premium_before * 100, 0)                    AS pct_of_premium_left,
    round((s.spot / a.spy_before - 1) * 100, 2)                                            AS spy_move_pct
FROM atm AS a
INNER JOIN spy_by_day AS s
    ON s.d = a.exp_date
ORDER BY a.exp_date
Run this yourself

On Mon Jun 1 the contract closed the evening before at $2.5 and was worth $0.58 at the expiry close, 23% of the premium, while SPY moved 0.12% between the two closes. The last row, Tue Jun 30, went from $2.31 to $5.3 on a SPY move of 0.75%. Sorted by outcome:

QueryHow the at-the-money call finished, June 2026 expiries
outcomeexpiries
1. Finished at or near zero (5% of the premium or less)10
2. Lost more than half1
3. Lost up to half5
4. Gained, less than doubled1
5. Doubled or better4
The exact SQL behind every number
WITH spy_by_day AS
(
    SELECT
        toDate(date)                             AS d,
        medianExact(toFloat64(underlying_close)) AS spot
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND date >= toDate('2026-06-01')
      AND date <  toDate('2026-07-01')
      AND underlying_close > 0
    GROUP BY d
),
last_sessions AS
(
    SELECT
        toDate(expiration_date) AS exp_date,
        max(toDate(date))       AS prior_session
    FROM global_markets.options_greeks
    WHERE underlying_symbol = 'SPY'
      AND expiration_date >= toDate('2026-06-01')
      AND expiration_date <  toDate('2026-07-01')
      AND date >= toDate('2026-05-22')
      AND date <  expiration_date
      AND volume > 0
    GROUP BY exp_date
),
atm AS
(
    SELECT
        toDate(g.expiration_date)                                                                                AS exp_date,
        argMin(toFloat64(g.strike_price), abs(toFloat64(g.strike_price) - toFloat64(g.underlying_close)))        AS strike,
        argMin(toFloat64(g.option_close), abs(toFloat64(g.strike_price) - toFloat64(g.underlying_close)))        AS premium_before
    FROM global_markets.options_greeks AS g
    INNER JOIN last_sessions AS ls
        ON ls.exp_date = toDate(g.expiration_date) AND ls.prior_session = toDate(g.date)
    WHERE g.underlying_symbol = 'SPY'
      AND lower(toString(g.option_type)) IN ('call', 'c')
      AND g.date >= toDate('2026-05-22')
      AND g.date <  toDate('2026-07-01')
      AND g.volume > 0
      AND g.option_close > 0
    GROUP BY exp_date
),
outcomes AS
(
    SELECT
        a.exp_date                                          AS exp_date,
        greatest(s.spot - a.strike, 0.0) / a.premium_before AS premium_ratio
    FROM atm AS a
    INNER JOIN spy_by_day AS s
        ON s.d = a.exp_date
)
SELECT
    tupleElement(b, 1)                                                                         AS outcome,
    countIf(o.premium_ratio >= tupleElement(b, 2) AND o.premium_ratio < tupleElement(b, 3))    AS expiries
FROM
(
    SELECT arrayJoin([
        ('1. Finished at or near zero (5% of the premium or less)', -1.0, 0.05),
        ('2. Lost more than half',                                   0.05, 0.5),
        ('3. Lost up to half',                                       0.5,  1.0),
        ('4. Gained, less than doubled',                             1.0,  2.0),
        ('5. Doubled or better',                                     2.0,  1000000.0)
    ]) AS b
) AS buckets
CROSS JOIN outcomes AS o
GROUP BY outcome
ORDER BY outcome
Run this yourself

Of the 21 expiries, 10 finished at or near zero, 1 lost more than half, 5 lost up to half, 1 gained without doubling and 4 doubled or better. Nobody trades exactly this way (most 0DTE positions open and close inside the session) and the tally says nothing about profitability. What it shows is dispersion: a premium of a few dollars became a fraction or a multiple of itself inside one session, expiry after expiry.

Why far strikes cost more than they look

A same-day contract two or three percent from the money trades for cents, and its market is often a few cents wide. Take a hypothetical $0.08 bid and $0.12 ask: the $0.04 spread is 40% of the $0.10 midpoint, given up before SPY moves at all. An at-the-money contract quoted $2.48 to $2.50 costs under 1% to cross. The far strike also carries a small delta, so it needs a large move to pay anything, and its low price invites size. Cheap in dollars is expensive in spread and in odds.

SPX versus SPY: cash settlement, assignment and the 5:30 p.m. cut-off

SPX index options are cash-settled and European-style: at expiry the contract pays the difference between the settlement value and the strike in cash, with no shares and no assignment. SPY and QQQ options are American-style with physical delivery. A SPY call that finishes a cent in the money becomes 100 shares per contract (a put, 100 short shares), and a holder can submit exercise instructions until the OCC's 5:30 p.m. ET cut-off on expiry day, well after the 4:00 p.m. close (brokers set earlier deadlines). SPY keeps trading after the bell, and a contract that closed a few cents out of the money can move in and be exercised against a seller who assumed it had expired. Short-option 0DTE traders in SPY tend to close before the bell for this reason, and many index traders favor SPX, alongside the tax treatment covered in SPX vs SPY options. Monthly SPX contracts settle on the morning open and weeklies at the close; AM vs PM settled options walks through the difference.

Is the risk the instrument or the position size?

Same-day contracts are now the majority of index option trading. Cboe reported that 0DTE made up 56% of SPX options volume in February 2025, a record at the time, and 57% of SPX average daily volume in the third quarter of 2025. Most of that volume is held for minutes to hours by traders who size it as a fraction of an account, and the mechanics above are the same for them as for anyone else.

What differs in the accounts that blow up is sizing. One contract's outcome distribution is fixed by the greeks and the payoff; the account's is that distribution multiplied by the number of contracts. A $2 contract looks cheap. Ten of them are $2,000 that can be zero by 4:00 p.m., a 20% drawdown on a $10,000 account from one afternoon, and recovering a 20% loss takes a 25% gain. The maximum drawdown guide covers that arithmetic, and how risky options trading is applies the same lens to longer-dated contracts.

What a defined-risk 0DTE trade looks like

Defined risk means the maximum loss is known and paid for at entry. Two shapes qualify for a beginner:

  • A long call or put. The most it can lose is the premium, and the panels above show what that premium does in a session.
  • A debit vertical spread: buy one strike and sell a farther one in the same expiry. The most it can lose is the net debit; the most it can make is the distance between the strikes minus that debit. The sold leg lowers the cost and caps both the gain and the gamma.

A credit spread also has a defined maximum loss (the strike width minus the credit) but collects theta while carrying the concentrated gamma, and in SPY the short leg can be assigned. Naked short options have no defined loss at all (margin for naked options explains why). The 0DTE strategies guide walks through how each structure is used.

Everything else on this page, gamma, theta, the spread and the settlement rules, is a property of the contract and cannot be dialed down. The number of contracts is the one input the trader sets. A common convention among traders who publish sizing rules is to keep a single 0DTE position's premium at a small fixed fraction of the account, with 1% a frequently cited figure. At that size a total loss is a routine bad day rather than a drawdown that needs months to recover.

FAQ

Are 0DTE options riskier than regular options?

Per dollar of premium, yes. In June 2026 an at-the-money SPY call with one day left carried 31.8 times the gamma and 28.7 times the daily theta of a 21-to-45-day contract, with no time to recover from a move against it. The dollar risk of a bought contract is still capped at the premium; the risk that scales is position size.

Can you lose more than you paid for a 0DTE option?

Not when buying: a long call or put loses at most the premium. Selling uncovered options can lose far more than the credit received, and in SPY or QQQ a short option that finishes in the money is assigned into 100 shares per contract. Defined-risk spreads cap the loss at the strike width minus the credit.

What happens if a 0DTE SPY option expires in the money?

It is automatically exercised if it finishes $0.01 or more in the money: a call becomes 100 shares of SPY per contract and a put becomes 100 short shares, settling the next business day. Holders can also submit or decline exercise until the OCC's 5:30 p.m. ET cut-off, and brokers set earlier deadlines. SPX options settle in cash instead, with no shares involved.

Do 0DTE options have higher gamma?

Yes, and it is concentrated at the strike. In June 2026 a 1% SPY move shifted an at-the-money next-day contract's delta by 0.497 versus 0.092 for a 21-to-45-day contract; two percent from the money the next-day figure fell to 0.042.

What is a defined-risk 0DTE trade?

A trade whose maximum loss is fixed when it is opened: a long call or put (loses at most the premium) or a debit spread (loses at most the net debit). Structure sets the maximum; the number of contracts decides whether that maximum is survivable.


Every panel above ships with the SQL that produced it. To run the same ladder on QQQ, or on a different month, open any query on the Strasmore terminal and change the symbol or the dates.