Volatility Trading and Arbitrage Strategies › Variance Swaps
Quantitative FinanceAll chapters Volatility Trading and Arbitrage Strategies › Variance SwapsOne section · Sections in this chapter9 / 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
Variance swaps are derivatives that provide pure exposure to realized variance, making them a cleaner instrument for volatility trading than delta-hedged options. Unlike options, which have path-dependent Greeks that require continuous hedging, variance swaps pay off directly based on the total realized variance over their life. This simplicity makes them attractive for you if you want volatility exposure without the operational complexity of dynamic hedging.
Structure and Payoff
A variance swap is a forward contract on realized variance. At maturity, the payoff is:
where:
- : payment received at maturity
- : variance notional (typically quoted as vega notional divided by )
- : annualized realized variance over the swap's life
- : variance strike (typically expressed as volatility: )
The payoff formula is simple. You receive a payment proportional to the difference between actual realized variance and a predetermined strike level. If the market is more volatile than the strike implies, you profit. If the market is calmer than expected, you pay the seller. Unlike options, there is no optionality here: the trade settles purely based on what happens to variance, with no path dependence in terms of when or how the moves occur.
The realized variance is calculated from daily log returns:
where:
- : number of observation days
- : price of the asset on day
- : price of the asset on day
- : annualization factor (assuming trading days)
Note that this formula uses the sum of squared returns directly, not the variance around the mean. This is the standard market convention and ensures the calculation is path-dependent and captures all price movements. The distinction matters: by using squared returns rather than variance around the mean, the calculation captures both the variance and any drift in the returns. This convention means that a market that trends strongly in one direction will register higher "realized variance" than one that fluctuates around a stable level, even if the two have identical standard deviations. This feature makes variance swaps sensitive to all price movements, not just deviations from trend.
def variance_swap_realized(prices):
"""Calculate realized variance for a variance swap."""
log_returns = np.diff(np.log(prices))
n = len(log_returns)
realized_var = (252 / n) * np.sum(log_returns**2)
return realized_var
def variance_swap_payoff(prices, strike_vol, vega_notional):
"""
Calculate variance swap payoff.
Parameters:
- prices: Array of daily prices
- strike_vol: Volatility strike (e.g., 0.20 for 20%)
- vega_notional: Notional amount per 1% move in volatility
"""
realized_var = variance_swap_realized(prices)
strike_var = strike_vol**2
realized_vol = np.sqrt(realized_var)
# Variance notional = vega_notional / (2 * strike_vol)
var_notional = vega_notional / (2 * strike_vol)
payoff = var_notional * (realized_var - strike_var)
return {
"realized_vol": realized_vol,
"strike_vol": strike_vol,
"realized_var": realized_var,
"strike_var": strike_var,
"var_notional": var_notional,
"payoff": payoff,
}
# Generate sample price paths
np.random.seed(42)
n_days = 30
# Low volatility regime
returns_low = np.random.normal(0, 0.012, n_days) # ~19% annualized
prices_low = 100 * np.exp(np.cumsum(returns_low))
prices_low = np.insert(prices_low, 0, 100)
# High volatility regime
returns_high = np.random.normal(0, 0.022, n_days) # ~35% annualized
prices_high = 100 * np.exp(np.cumsum(returns_high))
prices_high = np.insert(prices_high, 0, 100)
strike_vol = 0.25
vega_notional = 100000 # $100,000 per vol point
result_low = variance_swap_payoff(prices_low, strike_vol, vega_notional)
result_high = variance_swap_payoff(prices_high, strike_vol, vega_notional)Variance Swap Payoff Analysis ================================================== Strike Volatility: 25.0% Vega Notional: $100,000 Variance Notional: $200,000 Low Volatility Scenario: Realized Vol: 17.2% Long Variance Swap Payoff: $-6,560 High Volatility Scenario: Realized Vol: 32.2% Long Variance Swap Payoff: $8,301

The variance swap generates a positive payoff when realized volatility exceeds the strike volatility. Note that in the high volatility scenario, the payoff is substantial because the realized variance (volatility squared) increases quadratically, making the payout convex with respect to volatility moves. This convexity is a critical feature of variance swaps: a move from 25% to 35% volatility generates more profit than a move from 25% to 15% volatility generates loss, making variance swaps attractive instruments for long volatility positions.
Replication and Pricing
The variance swap strike is determined by a portfolio of options across all strikes. The theoretical result, derived by Demeterfi, Derman, Kamal, and Zou (1999), shows that variance can be replicated by a portfolio of options with weights inversely proportional to the square of the strike:
where:
- : variance strike
- : risk-free interest rate
- : time to expiration
- : forward price of the underlying asset
- : strike price
- : price of a put option with strike
- : price of a call option with strike
Variance exposure can be constructed from a portfolio of vanilla options. The key insight is that options at different strikes contribute differently to variance: lower strike options contribute more (because of the weighting) than higher strike options. This overweighting of low strikes reflects the fact that the logarithm function used in variance calculation is more sensitive to downward price moves than upward ones.
The formula splits the replication into two parts based on the forward price :
- : replicates variance using out-of-the-money puts for strikes below the forward price
- : replicates variance using out-of-the-money calls for strikes above the forward price
Using out-of-the-money options at each strike is a convention that minimizes the cost of maintaining the replicating portfolio, as OTM options have lower premiums than their in-the-money counterparts while providing the same exposure to variance.
In practice, this integral is approximated using available option strikes:
def price_variance_swap_strike(strikes, option_prices, is_call, S, r, T):
"""
Approximate variance swap strike using discrete option prices.
Uses out-of-the-money options: puts below forward, calls above.
"""
F = S * np.exp(r * T) # Forward price
# Sort strikes
sorted_idx = np.argsort(strikes)
strikes = strikes[sorted_idx]
option_prices = option_prices[sorted_idx]
is_call = is_call[sorted_idx]
variance = 0
for i in range(len(strikes)):
K = strikes[i]
price = option_prices[i]
# Use OTM options only
if K < F and not is_call[i]: # OTM put
# Calculate strike spacing for numerical integration
if i > 0:
dK = (strikes[i] - strikes[i - 1]) / 2
else:
dK = strikes[1] - strikes[0]
if i < len(strikes) - 1:
dK += (strikes[i + 1] - strikes[i]) / 2
variance += (2 / K**2) * price * dK
elif K >= F and is_call[i]: # OTM call
if i > 0:
dK = (strikes[i] - strikes[i - 1]) / 2
else:
dK = strikes[1] - strikes[0]
if i < len(strikes) - 1:
dK += (strikes[i + 1] - strikes[i]) / 2
variance += (2 / K**2) * price * dK
# Annualize
variance = (np.exp(r * T) / T) * variance
return np.sqrt(variance)
# Example: Price variance swap from option chain
S = 100
r = 0.05
T = 30 / 365
sigma = 0.25
# Generate option chain
strikes = np.arange(85, 116, 2.5)
option_prices = []
is_call = []
for K in strikes:
if K < S: # Use put
price = black_scholes_put(S, K, T, r, sigma)
option_prices.append(price)
is_call.append(False)
else: # Use call
price, _, _ = black_scholes_call(S, K, T, r, sigma)
option_prices.append(price)
is_call.append(True)
option_prices = np.array(option_prices)
is_call = np.array(is_call)
fair_vol = price_variance_swap_strike(strikes, option_prices, is_call, S, r, T)Black-Scholes Implied Vol: 25.0% Variance Swap Fair Vol: 21.5% Difference: -3.54% (convexity adjustment)
The variance swap fair strike is typically slightly higher than at-the-money implied volatility due to the convexity in the variance payoff. This convexity adjustment compensates for the asymmetric exposure to volatility: realized variance of 40% versus 20% strike creates more P&L than 20% versus 20%. The convexity adjustment exists because variance is the square of volatility: a symmetrical distribution of volatility outcomes translates into an asymmetrical distribution of variance outcomes, with large volatility outcomes contributing disproportionately to expected variance.
Vega Notional Versus Variance Notional
Variance swaps can be quoted in two ways:
Variance notional (): The dollar amount paid per point of variance. A variance notional of $1,000 pays $1,000 for each 0.0001 (1 bp) difference in variance.
Vega notional: The approximate P&L for a 1 percentage point change in volatility. For a vega notional of $100,000, if volatility moves from 25% to 26%, the P&L is approximately $100,000.
The relationship between them is:
where:
- : variance notional
- : vega notional (P&L per 1 vol point change)
- : volatility strike
This conversion is approximate because the variance payoff is convex in volatility. The formula comes from taking the derivative of variance with respect to volatility at the strike level: the derivative of with respect to is , so at the strike volatility , a small change in volatility creates a variance change of approximately times the volatility change. The vega notional convention makes it easier for you to think in terms of volatility points, which are more intuitive than variance points.