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)