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

9.4 KiB

No description has been provided for this image

This code retrieves option chains for a given ticker symbol using Yahoo Finance, then processes and visualizes the data. It fetches call and put options, calculates days to expiration, and filters based on implied volatility. The code further segments the options data by expiration date and strike price to plot implied volatility skew and term structure. Finally, it creates a 3D surface plot to visualize implied volatility across different strikes and expirations. This is useful for options analysis and trading strategies.

In [ ]:
import numpy as np
import pandas as pd
import yfinance as yf
import datetime as dt
In [ ]:
import matplotlib.pyplot as plt

Define a function to retrieve and process option chains for a given ticker symbol

In [ ]:
def option_chains(ticker):
    """Retrieve and process option chains.
    
    This function fetches option chains from Yahoo Finance for a given ticker symbol, 
    processes the data, and calculates days to expiration for each option.
    
    Parameters
    ----------
    ticker : str
        The ticker symbol of the asset.
    
    Returns
    -------
    chains : pd.DataFrame
        DataFrame containing processed option chains with days to expiration.
    """
    
    # Fetch option chains from Yahoo Finance for the given ticker
    asset = yf.Ticker(ticker)
    expirations = asset.options
    
    chains = pd.DataFrame()
    
    for expiration in expirations:
        # Retrieve option chain for a specific expiration date
        opt = asset.option_chain(expiration)
        
        calls = opt.calls
        calls['optionType'] = "call"
        
        puts = opt.puts
        puts['optionType'] = "put"
        
        # Concatenate call and put options into a single DataFrame
        chain = pd.concat([calls, puts])
        chain['expiration'] = pd.to_datetime(expiration) + pd.DateOffset(hours=23, minutes=59, seconds=59)
        
        chains = pd.concat([chains, chain])
    
    # Calculate days to expiration for each option
    chains["daysToExpiration"] = (chains.expiration - dt.datetime.today()).dt.days + 1
    
    return chains

Retrieve the option chains for the SPY ticker symbol

In [ ]:
options = option_chains("SPY")

Filter the option chains to get only call options

In [ ]:
calls = options[options["optionType"] == "call"]

Select call options that expire on 2023-01-20

In [ ]:
calls_at_expiry = calls[calls["expiration"] == "2023-01-20 23:59:59"]

Filter out call options with low implied volatility

In [ ]:
filtered_calls_at_expiry = calls_at_expiry[calls_at_expiry.impliedVolatility >= 0.001]

Plot implied volatility skew for call options expiring on 2023-01-20

In [ ]:
filtered_calls_at_expiry[["strike", "impliedVolatility"]].set_index("strike").plot(
    title="Implied Volatility Skew", figsize=(7, 4)
)

Select options with a strike price of 400.0

In [ ]:
calls_at_strike = options[options["strike"] == 400.0]

Filter out options with low implied volatility

In [ ]:
filtered_calls_at_strike = calls_at_strike[calls_at_strike.impliedVolatility >= 0.001]

Plot implied volatility term structure for options with a strike price of 400.0

In [ ]:
filtered_calls_at_strike[["expiration", "impliedVolatility"]].set_index("expiration").plot(
    title="Implied Volatility Term Structure", figsize=(7, 4)
)

Pivot the DataFrame to prepare data for a 3D surface plot

In [ ]:
surface = (
    calls[['daysToExpiration', 'strike', 'impliedVolatility']]
    .pivot_table(values='impliedVolatility', index='strike', columns='daysToExpiration')
    .dropna()
)

Create a figure object for the 3D plot

In [ ]:
fig = plt.figure(figsize=(10, 8))

Add a 3D subplot

In [ ]:
ax = fig.add_subplot(111, projection='3d')

Prepare coordinate matrices for the 3D plot

In [ ]:
x, y, z = surface.columns.values, surface.index.values, surface.values
X, Y = np.meshgrid(x, y)

Set axis labels and title

In [ ]:
ax.set_xlabel('Days to expiration')
ax.set_ylabel('Strike price')
ax.set_zlabel('Implied volatility')
ax.set_title('Call implied volatility surface')

Plot the 3D surface of implied volatility

In [ ]:
ax.plot_surface(X, Y, z)

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.