Portfolio Delta and Beta Weighting Explained
Raw option deltas do not add up across tickers. Beta weighting rescales portfolio delta into equivalent SPY shares, worked through a small book by hand.
Portfolio delta is the single number that answers one question: if the broad market moves 1%, roughly how much does the whole book move? Adding up the deltas of every position produces a number, but not that one. Beta weighting is the adjustment that makes the sum mean something, restating every holding as an equivalent count of SPY shares.
Why portfolio delta does not add up across tickers
Delta measures how much a position's value changes for a one dollar move in its underlying. One share of stock has a delta of 1. One option contract covers 100 shares, so a call showing a 0.30 delta carries 30 deltas of exposure. That single-position view is the subject of what option delta measures.
The problem arrives with the second ticker. A hundred deltas of a high-priced, high-beta name and a hundred deltas of a cheap defensive name are the same count and nowhere near the same exposure. One is tens of thousands of dollars of stock that has historically swung harder than the index. The other is a few thousand dollars of stock that has historically swung less. Adding them gives 200, a figure in units nobody can act on.
What is beta weighted delta?
Beta weighting restates every delta in the book as a delta of one chosen benchmark, usually SPY for a US equity book. Two multipliers do the work.
The first is beta: a stock's historical sensitivity to the benchmark, measured as the slope of its daily returns against the index's daily returns over a chosen window. A beta of 1.4 means the stock moved about 1.4% on average for every 1% move in the index over that window.
The second is the price ratio, the stock's price divided by the benchmark's price. Delta counts shares, and shares at different prices are different amounts of money. The ratio puts them on one scale.
Multiply a position's raw delta by both and the result is its beta weighted delta: the number of SPY shares that would have behaved the same way over the measurement window. The panel below measures each name's beta from daily closing returns over the year ending June 30, 2026, then shows its price against SPY's and the product of the two. SPY sits in the list as the anchor, with a beta of 1 and a price ratio of 1, which makes one SPY share exactly one beta weighted delta.
The exact SQL behind every number
WITH
sessions AS
(
SELECT
ticker AS ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
toFloat64(argMax(close, window_start)) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'NVDA', 'AAPL', 'MSFT', 'XOM', 'JNJ', 'KO')
AND window_start >= toDateTime('2025-07-01 04:00:00')
AND window_start < toDateTime('2026-07-01 04:00:00')
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
),
steps AS
(
SELECT
ticker,
d,
px,
any(px) OVER (PARTITION BY ticker ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_px
FROM sessions
),
daily_ret AS
(
SELECT ticker, d, (px / prev_px) - 1 AS r
FROM steps
WHERE prev_px > 0
),
bench AS
(
SELECT d, r AS spy_r
FROM daily_ret
WHERE ticker = 'SPY'
),
betas AS
(
SELECT
s.ticker AS ticker,
covarPop(s.r, b.spy_r) / varPop(b.spy_r) AS beta_vs_spy,
1 AS k
FROM daily_ret AS s
INNER JOIN bench AS b ON b.d = s.d
GROUP BY s.ticker
),
prices AS
(
SELECT ticker, argMax(px, d) AS close_px
FROM sessions
GROUP BY ticker
),
spy_price AS
(
SELECT argMax(px, d) AS spy_close, 1 AS k
FROM sessions
WHERE ticker = 'SPY'
)
SELECT
betas.ticker AS ticker,
round(betas.beta_vs_spy, 2) AS beta_vs_spy,
round(prices.close_px / spy_price.spy_close, 3) AS price_vs_spy,
round(betas.beta_vs_spy * prices.close_px / spy_price.spy_close, 3) AS spy_shares_per_share
FROM betas
INNER JOIN prices ON prices.ticker = betas.ticker
INNER JOIN spy_price ON spy_price.k = betas.k
ORDER BY beta_vs_spy DESCNVDA tops the list at a beta of 1.86, trading at 0.268 times SPY's price. Multiply the pair: one share of it carried the index exposure of 0.498 SPY shares. The far end of the 7 names sits below zero. XOM measured a beta of -0.36 over this window, a mild inverse slope against the index rather than a muted version of it, and one share converts to -0.067 SPY shares. One delta on the books in both cases. A wide gap in what that delta is exposed to, and an early hint that a beta printed to two decimals is an estimate with a window attached, a point taken up at the end of this post.
Where the option deltas come from
A stock's delta is fixed at 1 per share. An option's delta is not, and it moves with the strike, the time left to expiry, the underlying's price, and the implied volatility. The panel below reads the delta of every AAPL contract that traded on June 30, 2026 with 20 to 45 days left, grouped into 2% buckets by strike distance from the closing price.
The exact SQL behind every number
SELECT
concat(if(bucket_pct > 0, '+', ''), toString(bucket_pct), '%') AS strike_vs_spot,
round(avgIf(contract_delta, contract_delta > 0), 3) AS call_delta,
round(avgIf(contract_delta, contract_delta < 0), 3) AS put_delta,
count() AS contract_count
FROM
(
SELECT
toInt32(round((toFloat64(strike_price) / toFloat64(underlying_close) - 1) * 50)) * 2 AS bucket_pct,
toFloat64(delta) AS contract_delta
FROM global_markets.options_greeks
WHERE underlying_symbol = 'AAPL'
AND date >= toDate('2026-06-30')
AND date < toDate('2026-07-01')
AND iv_converged = 1
AND volume > 0
AND days_to_expiry BETWEEN 20 AND 45
AND abs(toFloat64(strike_price) / toFloat64(underlying_close) - 1) <= 0.12
)
GROUP BY bucket_pct
HAVING countIf(contract_delta > 0) > 0 AND countIf(contract_delta < 0) > 0
ORDER BY bucket_pctAt the -12% bucket, calls averaged a delta of 0.924 across 4 traded contracts, and puts averaged -0.084. At +10%, calls averaged 0.106 and puts -0.834. A call and a put at the same strike carry deltas of opposite sign, which is why a short call and a long put both offset a long stock position. How the whole curve shifts as expiry approaches is covered in how option greeks change over time.
Working one small book to a single number
Take a three-position book, sized by hand. Long 300 shares of AAPL. Short 3 AAPL calls about 5% above the money with roughly a month to expiry, the standard covered-call overlay. Long 5 KO puts near the money on a similar expiry, a hedge on a second name. The share and contract counts are hypothetical. Every delta and beta in the panel is measured.
The exact SQL behind every number
WITH
sessions AS
(
SELECT
ticker AS ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
toFloat64(argMax(close, window_start)) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'AAPL', 'KO')
AND window_start >= toDateTime('2025-07-01 04:00:00')
AND window_start < toDateTime('2026-07-01 04:00:00')
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
),
steps AS
(
SELECT
ticker,
d,
px,
any(px) OVER (PARTITION BY ticker ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_px
FROM sessions
),
daily_ret AS
(
SELECT ticker, d, (px / prev_px) - 1 AS r
FROM steps
WHERE prev_px > 0
),
bench AS
(
SELECT d, r AS spy_r
FROM daily_ret
WHERE ticker = 'SPY'
),
betas AS
(
SELECT
s.ticker AS ticker,
covarPop(s.r, b.spy_r) / varPop(b.spy_r) AS beta_vs_spy
FROM daily_ret AS s
INNER JOIN bench AS b ON b.d = s.d
GROUP BY s.ticker
),
prices AS
(
SELECT ticker, argMax(px, d) AS close_px, 1 AS k
FROM sessions
GROUP BY ticker
),
spy_price AS
(
SELECT argMax(px, d) AS spy_close, 1 AS k
FROM sessions
WHERE ticker = 'SPY'
),
opt_delta AS
(
SELECT
underlying_symbol AS ticker,
if(toFloat64(delta) > 0, 'call', 'put') AS kind,
avg(toFloat64(delta)) AS per_share_delta
FROM global_markets.options_greeks
WHERE date >= toDate('2026-06-30')
AND date < toDate('2026-07-01')
AND iv_converged = 1
AND volume > 0
AND days_to_expiry BETWEEN 25 AND 40
AND (
(underlying_symbol = 'AAPL' AND toFloat64(delta) > 0
AND toFloat64(strike_price) / toFloat64(underlying_close) BETWEEN 1.03 AND 1.07)
OR (underlying_symbol = 'KO' AND toFloat64(delta) < 0
AND toFloat64(strike_price) / toFloat64(underlying_close) BETWEEN 0.97 AND 1.03)
)
GROUP BY ticker, kind
),
legs AS
(
SELECT
tupleElement(leg, 1) AS leg_no,
tupleElement(leg, 2) AS position,
tupleElement(leg, 3) AS ticker,
tupleElement(leg, 4) AS kind,
tupleElement(leg, 5) AS qty,
tupleElement(leg, 6) AS multiplier
FROM
(
SELECT arrayJoin([
(1, 'Long 300 AAPL', 'AAPL', 'stock', 300., 1.),
(2, 'Short 3 AAPL calls', 'AAPL', 'call', -3., 100.),
(3, 'Long 5 KO puts', 'KO', 'put', 5., 100.)
]) AS leg
)
)
SELECT
position AS position,
round(raw_share_delta) AS raw_share_delta,
round(beta_vs_spy, 2) AS beta_vs_spy,
round(bw_delta) AS beta_weighted_delta,
round(sum(bw_delta) OVER (ORDER BY leg_no ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)) AS running_book_delta,
round(sum(bw_delta) OVER (ORDER BY leg_no ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) * spy_close / 100.) AS dollars_per_1pct_spy
FROM
(
SELECT
l.leg_no AS leg_no,
l.position AS position,
l.qty * l.multiplier * if(l.kind = 'stock', 1., o.per_share_delta) AS raw_share_delta,
bt.beta_vs_spy AS beta_vs_spy,
sp.spy_close AS spy_close,
raw_share_delta * bt.beta_vs_spy * pr.close_px / sp.spy_close AS bw_delta
FROM legs AS l
LEFT JOIN opt_delta AS o ON o.ticker = l.ticker AND o.kind = l.kind
INNER JOIN betas AS bt ON bt.ticker = l.ticker
INNER JOIN prices AS pr ON pr.ticker = l.ticker
INNER JOIN spy_price AS sp ON sp.k = pr.k
)
ORDER BY leg_noThe stock leg brings 300 raw deltas, one per share. The short calls bring -98 and the long puts -217. Adding those three counts gives one figure. Beta weighting gives a different one.
AAPL measured a beta of 0.88 over the window and KO -0.27, a negative slope against the index across those twelve months. After scaling each leg by its beta and by its price against SPY, the stock leg becomes 103 SPY shares, the short calls -34, and the puts 6. The put leg is the one worth pausing on. Its raw count of -217 deltas is short KO, and multiplying a short exposure by a negative beta lands it on the positive side of the ledger at 6 SPY shares, a small long-index reading. Sign aside, the magnitude is the point: a hedge that looks substantial in raw delta terms converts to a small fraction of that count in index terms, and its work is being done on KO rather than on the market. The running total column carries the legs in order, and the book lands at 76 beta weighted deltas.
What a beta weighted delta of that size actually means
A book at 76 beta weighted deltas has behaved, over the measurement window, like holding that many SPY shares. A positive figure describes a book that is long the index. A negative figure describes a book that is short it, which is what traders mean by tilting delta short. The last column translates the running total into money. A 1% move in SPY, with nothing else changing, moves the book by 565 dollars.
Flattening the figure means adding an offsetting beta weighted delta of equal size and opposite sign. Shorting SPY shares does it one for one: one SPY share is one beta weighted delta by construction. SPY options do it in fractions, at whatever delta the chosen contract carries. Trimming the underlying stock position does it at that stock's own conversion rate from the first panel. Each route carries its own costs and its own greeks.
Where beta weighting breaks down
Beta is a regression estimate, and the window it is measured over changes the answer. The panel below recomputes the same two betas over six lookbacks, all ending on the same date.
The exact SQL behind every number
WITH
sessions AS
(
SELECT
ticker AS ticker,
toDate(toTimeZone(window_start, 'America/New_York')) AS d,
toFloat64(argMax(close, window_start)) AS px
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker IN ('SPY', 'AAPL', 'KO')
AND window_start >= toDateTime('2024-04-01 04:00:00')
AND window_start < toDateTime('2026-07-01 04:00:00')
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
),
steps AS
(
SELECT
ticker,
d,
px,
any(px) OVER (PARTITION BY ticker ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS prev_px
FROM sessions
),
daily_ret AS
(
SELECT ticker, d, (px / prev_px) - 1 AS r
FROM steps
WHERE prev_px > 0
),
bench AS
(
SELECT d, r AS spy_r
FROM daily_ret
WHERE ticker = 'SPY'
),
paired AS
(
SELECT
s.ticker AS ticker,
s.r AS r,
b.spy_r AS spy_r,
row_number() OVER (PARTITION BY s.ticker ORDER BY s.d DESC) AS rn
FROM daily_ret AS s
INNER JOIN bench AS b ON b.d = s.d
WHERE s.ticker IN ('AAPL', 'KO')
),
windows AS
(
SELECT arrayJoin([30, 60, 90, 180, 252, 504]) AS lookback
)
SELECT
w.lookback AS lookback_sessions,
round(covarPopIf(p.r, p.spy_r, p.ticker = 'AAPL') / varPopIf(p.spy_r, p.ticker = 'AAPL'), 2) AS aapl_beta,
round(covarPopIf(p.r, p.spy_r, p.ticker = 'KO') / varPopIf(p.spy_r, p.ticker = 'KO'), 2) AS ko_beta
FROM paired AS p
CROSS JOIN windows AS w
WHERE p.rn <= w.lookback
GROUP BY w.lookback
HAVING countIf(p.ticker = 'AAPL') > 0 AND countIf(p.ticker = 'KO') > 0
ORDER BY lookback_sessionsOver the most recent 30 sessions AAPL measured 0.54, against 1.14 over 504 sessions. KO measured -1.04 on the short window and -0.03 on the long one. All 6 estimates are arithmetically correct. They answer different questions, and a beta weighted book delta inherits whichever window the platform happened to pick. A defensive name that prints a slightly negative beta on one window and a slightly positive one on the next is the ordinary case, not an anomaly, and every sign in the worked book above rests on that choice.
Correlation behaviour is the second limit. Beta is an average of ordinary sessions. During a broad selloff, names that usually travel at their own pace have tended to move together, and measured betas cluster toward 1. A book that looks balanced on a quiet-market beta can be far from balanced on the session where the hedge matters. Concentration risk describes the same blind spot from the other side: a summary statistic tells you about the middle of the distribution, not the tail.
Third, the calculation is first order and knows nothing about gamma. Beta weighted delta is the slope of the book's value at today's prices, and it assumes that slope holds. Gamma, the rate at which delta itself changes, appears nowhere in it. A book carrying short options can show a modest beta weighted delta and still change character quickly on a 3% index move. The deltas that fed the calculation no longer describe those positions at those prices. Treat the figure as a description of small moves. Positions built for the tail, such as the ones in protective puts, look tiny in beta weighted terms and are not doing their work in that range anyway.
The benchmark is also a choice. A book of small caps weighted against SPY buries whatever part of its movement belongs to company size rather than to the broad market. Delta is one greek among several, and the rest of the set is laid out in the option greeks explained.
FAQ
What is beta weighted delta?
Beta weighted delta restates every position in a portfolio as an equivalent number of shares of one benchmark, usually SPY. Each position's raw delta is multiplied by the underlying's beta to that benchmark and by the ratio of the two prices, and the results are summed into one figure for the book.
How do you calculate beta weighted delta by hand?
Start with the position's delta in shares: 1 per share of stock, or 100 times the option delta per contract. Multiply by the underlying's beta against the benchmark, then multiply again by the underlying's price divided by the benchmark's price. Add the results across every position.
What does a negative beta weighted delta mean?
It describes a book positioned to gain value when the benchmark falls and lose value when it rises, at roughly the rate of being short that many benchmark shares. Traders call this tilting delta short. The figure holds for small moves only.
Can a stock have a negative beta?
Yes, over a given window. Beta is the measured slope of a stock's daily returns against the index's, and a defensive name can come out slightly below zero over one twelve-month stretch and slightly above zero over the next. A negative beta flips the sign of that position's beta weighted delta, which is why the metric is read alongside the window it was measured on.
Which lookback window gives the right beta?
There is no single right window. A 30-session beta tracks recent behaviour and moves around a great deal, while a one-year or two-year beta is steadier and slower to register a change in the underlying business. The stability panel above shows how far apart two windows can sit for the same stock on the same date.
Does beta weighting account for gamma or volatility?
No. It is a first-order measure built from current deltas and a historical beta. Gamma, vega, theta, and rho are untouched by it, so a book of short options can look flat in beta weighted delta terms and still carry substantial risk on a large move.
Every panel above ships with the SQL that produced it. Open one, swap the tickers or the measurement window, and the same beta weighted arithmetic runs against any book you can describe on the Strasmore terminal.