Volume vs open interest is the first thing a serious options trader checks, because together they answer one question: is the action at this strike fresh money or just noise? Volume is how many contracts traded today; open interest is how many contracts are still open and outstanding. This guide explains the difference, shows why their ratio is the real unusual-activity signal, and then builds a complete scoring engine — the kind that powers an "unusual whales"-style scanner — that ranks any contract into a STRONG, WATCH, or INTERESTING alert tier.

ℹ️ INFO
This builds directly on [how to read an option chain](/learning/read-option-chain/). If delta, gamma, and theta are still fuzzy, read that first — this article uses all three as scoring inputs.

Volume vs open interest: the core difference

These two numbers sit side by side in every chain, and beginners constantly confuse them. The distinction is simple once you anchor it:

VolumeOpen Interest
MeasuresContracts traded TODAYContracts still OPEN
ResetsEvery day at the openNever — it's cumulative
Tells youToday's activity / interestTotal existing positions
DirectionCan rise all dayUpdated once overnight

Volume is a speedometer — it reads today's pace and zeros out tomorrow. Open interest (OI) is an odometer — it accumulates every position that has been opened and not yet closed. A strike can have huge open interest (lots of standing positions) but tiny volume today (nobody trading), or the reverse.

ℹ️ INFO
Open interest updates once per day, after the close — it is not real-time. Volume is live and ticks up all session. That timing gap matters when you build a scanner: you compare a live number against yesterday's standing base.

The volume/OI ratio is the real signal

Neither number means much alone. The signal is the ratio:

This single number tells you whether today's trading is routine churn or something new arriving:

Quiet — skip it
Ratio < 0.5
Normal activity
Ratio 0.5–1
Notable — volume tops OI
Ratio > 1
Unusual — fresh positioning
Ratio > 3

When volume exceeds open interest (ratio > 1), more contracts changed hands today than existed at the open — impossible unless brand-new positions are being created. When the ratio crosses 3, it is a loud signal: roughly three times the standing base traded in a single session. That is the footprint of large, directional, intentional buying. Plug in real numbers below and watch the verdict flip across the thresholds.


Fresh positioning vs liquidation

A high ratio tells you something happened — it does not tell you what. This is the nuance most guides skip. A spike in volume relative to OI can mean two opposite things:

  • Fresh positioning — new buyers opening contracts. Tomorrow's OI will rise to absorb today's volume. This is the bullish-for-calls / bearish-for-puts signal scanners hunt.
  • Liquidation — existing holders closing out. Tomorrow's OI will fall. Same volume spike, opposite meaning.

You cannot tell them apart from the ratio alone in real time. That is exactly why a good scanner never trades the ratio by itself — it stacks the ratio with price direction and premium movement to confirm new money is flowing in the same direction. Unusual volume that lines up with a rising stock and a rising premium is the smart-money flow signal worth acting on.

⚠️ WARNING
A high volume/OI ratio is necessary but not sufficient. Always confirm with direction (is the stock moving the right way?) and premium change (is the option itself gaining value?) before treating it as a real alert.

From signal to score: the alert detector

So how do professionals turn these scattered clues into one decision? They score every contract. Instead of one make-or-break rule, each bullish clue adds points and each red flag subtracts them. A contract that stacks many confirmations rises to the top; a contract with one good trait but a fatal flaw (a wide, illiquid spread) gets filtered out.

flowchart LR A[Contract data] --> B[Derived metrics] B --> C[Score each factor] C --> D{Total score} D -- ">= 85" --> S[STRONG ALERT] D -- "70-84" --> W[WATCH] D -- "55-69" --> I[INTERESTING] D -- "< 55" --> X[Skip]

The engine runs in five stages: pull the raw contract data, compute derived metrics (ratios, percentage changes, velocity), score each factor, confirm direction, then map the total to an alert tier. Here is the complete, commented engine:

# =====================================================================
#  EXPERT OPTION ALERT DETECTOR
#  Scores every contract in a chain for unusual activity and assigns
#  an alert tier. Higher score = more confirmations stacked together.
# =====================================================================

for contract in option_chain:

    # -----------------------------------------------------------------
    # 1. Raw contract data (straight from the feed)
    # -----------------------------------------------------------------
    symbol = contract.symbol
    type   = contract.type            # "CALL" or "PUT"
    bid    = contract.bid
    ask    = contract.ask
    volume = contract.volume          # contracts traded TODAY
    oi     = max(contract.open_interest, 1)   # avoid divide-by-zero

    delta  = abs(contract.delta)      # use magnitude (puts are negative)
    gamma  = contract.gamma
    theta  = contract.theta

    stock_now     = underlying.price_now
    stock_5m_ago  = underlying.price_5m_ago

    premium_now    = (bid + ask) / 2          # mid price
    premium_5m_ago = contract.premium_5m_ago

    # -----------------------------------------------------------------
    # 2. Derived metrics (the numbers that actually carry signal)
    # -----------------------------------------------------------------
    spread_pct = (ask - bid) / premium_now * 100        # liquidity cost

    volume_oi_ratio = volume / oi                       # fresh-money gauge

    premium_change_pct = (premium_now - premium_5m_ago) / premium_5m_ago * 100
    stock_change_pct   = (stock_now - stock_5m_ago)     / stock_5m_ago   * 100

    premium_velocity = premium_change_pct / 5           # %% move per minute

    # -----------------------------------------------------------------
    # 3. Direction confirmation
    #    A real alert needs price AND premium moving the same way.
    # -----------------------------------------------------------------
    bullish_call = (type == "CALL"
                    and stock_change_pct > 0
                    and premium_change_pct > 0)

    bearish_put  = (type == "PUT"
                    and stock_change_pct < 0          # stock falling
                    and premium_change_pct > 0)       # put gaining value

    direction_confirmed = bullish_call or bearish_put

    # -----------------------------------------------------------------
    # 4. Expert scoring — each factor adds or subtracts points
    # -----------------------------------------------------------------
    score = 0

    # --- Unusual activity (the volume/OI core) ---
    if volume > 1000:            score += 10   # liquid enough to matter
    if volume_oi_ratio > 1:      score += 15   # volume tops open interest
    if volume_oi_ratio > 3:      score += 25   # fresh positioning (stacks)

    # --- Premium movement (is the option itself running?) ---
    if premium_change_pct > 10:  score += 10
    if premium_change_pct > 20:  score += 20   # stacks on top of the +10
    if premium_velocity > 3:     score += 15   # moving FAST, not drifting

    # --- Liquidity (reward tight, punish wide) ---
    if spread_pct < 5:           score += 15   # easy in / easy out
    elif spread_pct > 10:        score -= 20   # spread tax — avoid

    # --- Day-trading delta zone ---
    if 0.30 <= delta <= 0.70:    score += 15   # responsive but not too deep

    # --- Gamma accelerator (delta picks up speed near the money) ---
    if gamma > 0.03:             score += 10
    if gamma > 0.05:             score += 15   # stacks on top of the +10

    # --- Direction confirmation bonus ---
    if direction_confirmed:      score += 20

    # --- Theta risk penalty (decay eating the premium) ---
    if abs(theta) > premium_now * 0.25:  score -= 10

    # -----------------------------------------------------------------
    # 5. Alert tier — map the total score to a label
    # -----------------------------------------------------------------
    if   score >= 85:  alert_level = "🔥 STRONG ALERT"
    elif score >= 70:  alert_level = "⚠️ WATCH ALERT"
    elif score >= 55:  alert_level = "👀 INTERESTING"
    else:              continue          # below threshold — skip silently

    # -----------------------------------------------------------------
    # 6. Send the alert
    # -----------------------------------------------------------------
    send_alert({
        "symbol":             symbol,
        "type":               type,
        "strike":             contract.strike,
        "expiry":             contract.expiry,
        "score":              score,
        "alert_level":        alert_level,
        "premium_now":        premium_now,
        "premium_change_pct": premium_change_pct,
        "volume":             volume,
        "open_interest":      oi,
        "volume_oi_ratio":    volume_oi_ratio,
        "spread_pct":         spread_pct,
        "delta":              delta,
        "gamma":              gamma,
        "stock_change_pct":   stock_change_pct,
    })

The next sections unpack why each block earns the points it does.


Scoring unusual activity

The volume and OI block is the heart of the engine. Note how the volume/OI rules stack: a ratio above 3 fires both the > 1 rule (+15) and the > 3 rule (+25) for +40 total. That is intentional — a ratio of 3.5 is far more meaningful than 1.1, so it should score far higher.

+10
volume > 1,000
+15
volume/OI > 1
+25 (stacks → +40)
volume/OI > 3

The bare volume > 1000 check is a liquidity floor — it stops the scanner from flagging a thinly-traded strike where five contracts created a misleading ratio.


Scoring premium movement

Volume tells you contracts are trading; premium change tells you traders are paying up. A rising premium confirms demand is real, not passive.

+10
premium up > 10%
+20 (stacks → +30)
premium up > 20%
+15
velocity > 3%/min

Velocity is the subtle one. premium_velocity = premium_change_pct / 5 converts a 5-minute change into a per-minute pace. A premium up 16% over five minutes (velocity 3.2) is a far stronger signal than the same 16% bled out over an hour — it means buyers are aggressive right now.


Scoring liquidity and the spread tax

Liquidity is the only factor that can go negative on its own, and for good reason. A wide bid/ask spread is a hidden tax you pay on entry and exit:

+15
spread < 5%
0 (neutral)
spread 5–10%
−20
spread > 10%

A contract can ace every other test and still be untradeable if the spread is 12% wide — you would lose a chunk the instant you enter. The −20 penalty deliberately drags those contracts below the alert threshold no matter how unusual the volume looks.

🚨 DANGER
Never chase a high-score alert with a wide spread. The −20 penalty exists because an illiquid contract traps you: the spread eats your edge on entry, and you may not find a buyer when you need to exit.

The Greek filters: delta, gamma, theta

The same Greeks you decoded in how to read an option chain become quality filters here:

  • Delta 0.30–0.70 (+15) — the day-trading sweet spot. Responsive to the underlying, but not so deep ITM that it costs a fortune and stops accelerating.
  • Gamma > 0.03 (+10), > 0.05 (+15, stacks) — rewards contracts whose delta will accelerate as the move develops. High gamma is the near-the-money kicker.
  • Theta penalty (−10) — fires when abs(theta) > premium_now × 0.25, i.e. decay is burning more than a quarter of the premium per day. This protects you from buying a fast-bleeding contract right before expiration.

The theta rule is what keeps the scanner honest near expiry: a 0-DTE contract can look explosive on volume and premium, but if it is shedding 30% of its value per day, the engine docks it.


Alert tiers: STRONG, WATCH, INTERESTING

The final step maps the total to a tier. Anything under 55 is dropped silently — no alert, no noise.

🔥 STRONG ALERT
Score ≥ 85
⚠️ WATCH ALERT
Score 70–84
👀 INTERESTING
Score 55–69
skipped
Score < 55

Because the bullish rules stack, a textbook setup — unusual ratio, fast premium, tight spread, ATM delta, high gamma, confirmed direction — easily clears 85 and several points beyond. That headroom is fine; the tiers are floors, not caps. Run a live contract through the full engine below and watch each rule light up:


Developer notes: the data you actually need

To run this engine you do not need an expensive platform — you need a feed that delivers, per contract:

RequiredPlus a short history
VolumeLive, per contract
Open interestDaily snapshot
Bid / AskFor spread + mid
Greeksdelta, gamma, theta
Premium 5m agorolling buffer you store
Stock 5m agounderlying lookback
IVoptional refinement

The only piece a raw snapshot does not hand you is the 5-minutes-ago values — you maintain those yourself with a small rolling buffer, sampling each contract's mid price and the underlying every minute. Everything else (Greeks, OI, volume, quotes) comes straight from a standard options feed. That is enough to build a scanner that rivals the paid tools.

Confirmed Alert — Price and Premium Rising Together


Key takeaway

Read volume and open interest together, never apart: volume/OI ratio first to spot fresh money, then stack confirmations — premium movement, tight spread, the right delta and gamma, and price direction — before you call it an alert. The scoring engine's whole purpose is to stop you acting on a single clue. One unusual-volume print is a question; a contract that scores 85+ across six independent factors is an answer.

The one-line takeaway
Volume is today's pace, open interest is the standing base, and their ratio flags fresh money. Score that signal against premium, spread, Greeks, and direction — and only trade the contracts that stack confirmations into a STRONG alert.