Python Script for Calculating Volatility Skew
Analyzing implied volatility using Yahoo Finance data for options
Highlights
- Data Extraction: Utilize libraries such as yfinance or yahoo_fin to retrieve options data.
- Data Processing: Combine and filter calls and puts to extract implied volatility for each expiration date.
- Simplified Visualization: Plot volatility skew per expiration date using matplotlib to observe market trends.
Overview
This guide presents a detailed Python script that retrieves the option chain data for a specified stock from Yahoo Finance and calculates the implied volatility skew for each expiration date. While Bloomberg Financial data requires a subscription and proprietary API access, Yahoo Finance provides an accessible alternative using libraries such as yfinance and yahoo_fin. The script outlined below fetches the option chain data, processes both calls and puts, computes the skew, and visualizes the results using matplotlib.
Script Structure
1. Environment Setup and Library Installation
Before running the script, ensure that the following libraries are installed via pip:
- yfinance
- pandas
- numpy
- matplotlib
Installation command:
# Install required libraries
pip install yfinance pandas numpy matplotlib
2. Fetching Option Chain Data from Yahoo Finance
The script uses the yfinance library to fetch the option chain data for the target stock. The function retrieves all available expiration dates and their corresponding options data. Both calls and puts are combined, and a filtering process ensures that only realistic implied volatility values are used in analysis.
3. Calculating the Volatility Skew
Volatility skew refers to the variation of implied volatility across different strike prices. For each expiration date, the script calculates various metrics such as minimum, maximum, mean, and median implied volatility. Additionally, it computes the volatility skew overall by examining the differences in these implied volatility values as the strikes increase.
4. Visualizing the Results
The matplotlib library is used to generate line plots that demonstrate the volatility skew for each expiration date. By plotting the implied volatility against strike prices for both calls and puts separately, users can visually confirm the patterns and potential anomalies in market pricing.
Python Script Implementation
Below is the complete Python script that achieves the objectives described:
# Import necessary libraries
import yfinance as yf # For retrieving financial data from Yahoo Finance
import pandas as pd # For data manipulation
import numpy as np # For numerical operations
import matplotlib.pyplot as plt # For plotting
def fetch_option_chain(ticker):
"""
Fetch the option chain data for the given ticker using yfinance.
This function returns a dictionary with expiration dates as keys and option data as values.
"""
# Create a Ticker object
asset = yf.Ticker(ticker)
expirations = asset.options # List of expiration dates
# Dictionary to store option chain data per expiration date
expiration_data = {}
for expiration in expirations:
# Retrieve the option chain for this expiration
chain = asset.option_chain(expiration)
calls = chain.calls
puts = chain.puts
# Add an indicator for option type
calls['optionType'] = 'call'
puts['optionType'] = 'put'
# Combine calls and puts data
combined = pd.concat([calls, puts])
expiration_data[expiration] = combined
return expiration_data
def calculate_volatility_skew(expiration_data):
"""
Calculate the volatility skew for each expiration date.
Returns a dictionary where each key is an expiration date associated with computed skew metrics.
"""
skew_metrics = {}
for expiration, data in expiration_data.items():
# Only consider entries with realistic implied volatility values
valid_data = data[data['impliedVolatility'] > 0.001]
# Group by option type if separate analysis for calls and puts is needed
calls = valid_data[valid_data['optionType'] == 'call']
puts = valid_data[valid_data['optionType'] == 'put']
# Calculate skew metrics for calls
if not calls.empty:
calls_sorted = calls.sort_values(by='strike')
call_skew_values = calls_sorted['impliedVolatility'].diff().dropna()
call_skew = {
'min_iv': calls_sorted['impliedVolatility'].min(),
'max_iv': calls_sorted['impliedVolatility'].max(),
'mean_iv': calls_sorted['impliedVolatility'].mean(),
'median_iv': calls_sorted['impliedVolatility'].median(),
'skew_diff': call_skew_values.mean() # average difference between successive iv values
}
else:
call_skew = None
# Calculate skew metrics for puts
if not puts.empty:
puts_sorted = puts.sort_values(by='strike')
put_skew_values = puts_sorted['impliedVolatility'].diff().dropna()
put_skew = {
'min_iv': puts_sorted['impliedVolatility'].min(),
'max_iv': puts_sorted['impliedVolatility'].max(),
'mean_iv': puts_sorted['impliedVolatility'].mean(),
'median_iv': puts_sorted['impliedVolatility'].median(),
'skew_diff': put_skew_values.mean()
}
else:
put_skew = None
# Combine metrics for each expiration
skew_metrics[expiration] = {
'calls': call_skew,
'puts': put_skew
}
return skew_metrics
def plot_volatility_skew(expiration_data, ticker):
"""
Plot the volatility skew for each expiration date.
Creates side-by-side plots for calls and puts if data exists.
"""
for expiration, data in expiration_data.items():
# Filter valid iv data
valid_data = data[data['impliedVolatility'] > 0.001]
calls = valid_data[valid_data['optionType'] == 'call']
puts = valid_data[valid_data['optionType'] == 'put']
fig, axes = plt.subplots(1, 2, figsize=(14, 6))
if not calls.empty:
calls = calls.sort_values(by='strike')
axes[0].plot(calls['strike'], calls['impliedVolatility'], marker='o', linestyle='-')
axes[0].set_title(f"Calls Volatility Skew - Exp: {expiration}")
axes[0].set_xlabel("Strike Price")
axes[0].set_ylabel("Implied Volatility")
axes[0].grid(True)
else:
axes[0].text(0.5, 0.5, "No call data available", horizontalalignment='center', verticalalignment='center')
if not puts.empty:
puts = puts.sort_values(by='strike')
axes[1].plot(puts['strike'], puts['impliedVolatility'], marker='o', linestyle='-', color='orange')
axes[1].set_title(f"Puts Volatility Skew - Exp: {expiration}")
axes[1].set_xlabel("Strike Price")
axes[1].set_ylabel("Implied Volatility")
axes[1].grid(True)
else:
axes[1].text(0.5, 0.5, "No put data available", horizontalalignment='center', verticalalignment='center')
fig.suptitle(f"{ticker} Options Volatility Skew for {expiration}", fontsize=16)
plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()
def display_skew_metrics_table(skew_metrics):
"""
Display the computed skew metrics for each expiration date in a formatted table.
"""
html_table = """
<table border="1" cellpadding="5" cellspacing="0">
<tr>
<th>Expiration Date</th>
<th>Option Type</th>
<th>Min IV</th>
<th>Max IV</th>
<th>Mean IV</th>
<th>Median IV</th>
<th>Avg IV Diff (Skew)</th>
</tr>
"""
for expiration, metrics in skew_metrics.items():
for option_type in ['calls', 'puts']:
data = metrics[option_type]
if data:
html_table += f"""
<tr>
<td>{expiration}</td>
<td>{option_type.title()}</td>
<td>{data['min_iv']:.4f}</td>
<td>{data['max_iv']:.4f}</td>
<td>{data['mean_iv']:.4f}</td>
<td>{data['median_iv']:.4f}</td>
<td>{data['skew_diff']:.4f}</td>
</tr>
"""
html_table += "</table>"
return html_table
def main():
# Specify the stock ticker
ticker = "AAPL" # you may change to any ticker of interest
# Fetch option chain data
option_data = fetch_option_chain(ticker)
# Calculate volatility skew metrics
skew_metrics = calculate_volatility_skew(option_data)
# Display computed metrics as a table in the console (or in a HTML context)
table_html = display_skew_metrics_table(skew_metrics)
print("Volatility Skew Metrics:")
print(table_html)
# Plot volatility skew for each expiration date
plot_volatility_skew(option_data, ticker)
if __name__ == "__main__":
main()
Discussion
Data Retrieval
This script leverages yfinance's flexible API to access option chain data by looping through every available expiration date. Data for both call and put options is combined after labeling, ensuring that the subsequent calculations can be performed uniformly. The filtering applied on the implied volatility values helps remove any minimum outliers that might result from data inconsistencies.
Skew Calculation and Analysis
The calculation of the skew primarily involves sorting the option chain data based on strike prices and computing first differences (i.e., the mean difference between successive implied volatility values). The provided metrics (min, max, mean, median, and average IV difference) offer a quantitative glance at the volatility behavior across the strike range.
Visualization
The visualization component, built with matplotlib, enables a clear comparative view of implied volatility trends for calls and puts across different expiration dates. Having side-by-side plots for calls and puts makes it easier to observe market sentiment and the evolution of the skew.
References
- yahoo_vol - GitHub
- Exploring Stock Data with Yahoo Finance Python Module - Medium
- Build an Implied Volatility Surface with Python - PyQuant News
- Volatility Skew and Options Overview - Options Education
- Volatility Skew in Options Trading - SoFi
Recommended Queries
Last updated March 9, 2025