pythonloopsnestedscopingyfinance

Python yfinance - Pulling option chains for multiple tickers and all expirations per ticker


I'm trying to use yfinance to pull option chains per stock from a list of tickers and for all the available expirations per ticker.

So my code should loop over each ticker, get expiration dates, loop over each date, get options chain, then jump to next ticker and repeat.

The code below sometimes works fine, but not always, and especially as I add tickers it seems like variables get reassigned on each loop? - For example, by the time it gets to RKT the expiration dates for RKT look nothing like its actual expirations dates. It may happen on the first tickers or towards the end, or randomly, but there's always some tickers with wrong expirations, especially as the list grows.

This is my first go at it and tried to use similar examples to debug, but nothing worked or I wasn't applying them correctly.

import yfinance as yf
import pandas as pd

yf.pdr_override()

stocklist =['DIS','GM','HD','BABA','AAPL','APPS','PLTR','EXPR','MARA','BABA','SPCE','GME','RIOT','BB','RKT','HD','NIO']
optionsX = pd.DataFrame()

for x in stocklist:
    print(x)
    tk = yf.Ticker(x)  
    exps = tk.options  #expiration dates
    try:
        for e in exps:
            print(e)
            opt = tk.option_chain(e)
            opt = pd.DataFrame().append(opt.calls).append(opt.puts)
            opt['expirationDate'] = e
            opt['Symbol'] = x
            optionsX = optionsX.append(opt, ignore_index=True)
    except:
        pass
optionsX

En example of an error: If I run the code as is, it seemingly runs fine and I get this for DIS:

    DIS
    2021-03-19
    2021-03-26
    2021-04-01
    2021-04-09
    2021-04-16
    2021-04-23
    ...

But if I try adding another ticker to the list, for example TSLA, I now get this for DIS:

   DIS
   2021-03-19
   2021-04-16
   2021-06-18
   2022-01-21
   2022-06-17
   2023-01-20

It doesn't have to happen to the first ticker on the list, and not exactly sure what triggers the error, but usually the longer the list of tickers, the more inconsistencies with the expiration dates. - Any help is appreciated.


Solution

  • I can't find anything wrong with your code - it kind of seems like the data from that endpoint is changing, which is why you're getting different results from each request.

    I can offer an alternative solution though (it's a bit faster and much easier to implement). It's a package called yahooquery. Disclaimer: I'm the author of the package.

    from yahooquery import Ticker
    
    stocklist =['DIS','GM','HD','BABA','AAPL','APPS','PLTR','EXPR','MARA','BABA','SPCE','GME','RIOT','BB','RKT','HD','NIO']
    
    t = Ticker(stocklist, asynchronous=True)
    
    df = t.option_chain
    
    df.columns
    Index(['contractSymbol', 'strike', 'currency', 'lastPrice', 'change',
           'percentChange', 'volume', 'openInterest', 'bid', 'ask', 'contractSize',
           'lastTradeDate', 'impliedVolatility', 'inTheMoney'],
          dtype='object')
    
    df.index.unique(level=0)
    Index(['AAPL', 'APPS', 'BABA', 'BB', 'DIS', 'EXPR', 'GM', 'GME', 'HD', 'MARA',
           'NIO', 'PLTR', 'RIOT', 'RKT', 'SPCE'],
          dtype='object', name='symbol')
    
    df.shape
    (22360, 14)