July cohort is now open: How to secure your spot:

Demystifying volatility swaps

Volatility can wreak havoc on your portfolio. Understanding and managing this risk is the number one job for any serious investor. Many use options or futures to hedge against volatility, but these approaches can fall short and leave portfolios exposed during extreme market conditions.

This is where volatility swaps can help

These derivatives traders hedge against volatility in a more targeted and effective way. However, pricing and using volatility swaps can be mysterious. Something only professionals with advanced modeling techniques can understand.

Not anymore.

By reading today’s newsletter, you’ll value a volatility swap on Apple using October expiration call options using QuantLib.

Let’s go!

Demystifying volatility swaps (easily value one on Apple with Python)

Volatility swaps give traders a way to directly trade market volatility. Volatility swaps let investors to gain exposure to the volatility of an asset without actually owning the asset itself.

This is useful for managing risk during extreme market conditions.

The pricing of volatility swaps involves setting strike volatility based on implied volatility. Then, we calculate the payoff based on the difference between the realized and the strike.

In practice, volatility swaps provide a more precise hedging tool. This is especially true during periods of high market uncertainty. They offer better liquidity and reduced transaction costs compared to other hedging tools.

By using volatility swaps, you can hedge against market volatility and enhance your trading performance.

Let’s see how they work.

Imports and set up

Import the libraries we’ll use for the analysis and set up the basic parameters for the volatility swap.

import QuantLib as ql
import numpy as np
import pandas as pd

notional = 100_000
volatility_strike = 0.2438
days_to_maturity = 148
observation_period = 252

risk_free_rate = 0.0525
dividend_yield = 0.0052
spot_price = 188.64

The swap requires a notional amount, a strike price, number of days to maturity, and number of trading days in a year. We also define the market data, such as risk-free rate, dividend yield, and the initial price of the underlying asset.

Set up QuantLib for our swap

Create QuantLib objects for the interest rate curve, the dividend yield curve, and the underlying asset price.

calendar = ql.NullCalendar()
day_count = ql.Actual360()

today = ql.Date().todaysDate()
ql.Settings.instance().evaluationDate = today

risk_free_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(today, risk_free_rate, day_count)
)

dividend_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(today, dividend_yield, day_count)
)

# Underlying asset price
spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))

This code initializes a calendar and day count convention, sets today’s date, and creates yield term structures for the risk-free rate and dividend yield. It also establishes a handle for the underlying asset’s spot price.

Compute implied volatility and simulate realized volatility

In our example, we’ll assume a European style exercise. You can change this to use American style exercise if you’d like. We use this valuation model to compute the implied volatility.

strike_price = 190
option_price = 11.05
expiration_date = today + ql.Period(days_to_maturity, ql.Days)

payoff = ql.PlainVanillaPayoff(ql.Option.Call, strike_price)
exercise = ql.EuropeanExercise(expiration_date)
european_option = ql.VanillaOption(payoff, exercise)

volatility_handle = ql.BlackVolTermStructureHandle(
    ql.BlackConstantVol(today, calendar, volatility_strike, day_count)
)

bsm_process = ql.BlackScholesMertonProcess(
    spot_handle, dividend_ts, risk_free_ts, volatility_handle
)

implied_volatility = european_option.impliedVolatility(
    option_price, bsm_process, 1e-4, 1000, 1e-8, 4.0
)

The code sets up a European call option for Apple with a strike price of $190 using the October 18th expiration. It constructs a Black-Scholes-Merton process with the given market data and volatility. Finally, it calculates the implied volatility from the market price of the option.

Now we need to simulate the underlying price paths to estimate future realized volatility. Use the geometric Brownian motion model to simulate the underlying asset’s price paths and calculate the realized volatility.

np.random.seed(42)

time_steps = observation_period
dt = 1 / observation_period

prices = np.zeros((time_steps + 1, 1))
prices[0] = spot_price

for t in range(1, time_steps + 1):
    z = np.random.normal(size=1)
    prices[t] = (
        prices[t-1] 
        * np.exp(
            (risk_free_rate - 0.5 * implied_volatility**2) * 
            dt + 
            implied_volatility * 
            np.sqrt(dt) * z
        )
    )

prices_df = pd.DataFrame(prices, columns=['Price'])

prices_df['Return'] = prices_df['Price'].pct_change().dropna()

realized_volatility = np.std(prices_df['Return']) * np.sqrt(observation_period)

This code simulates the price paths of Apple using a geometric Brownian motion. It initializes prices and calculates each subsequent price based on the risk-free rate, implied volatility, and a random shock. Finally, it calculates daily returns from these simulated prices and computes the realized volatility over the observation period.

Calculate the value of the volatility swap

The value of the volatility swap is the difference between the realized volatility and the strike volatility, scaled by the notional amount and the time to maturity.

time_to_maturity = days_to_maturity / observation_period

volatility_swap_value = (
    (realized_volatility - volatility_strike) * 
    notional * 
    np.sqrt(time_to_maturity)
)

print(f"Volatility Swap Value: ${volatility_swap_value:.2f}")

First we calculate the time to maturity by dividing the number of days to maturity by the number of trading days in a year. We then compute the value of the volatility swap by scaling the difference between realized volatility and the volatility strike by the notional amount and the square root of the time to maturity.

Your next steps

Try replacing the option parameters with those of another option contract to see how the volatility swap value changes.

After that, experiment by replacing the European exercise with an American exercise to understand its impact on the calculations. This will help you get a better understanding of how different factors influence the pricing of volatility swaps.