Files
strategy-lab/to_explore/pyquantnews/97_VolatilitySwaps.ipynb
David Brazda e3da60c647 daily update
2024-10-21 20:57:56 +02:00

11 KiB

No description has been provided for this image

This code calculates the implied and realized volatility of an asset, and evaluates the payoff of a volatility swap. It uses QuantLib to set up financial instruments and yield curves, and NumPy and Pandas for simulations and calculations. First, it calculates the implied volatility from the market price of a European option using the Black-Scholes model. Then, it simulates asset price paths to compute realized volatility. Finally, it calculates the value of a volatility swap based on these volatilities.

In [ ]:
import QuantLib as ql
import numpy as np
import pandas as pd

Define financial parameters such as notional amount, volatility strike, days to maturity, and observation period

In [ ]:
notional = 100_000 
volatility_strike = 0.2438
days_to_maturity = 148
observation_period = 252

Define additional financial parameters such as risk-free rate, dividend yield, and current spot price

In [ ]:
risk_free_rate = 0.0525
dividend_yield = 0.0052
spot_price = 188.64

Create calendar and day count convention objects for use in QuantLib calculations

In [ ]:
calendar = ql.NullCalendar()
day_count = ql.Actual360()

Set today's date and evaluation date in QuantLib

In [ ]:
today = ql.Date().todaysDate()
ql.Settings.instance().evaluationDate = today

Create the risk-free rate term structure handle using a flat forward curve

In [ ]:
risk_free_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(today, risk_free_rate, day_count)
)

Create the dividend yield term structure handle using a flat forward curve

In [ ]:
dividend_ts = ql.YieldTermStructureHandle(
    ql.FlatForward(today, dividend_yield, day_count)
)

Create the spot price handle using a simple quote

In [ ]:
spot_handle = ql.QuoteHandle(ql.SimpleQuote(spot_price))

Define parameters for the European option including strike price, market price, and expiration date

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

Set up the option with a plain vanilla payoff and European exercise

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

Set up the volatility structure with an initial guess for implied volatility

In [ ]:
volatility_handle = ql.BlackVolTermStructureHandle(
    ql.BlackConstantVol(today, calendar, volatility_strike, day_count)
)

Use the Black-Scholes-Merton process for option pricing

In [ ]:
bsm_process = ql.BlackScholesMertonProcess(
    spot_handle, dividend_ts, risk_free_ts, volatility_handle
)

Calculate the implied volatility from the market price of the option

In [ ]:
implied_volatility = european_option.impliedVolatility(
    option_price, bsm_process, 1e-4, 1000, 1e-8, 4.0
)
In [ ]:
print(f"Implied Volatility: {implied_volatility:.4f}")

Set the random seed for reproducibility and define simulation parameters

In [ ]:
np.random.seed(42)
time_steps = observation_period
dt = 1 / observation_period

Initialize an array to store simulated asset prices and set the initial price

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

Simulate asset price paths using a geometric Brownian motion model

In [ ]:
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
        )
    )

Convert the simulated prices to a pandas DataFrame for further analysis

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

Calculate daily returns from the simulated prices

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

Calculate realized volatility from the daily returns

In [ ]:
realized_volatility = np.std(prices_df['Return']) * np.sqrt(observation_period)
In [ ]:
print(f"Realized Volatility: {realized_volatility:.4f}")

Calculate the time to maturity in years

In [ ]:
time_to_maturity = days_to_maturity / observation_period

Calculate the payoff of the volatility swap based on realized and strike volatility

In [ ]:
volatility_swap_value = (
    (realized_volatility - volatility_strike) * 
    notional * 
    np.sqrt(time_to_maturity)
)
In [ ]:
print(f"Volatility Swap Value: ${volatility_swap_value:.2f}")

PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk.