Volatility Trading and Arbitrage Strategies › Volatility Arbitrage

Michael BrenndoerferDecember 30, 202510 min read
Quantitative FinanceAll chapters
Part 11 of 15Quantitative Trading Strategies
Chapter 63Volatility Trading and Arbitrage Strategies › Volatility Arbitrage
Reading section 5 of 15 · Volatility Arbitrage · 10 minSection 5 of 15 · 10 min

Book contents

Section 5 of 15 · 10 min read

Volatility Trading and Arbitrage Strategies › Volatility ArbitrageOne section · Sections in this chapter5 / 15 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Volatility arbitrage strategies seek to profit from differences between implied volatility and expected realized volatility. These strategies require both a view on future volatility and the ability to isolate volatility exposure through hedging. The term "arbitrage" is a misnomer; these strategies involve taking a view rather than exploiting a riskless mispricing. However, the term has become standard in the industry to describe strategies that attempt to profit from the difference between where volatility is priced and where it will be realized.

Long Volatility Strategies

You go long volatility when you believe options are underpriced relative to future realized volatility. This typically occurs:

  • Before anticipated high-volatility events (earnings, elections, major economic announcements)
  • When implied volatility is historically low relative to its own range
  • When technical or fundamental factors suggest increased uncertainty

Long volatility positions can be constructed through:

  • Straddles: Buy both a call and put at the same strike, profiting from large moves in either direction
  • Strangles: Buy an out-of-the-money call and put, cheaper but requiring larger moves
  • Delta-hedged long options: Buy options and maintain delta-neutral exposure

A straddle combines a call and a put at the same strike price and expiration, creating a position that profits from any large price move regardless of direction. The maximum loss is limited to the premium paid for both options, which occurs if the underlying closes exactly at the strike at expiration. The trade becomes profitable when the underlying moves far enough from the strike to exceed the total premium paid.

The P&L for a long straddle at expiration is:

P&L=max⁡(ST−K,0)+max⁡(K−ST,0)−(Cpremium+Ppremium)\text{P\&L} = \max(S_T - K, 0) + \max(K - S_T, 0) - (C_{\text{premium}} + P_{\text{premium}})

where:

  • P&L\text{P\&L}: profit or loss at expiration
  • STS_T: stock price at expiration
  • KK: strike price
  • CpremiumC_{\text{premium}}: premium paid for the call
  • PpremiumP_{\text{premium}}: premium paid for the put

The formula captures the essential structure of the straddle: at expiration, exactly one of the two options will be in the money (unless the stock closes precisely at the strike). If the stock is above the strike, the call pays out its intrinsic value while the put expires worthless. If the stock is below the strike, the put pays out while the call expires worthless. The first two terms in the formula calculate these payoffs, and the third term subtracts the cost of establishing the position. For the trade to be profitable, the stock must move far enough that the winning option's payoff exceeds the combined cost of both options.

In[16]:
Code
def straddle_payoff(S_T, K, call_premium, put_premium):
    """Calculate straddle P&L at expiration."""
    call_payoff = np.maximum(S_T - K, 0) - call_premium
    put_payoff = np.maximum(K - S_T, 0) - put_premium
    return call_payoff + put_payoff


def black_scholes_put(S, K, T, r, sigma):
    """Calculate Black-Scholes put price."""
    d1 = (np.log(S / K) + (r + 0.5 * sigma**2) * T) / (sigma * np.sqrt(T))
    d2 = d1 - sigma * np.sqrt(T)
    return K * np.exp(-r * T) * norm.cdf(-d2) - S * norm.cdf(-d1)


# Straddle parameters
S = 100
K = 100
T = 30 / 365
r = 0.05
sigma = 0.25

call_price, _, _ = black_scholes_call(S, K, T, r, sigma)
put_price = black_scholes_put(S, K, T, r, sigma)
straddle_cost = call_price + put_price

# Calculate breakeven points
S_range = np.linspace(80, 120, 200)
straddle_pnl = straddle_payoff(S_range, K, call_price, put_price)

breakeven_down = K - straddle_cost
breakeven_up = K + straddle_cost
Out[17]:
Visualization
V-shaped long-straddle payoff centered on the 100-dollar strike, with losses between the two breakevens and profits beyond them.
Expiration payoff profile for a long straddle at the \$100 strike. The V-shaped diagram illustrates that profit is achieved when the underlying asset moves beyond the upper or lower breakeven points, which are determined by the total premium paid for the call and put.
Out[18]:
Console
Straddle Cost: $5.72
Lower Breakeven: $94.28 (-5.7% move)
Upper Breakeven: $105.72 (5.7% move)

Implied Move: ±5.7% over 30 days

The "implied move" embedded in a straddle price represents the market's expectation of the stock's range. If you believe the stock will move more than this implied amount, you would buy the straddle. This implied move is a convenient way to interpret straddle prices: if a 30-day straddle costs 5% of the stock price, the market is implying that the stock will move approximately 5% in one direction or the other over that period. If you expect the stock to move 8% due to an upcoming catalyst, the straddle looks attractively priced.

Short Volatility Strategies

Short volatility strategies profit when implied volatility exceeds realized volatility. These strategies collect premium from option buyers who overpay for protection. Common approaches include:

  • Selling straddles or strangles: Collect premium, profit if stock stays range-bound
  • Iron condors: Sell strangle, buy further OTM options for protection
  • Covered calls or cash-secured puts: Systematic premium collection

For a short strangle involving a put with strike KPK_P and a call with strike KCK_C (where KP<KCK_P < K_C), the P&L at expiration is:

P&L=(Ppremium+Cpremium)−max⁡(KP−ST,0)−max⁡(ST−KC,0)\text{P\&L} = (P_{\text{premium}} + C_{\text{premium}}) - \max(K_P - S_T, 0) - \max(S_T - K_C, 0)

where:

  • P&L\text{P\&L}: profit or loss at expiration
  • PpremiumP_{\text{premium}}: premium received for the put
  • CpremiumC_{\text{premium}}: premium received for the call
  • KPK_P: put strike price
  • KCK_C: call strike price
  • STS_T: stock price at expiration

The formula reveals the risk-reward structure of a short strangle. The first term represents the premium collected upfront, which is the maximum possible profit. This maximum profit is realized if the stock finishes anywhere between the two strikes at expiration, in which case both options expire worthless and you keep the entire premium. The second and third terms represent potential losses: if the stock falls below the put strike or rises above the call strike, you must pay out the intrinsic value of the in-the-money option. Because there is no upper limit to how high the stock can rise and the stock can fall to zero, the potential losses on a short strangle are theoretically unlimited on the upside and substantial on the downside.

The key risk of short volatility strategies is their asymmetric payoff profile. Gains are limited to the premium collected, while losses can be substantial during volatility spikes.

In[19]:
Code
def short_strangle_payoff(S_T, K_put, K_call, put_premium, call_premium):
    """Calculate short strangle P&L at expiration."""
    put_payoff = put_premium - np.maximum(K_put - S_T, 0)
    call_payoff = call_premium - np.maximum(S_T - K_call, 0)
    return put_payoff + call_payoff


# Short strangle parameters
K_put = 95
K_call = 105
put_price = black_scholes_put(S, K_put, T, r, sigma)
call_price_otm, _, _ = black_scholes_call(S, K_call, T, r, sigma)
strangle_premium = put_price + call_price_otm

# Calculate payoff
strangle_pnl = short_strangle_payoff(
    S_range, K_put, K_call, put_price, call_price_otm
)
Out[20]:
Visualization
Short-strangle payoff is flat and positive between the 95-dollar put and 105-dollar call strikes, then declines beyond either breakeven.
Short strangle payoff profile with out-of-the-money strikes at 95 and 105. The strategy earns a maximum profit equal to the premium collected if the stock price stays between the strikes, but faces rapidly increasing losses if the price breaks through the breakeven points.

The payoff diagram highlights the defined profit zone between the strikes and the unlimited risk beyond the breakeven points. This structure benefits from time decay but requires the underlying asset to remain within a specific range. The flat profit region in the middle represents the comfort zone for short volatility traders: as long as the stock stays within this range, they earn the full premium. But the steep losses beyond the breakeven points illustrate why risk management is so critical for these strategies.

Building a Volatility Forecast

To succeed at volatility arbitrage, you must predict future realized volatility using one of several approaches:

Historical volatility models estimate future volatility based on past returns. As we covered in Part III, Chapter 18, GARCH models capture volatility clustering and mean reversion. The key insight behind GARCH is that volatility tends to be persistent: high volatility days tend to be followed by high volatility days, and low volatility periods tend to persist as well. By modeling this persistence explicitly, GARCH can provide more accurate short-term volatility forecasts than simple historical measures.

In[21]:
Code
def garch_forecast(returns, omega=0.00001, alpha=0.1, beta=0.85, n_ahead=21):
    """
    Simple GARCH(1,1) variance forecast.

    Variance forecast formula:
    σ²(t+1) = ω + α·ε²(t) + β·σ²(t)
    """
    # Initialize variance
    var = returns.var()

    # Update variance through history
    for ret in returns:
        var = omega + alpha * ret**2 + beta * var

    # Forecast future variance
    long_run_var = omega / (1 - alpha - beta)
    forecasts = []

    for h in range(1, n_ahead + 1):
        # Multi-step forecast converges to long-run variance
        forecast = long_run_var + (alpha + beta) ** (h - 1) * (
            var - long_run_var
        )
        forecasts.append(forecast)

    # Convert to annualized volatility
    avg_var = np.mean(forecasts)
    return np.sqrt(avg_var * 252)


# Generate sample returns
np.random.seed(42)
sample_returns = np.random.normal(0, 0.015, 100)

# Add a volatility cluster
sample_returns[50:60] = np.random.normal(0, 0.03, 10)

garch_vol = garch_forecast(sample_returns)
historical_vol = np.std(sample_returns[-21:]) * np.sqrt(252)
Out[22]:
Console
GARCH(1,1) 21-day Volatility Forecast: 19.7%
21-day Historical Volatility: 18.5%

The GARCH forecast differs from the simple historical volatility because it accounts for the recent volatility cluster in the data. By weighing recent observations more heavily and incorporating mean reversion, GARCH models often provide more responsive forecasts than rolling standard deviations. The model recognizes that the recent spike in volatility is likely to persist somewhat into the future, even as it gradually decays back toward the long-run average. This forward-looking adjustment makes GARCH particularly valuable for short-term volatility trading decisions.

Implied volatility models use the term structure and skew of implied volatility to forecast. If short-term implied volatility is elevated relative to longer-term volatility, mean reversion suggests it may decline.

Fundamental factors such as earnings announcements, economic data releases, and geopolitical events can inform volatility expectations.