DEV Community

Dmitry Romanoff
Dmitry Romanoff

Posted on

Pulling Options Data with Python and yFinance — and Saving it Like a Pro

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
Enter fullscreen mode Exit fullscreen mode

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.")
Enter fullscreen mode Exit fullscreen mode

▶️ Example Usage

fetch_and_save_options("LLY", "2025-06-06")
Enter fullscreen mode Exit fullscreen mode

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. Use stock.options to list available dates.
  • The output uses U.S. Eastern Time for last trade timestamps.
  • Missing data (like volume or implied 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)