Strasmore Research
Learn Matt ConnorBy Matt Connor · data as of October 5, 2026 · refreshed weekly

What Is Vomma? The Convexity of Vega

Vomma is the rate of change of an option's vega as implied volatility moves. See where it peaks on the strike ladder, measured on a real SPY option chain.

Vomma is the rate of change of an option's vega as implied volatility changes. Vega measures how much an option's price moves per one point of implied volatility. Vomma measures how much that vega figure itself grows or shrinks as implied volatility travels, which is why a long option gains more during a volatility spike than a single vega number predicts, and why out-of-the-money strikes carry much more of that effect than at-the-money ones.

What is vomma in options?

Vega is the first derivative of an option's model price with respect to implied volatility. Vomma is the derivative of vega with respect to that same input, which makes it the second derivative of price in volatility. Traders call the property convexity: the option's value curve in volatility space bends instead of running straight, and vega is a tangent line that goes stale as soon as volatility moves.

One derivative is all the maths this needs. Under the standard Black-Scholes treatment, vomma = vega * d1 * d2 / sigma, where sigma is implied volatility and d1 and d2 are the two standardised distances inside every Black-Scholes price. d1 measures how far the strike sits from the forward price in standard deviations of the option's remaining life, and d2 is d1 less one of those standard deviations. The product of the two does the work. Near the money, d1 and d2 sit close to zero with opposite signs, and their product is close to nothing. Far out in either wing both sit well away from zero with the same sign, and the product grows. For the first-order greek underneath this one, start with option vega; for the full family, see the option greeks explained.

Where vomma sits on the strike ladder

The panel below takes one SPY expiry about five weeks out, sorts every contract that traded that session into bands by the distance from its strike to spot, and scales vega and vomma against the largest reading on the chain so both shapes fit one axis. The third series restates vomma as a plain number: the percentage change in vega per one point move in implied volatility.

QueryVega and vomma across strikes, one SPY expiry
moneynessvega_pct_of_peakvomma_pct_of_peakvega_growth_pct_per_vol_pt
10%+ below spot12.924.812.88
5-10% below4960.47.63
2-5% below76.144.43.62
within 2% of spot1009.30.58
2-5% above74.471.36.55
5-10% above28.110025.42
10%+ above spot4.634.246.63
The exact SQL behind every number
WITH
    (
        SELECT max(date)
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
    ) AS snap_date,
    (
        SELECT argMin(expiration_date, abs(toInt32(days_to_expiry) - 35))
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date = snap_date
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry BETWEEN 20 AND 60
    ) AS expiry
SELECT
    strike_band                                             AS moneyness,
    round(100 * avg_vega / max(avg_vega) OVER (), 1)        AS vega_pct_of_peak,
    round(100 * avg_vomma / max(abs(avg_vomma)) OVER (), 1) AS vomma_pct_of_peak,
    round(avg_growth, 2)                                    AS vega_growth_pct_per_vol_pt
FROM
(
    SELECT
        multiIf(k < -0.10, '10%+ below spot',
                k < -0.05, '5-10% below',
                k < -0.02, '2-5% below',
                k <= 0.02, 'within 2% of spot',
                k <= 0.05, '2-5% above',
                k <= 0.10, '5-10% above',
                           '10%+ above spot')     AS strike_band,
        multiIf(k < -0.10, 1, k < -0.05, 2, k < -0.02, 3,
                k <= 0.02, 4, k <= 0.05, 5, k <= 0.10, 6, 7) AS band_sort,
        avg(vega)                                  AS avg_vega,
        avg(vega * d1 * d2 / sigma)                AS avg_vomma,
        avg(d1 * d2 / sigma)                       AS avg_growth
    FROM
    (
        SELECT
            k,
            sigma,
            vega,
            d1,
            d1 - sigma * sqrt(t_years)             AS d2
        FROM
        (
            SELECT
                k,
                sigma,
                vega,
                t_years,
                (log(spot / strike) + (rate + sigma * sigma / 2) * t_years)
                    / (sigma * sqrt(t_years))      AS d1
            FROM
            (
                SELECT
                    toFloat64(underlying_close)                               AS spot,
                    toFloat64(strike_price)                                   AS strike,
                    toFloat64(strike_price) / toFloat64(underlying_close) - 1 AS k,
                    toFloat64(implied_volatility)                             AS sigma,
                    toFloat64(vega)                                           AS vega,
                    days_to_expiry / 365.0                                    AS t_years,
                    if(toFloat64(risk_free_rate) > 1,
                       toFloat64(risk_free_rate) / 100,
                       toFloat64(risk_free_rate))                             AS rate
                FROM global_markets.options_greeks
                WHERE underlying_symbol = 'SPY'
                  AND date = snap_date
                  AND expiration_date = expiry
                  AND iv_converged = 1
                  AND volume > 0
                  AND vega > 0
                  AND days_to_expiry >= 7
                  AND implied_volatility BETWEEN 0.02 AND 3.0
            )
        )
    )
    GROUP BY strike_band, band_sort
)
ORDER BY band_sort
Run this yourself

Vega peaks in the middle of the ladder. The band within 2% of spot prints 100% of the chain's peak vega, while the band 10% or more above spot prints 4.6%. Vomma runs the other way. In that same middle band it measures 9.3% of the chain's largest absolute vomma, against 24.8% in the deepest band below spot and 34.2% in the deepest band above it. Read as a growth rate, vega in the far above-spot band changes 46.63% per point of implied volatility, against 0.58% within 2% of spot.

That pairing is the practical content of the panel. An at-the-money option is where vega is biggest and steadiest. A wing option starts with less vega and owns a vega that climbs as volatility rises, so the position grows longer volatility the more volatility there is.

A volatility spike pays more than the vega estimate

Work it through on a hypothetical contract. Say it carries a vega of 12 cents per volatility point, and a vomma such that vega grows 6% for every point implied volatility adds. Implied volatility then rises 5 points. The linear estimate multiplies vega by the move: 5 times 12 cents is 60 cents. The real path differs, since vega is not 12 cents for the whole trip. It is 12 cents at the start and roughly 15.6 cents at the end, averaging near 13.8 cents, so the option picks up about 69 cents. That 9 cent difference is the vomma term. Its general form is half the vomma times the square of the volatility move.

The panel below runs the same arithmetic on the real chain, comparing the wing bands (5% to 12% away from spot) with the at-the-money band across a range of volatility shocks.

QueryHow far the vega-only estimate falls short, by size of the vol move
vol_risewing_uplift_pctatm_uplift_pct
+1 vol pts7.90.3
+2 vol pts15.90.6
+3 vol pts23.80.9
+5 vol pts39.71.4
+8 vol pts63.52.3
+10 vol pts79.32.9
+15 vol pts1194.3
The exact SQL behind every number
WITH
    (
        SELECT max(date)
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
    ) AS snap_date,
    (
        SELECT argMin(expiration_date, abs(toInt32(days_to_expiry) - 35))
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date = snap_date
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry BETWEEN 20 AND 60
    ) AS expiry
SELECT
    concat('+', toString(shock_pts), ' vol pts')  AS vol_rise,
    round(0.5 * wing_growth * shock_pts, 1)       AS wing_uplift_pct,
    round(0.5 * atm_growth * shock_pts, 1)        AS atm_uplift_pct
FROM
(
    SELECT
        avgIf(d1 * d2 / sigma, abs(k) > 0.05 AND abs(k) <= 0.12) AS wing_growth,
        avgIf(d1 * d2 / sigma, abs(k) <= 0.02)                   AS atm_growth
    FROM
    (
        SELECT
            k,
            sigma,
            d1,
            d1 - sigma * sqrt(t_years) AS d2
        FROM
        (
            SELECT
                k,
                sigma,
                t_years,
                (log(spot / strike) + (rate + sigma * sigma / 2) * t_years)
                    / (sigma * sqrt(t_years)) AS d1
            FROM
            (
                SELECT
                    toFloat64(underlying_close)                               AS spot,
                    toFloat64(strike_price)                                   AS strike,
                    toFloat64(strike_price) / toFloat64(underlying_close) - 1 AS k,
                    toFloat64(implied_volatility)                             AS sigma,
                    days_to_expiry / 365.0                                    AS t_years,
                    if(toFloat64(risk_free_rate) > 1,
                       toFloat64(risk_free_rate) / 100,
                       toFloat64(risk_free_rate))                             AS rate
                FROM global_markets.options_greeks
                WHERE underlying_symbol = 'SPY'
                  AND date = snap_date
                  AND expiration_date = expiry
                  AND iv_converged = 1
                  AND volume > 0
                  AND vega > 0
                  AND days_to_expiry >= 7
                  AND implied_volatility BETWEEN 0.02 AND 3.0
            )
        )
    )
    HAVING countIf(abs(k) > 0.05 AND abs(k) <= 0.12) > 0
       AND countIf(abs(k) <= 0.02) > 0
) AS chain
CROSS JOIN
(
    SELECT arrayJoin([1, 2, 3, 5, 8, 10, 15]) AS shock_pts
) AS shocks
ORDER BY shock_pts
Run this yourself

At a +5 vol pts move, the wing bands land 39.7% above what vega alone predicts, while the at-the-money band lands 1.4%. Push the shock to +15 vol pts and the wing gap widens to 119%. The term is quadratic in the size of the move, so it stays a rounding error in a quiet tape and becomes the main event in a violent one. The symmetry matters as well: the same convexity that pays extra on a volatility rise gives back less than the linear estimate on a volatility fall.

Vomma and the volatility smile

A model with one constant volatility for every strike has nothing to say about vomma in the market's sense. Price every contract on an expiry with the same number and the implied volatilities come back identical across strikes, a flat line. Real chains do not print flat lines.

QueryImplied volatility across strikes on the same SPY expiry
moneynessimplied_vol_pctvs_chain_avg_ptscontracts
10%+ below spot34.1516.9631
5-10% below19.061.8822
2-5% below16.42-0.7631
within 2% of spot13.45-3.7458
2-5% above11.67-5.5129
5-10% above11.52-5.6613
10%+ above spot14.02-3.175
The exact SQL behind every number
WITH
    (
        SELECT max(date)
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
    ) AS snap_date,
    (
        SELECT argMin(expiration_date, abs(toInt32(days_to_expiry) - 35))
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date = snap_date
          AND iv_converged = 1
          AND volume > 0
          AND days_to_expiry BETWEEN 20 AND 60
    ) AS expiry
SELECT
    strike_band                                        AS moneyness,
    round(100 * avg_iv, 2)                             AS implied_vol_pct,
    round(100 * avg_iv - 100 * avg(avg_iv) OVER (), 2) AS vs_chain_avg_pts,
    contracts
FROM
(
    SELECT
        multiIf(k < -0.10, '10%+ below spot',
                k < -0.05, '5-10% below',
                k < -0.02, '2-5% below',
                k <= 0.02, 'within 2% of spot',
                k <= 0.05, '2-5% above',
                k <= 0.10, '5-10% above',
                           '10%+ above spot')     AS strike_band,
        multiIf(k < -0.10, 1, k < -0.05, 2, k < -0.02, 3,
                k <= 0.02, 4, k <= 0.05, 5, k <= 0.10, 6, 7) AS band_sort,
        avg(sigma)                                 AS avg_iv,
        count()                                    AS contracts
    FROM
    (
        SELECT
            toFloat64(strike_price) / toFloat64(underlying_close) - 1 AS k,
            toFloat64(implied_volatility)                             AS sigma
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
          AND date = snap_date
          AND expiration_date = expiry
          AND iv_converged = 1
          AND volume > 0
          AND vega > 0
          AND days_to_expiry >= 7
          AND implied_volatility BETWEEN 0.02 AND 3.0
    )
    GROUP BY strike_band, band_sort
)
ORDER BY band_sort
Run this yourself

On this expiry the deepest band below spot prints 34.15% implied volatility, the middle band 13.45%, and the deepest band above spot 14.02%. Measured against the average of the whole ladder, the low-strike wing stands at 16.96 points and the high-strike wing at -3.17. That curve is the volatility smile, and its equity-market tilt toward the lower strikes is the subject of our volatility skew guide.

The link back to vomma is direct. A smile means the market charges a different volatility at each strike, which is another way of saying it treats volatility as something that itself moves. Models carrying a second source of randomness for volatility, the Heston model among them, generate a smile out of their own dynamics, and vomma is the sensitivity that makes that possible. With zero vomma everywhere there is no curvature in volatility to charge for.

Does vomma change with time to expiry?

QueryPercent change in vega per vol point, by time to expiry (SPY)
dtewing_growth_pctatm_growth_pct
7 to 21 days26.233.34
22 to 45 days16.860.62
46 to 90 days8.540.33
91 to 180 days4.640.26
over 180 days1.250.29
The exact SQL behind every number
WITH
    (
        SELECT max(date)
        FROM global_markets.options_greeks
        WHERE underlying_symbol = 'SPY'
    ) AS snap_date
SELECT
    dte,
    round(wing_growth, 2) AS wing_growth_pct,
    round(atm_growth, 2)  AS atm_growth_pct
FROM
(
    SELECT
        multiIf(dte_days <= 21,  '7 to 21 days',
                dte_days <= 45,  '22 to 45 days',
                dte_days <= 90,  '46 to 90 days',
                dte_days <= 180, '91 to 180 days',
                                 'over 180 days')  AS dte,
        multiIf(dte_days <= 21, 1, dte_days <= 45, 2, dte_days <= 90, 3,
                dte_days <= 180, 4, 5)             AS dte_sort,
        avgIf(d1 * d2 / sigma, abs(k) > 0.05 AND abs(k) <= 0.12) AS wing_growth,
        avgIf(d1 * d2 / sigma, abs(k) <= 0.02)                   AS atm_growth
    FROM
    (
        SELECT
            k,
            sigma,
            dte_days,
            d1,
            d1 - sigma * sqrt(t_years) AS d2
        FROM
        (
            SELECT
                k,
                sigma,
                dte_days,
                t_years,
                (log(spot / strike) + (rate + sigma * sigma / 2) * t_years)
                    / (sigma * sqrt(t_years)) AS d1
            FROM
            (
                SELECT
                    toFloat64(underlying_close)                               AS spot,
                    toFloat64(strike_price)                                   AS strike,
                    toFloat64(strike_price) / toFloat64(underlying_close) - 1 AS k,
                    toFloat64(implied_volatility)                             AS sigma,
                    toInt32(days_to_expiry)                                   AS dte_days,
                    days_to_expiry / 365.0                                    AS t_years,
                    if(toFloat64(risk_free_rate) > 1,
                       toFloat64(risk_free_rate) / 100,
                       toFloat64(risk_free_rate))                             AS rate
                FROM global_markets.options_greeks
                WHERE underlying_symbol = 'SPY'
                  AND date = snap_date
                  AND iv_converged = 1
                  AND volume > 0
                  AND vega > 0
                  AND days_to_expiry >= 7
                  AND implied_volatility BETWEEN 0.02 AND 3.0
            )
        )
    )
    GROUP BY dte, dte_sort
    HAVING countIf(abs(k) > 0.05 AND abs(k) <= 0.12) > 2
       AND countIf(abs(k) <= 0.02) > 2
)
ORDER BY dte_sort
Run this yourself

Vomma is not one number per name. In the 7 to 21 days bucket the wing reading prints 26.23% per point, and in the over 180 days bucket 1.25%. The at-the-money column runs 3.34% and 0.29% across those same two buckets. The mechanics live in d1 and d2 again. Distance from the money is measured in standard deviations of the remaining life, and that yardstick stretches with the square root of time. A strike 8% away is several standard deviations out over two weeks and a fraction of one over two years, which pulls d1 and d2 toward each other and changes their product. The same stretching runs through every greek, traced in how option greeks change over time.

Vomma is a model output, not a tape print

No exchange publishes vomma. It falls out of a model, and a model needs assumptions: which volatility to feed each strike, how to treat dividends, which rate to discount at, whether volatility is held constant or allowed to wander. Two desks can agree on an option's price to the penny and still report different vommas for it, since they are differentiating different functions. The figures on this page come from one consistent treatment applied the same way to every contract on the chain, which is what makes the shape across strikes worth reading even where the level is a model choice.

How these numbers were computed

Each panel starts from the daily per-contract greeks for SPY on the most recent session available, keeping only contracts that traded (volume > 0) with a converged implied volatility (iv_converged = 1). Vomma is derived from the stored vega and the same Black-Scholes inputs that vega rests on, through vomma = vega * d1 * d2 / sigma. Discrete dividends are not modelled, which shifts the forward slightly on longer-dated contracts. Bands average calls and puts at the same strike, where vega and vomma are theoretically equal, so small differences in quoted implied volatility between the two feed into the band averages. The expiry used in the strike-ladder panels is the listed expiration closest to 35 days out.

FAQ

What is vomma in options trading?

Vomma is the rate of change of an option's vega as implied volatility changes, which makes it the second derivative of the option's price with respect to volatility. A positive vomma means vega grows as implied volatility rises.

What is the difference between vega and vomma?

Vega is how much the option price moves per one point of implied volatility. Vomma is how much vega itself moves per one point of implied volatility. Vega is the slope; vomma is the bend in that slope.

Which options have the most vomma?

Strikes away from the money carry the most, and contracts within a couple of percent of spot carry close to none. The strike ladder above shows the full shape for one expiry, with vega peaking in the middle while vomma peaks in the wings.

Can vomma be negative?

Yes. Its sign follows the product of d1 and d2, and those two carry opposite signs in a narrow band around the money, so a near-the-money contract can show a small negative vomma. The magnitude there is small in either direction.


Every panel on this page ships with the SQL that produced it, so the same strike ladder can be rebuilt on another name or another expiry. Ask for that chain in plain English on the Strasmore terminal.

#options greeks#vomma#vega#volatility smile#second-order greeks