If you’re diving into financial data analysis with Python, chances are you’ve come across yfinance. This handy library lets you tap into Yahoo Finance data with just a few lines of code. In this post, we’ll explore how to extract options chain data for a stock, then save it cleanly to CSV files — one for calls, one for puts.
Whether you're analyzing volatility, building trading strategies, or just curious, having structured access to options data is gold. So let’s jump into the code!
🔧 Prerequisites
You'll need the yfinance
library, which you can install with:
pip install yfinance
We're also using Python’s built-in csv
and datetime
modules — no extra dependencies there.
📦 The Goal
We’ll write a function that:
- Accepts a stock ticker and expiration date,
- Retrieves the options chain for that date (calls & puts),
- Formats the data neatly,
- Writes the results to two CSV files:
<symbol>_calls.csv
and<symbol>_puts.csv
.
🧠 The Code
import yfinance as yf
import csv
from datetime import datetime
def fetch_and_save_options(symbol, expiration_date):
stock = yf.Ticker(symbol)
if expiration_date not in stock.options:
print(f"Invalid expiration date. Available options dates: {stock.options}")
return
options = stock.option_chain(expiration_date)
calls_data = []
puts_data = []
for call in options.calls.itertuples():
call_data = {
"Contract Name": call.contractSymbol,
"Last Trade Date (EDT)": call.lastTradeDate.strftime("%m/%d/%Y %I:%M %p") if call.lastTradeDate else "",
"Strike": call.strike,
"Last Price": call.lastPrice,
"Bid": call.bid,
"Ask": call.ask,
"Change": call.change,
"% Change": call.percentChange,
"Volume": call.volume if call.volume is not None else "-",
"Open Interest": call.openInterest if call.openInterest is not None else "-",
"Implied Volatility": f"{call.impliedVolatility * 100:.2f}%" if call.impliedVolatility else "-"
}
calls_data.append(call_data)
for put in options.puts.itertuples():
put_data = {
"Contract Name": put.contractSymbol,
"Last Trade Date (EDT)": put.lastTradeDate.strftime("%m/%d/%Y %I:%M %p") if put.lastTradeDate else "",
"Strike": put.strike,
"Last Price": put.lastPrice,
"Bid": put.bid,
"Ask": put.ask,
"Change": put.change,
"% Change": put.percentChange,
"Volume": put.volume if put.volume is not None else "-",
"Open Interest": put.openInterest if put.openInterest is not None else "-",
"Implied Volatility": f"{put.impliedVolatility * 100:.2f}%" if put.impliedVolatility else "-"
}
puts_data.append(put_data)
with open(f"{symbol}_calls.csv", mode="w", newline="") as file:
writer = csv.DictWriter(file, fieldnames=calls_data[0].keys())
writer.writeheader()
writer.writerows(calls_data)
with open(f"{symbol}_puts.csv", mode="w", newline="") as file:
writer = csv.DictWriter(file, fieldnames=puts_data[0].keys())
writer.writeheader()
writer.writerows(puts_data)
print(f"Options data for {symbol} on {expiration_date} saved to CSV files.")
▶️ Example Usage
fetch_and_save_options("LLY", "2025-06-06")
This will create:
-
LLY_calls.csv
– with detailed call options data -
LLY_puts.csv
– with detailed put options data
Each row contains:
- Contract symbol
- Last trade timestamp
- Strike price
- Bid/ask prices
- Volume, open interest
- Implied volatility
- And more!
⚠️ Notes & Tips
- Be sure the expiration date is in
YYYY-MM-DD
format and is valid for the symbol. Usestock.options
to list available dates. - The output uses U.S. Eastern Time for last trade timestamps.
- Missing data (like
volume
orimplied volatility
) is replaced with"-"
for cleaner output.
💡 Use Cases
- Options backtesting — pair this with historical data.
- Volatility screening — sort by IV or OI for trade ideas.
- Automated reporting — schedule daily runs via cron or Airflow.
🧵 Wrapping Up
With just a few lines of Python, you can gain powerful access to real-time options data using yfinance
. This script is a solid starting point for financial data exploration, quantitative research, or even building your own trading dashboard.
Top comments (0)