If the code displayed in this article doesn't work for any reason, please email me.
In this article we will show how to get stock options data from Yahoo Finance. In order to do this we will use the Pandas Datareader package. You can find installation steps here.
It is also worth noting that options data bid/ ask prices will only be available during trading hours 9.30am ET - 4pm ET and also bear in mind that the data is on a short delay of approximately 15 minutes.
With that said let's begin and take a look at some options data. Import the following packages and execute the script to get options data for Facebook (FB).
import pandas as pd
import pandas_datareader.data as web
import numpy as np
FB = web.YahooOptions('FB')
Now that we have an options object we can use some of the built in methods to get data.
Show Available Expiries
The options object has a nice built in property that allows us to view the expiries available for the given stock option. It is also worth nothing here that the larger stocks will have more expiries since they are more widely traded.
for exp in FB.expiry_dates:
print(exp.isoformat())
#2020-12-11
#2020-12-18
#2020-12-24
#2020-12-31
#2021-01-08
#2021-01-15
#2021-02-19
#2021-03-19
#2021-06-18
#2021-07-16
#2021-09-17
#2022-01-21
#2022-06-17
#2022-09-16
#2023-01-20
#2026-02-21
Getting Call & Put Option Data.
We can get data for call options that expiry on a certain date, along with filtering by the month of expiry. Let's first check out the default call for this function.
calls = FB.get_call_data()
calls
So viewing the expiries it seems that the default is for this function call is to return the nearest expiration.
Last ... JSON
Strike Expiry Type Symbol ...
135.0 2020-12-11 call FB201211C00135000 150.08 ... {'contractSymbol': 'FB201211C00135000', 'strik...
185.0 2020-12-11 call FB201211C00185000 92.95 ... {'contractSymbol': 'FB201211C00185000', 'strik...
190.0 2020-12-11 call FB201211C00190000 93.75 ... {'contractSymbol': 'FB201211C00190000', 'strik...
195.0 2020-12-11 call FB201211C00195000 89.00 ... {'contractSymbol': 'FB201211C00195000', 'strik...
200.0 2020-12-11 call FB201211C00200000 79.65 ... {'contractSymbol': 'FB201211C00200000', 'strik...
... ... ...
395.0 2020-12-11 call FB201211C00395000 0.08 ... {'contractSymbol': 'FB201211C00395000', 'strik...
400.0 2020-12-11 call FB201211C00400000 0.23 ... {'contractSymbol': 'FB201211C00400000', 'strik...
405.0 2020-12-11 call FB201211C00405000 0.32 ... {'contractSymbol': 'FB201211C00405000', 'strik...
410.0 2020-12-11 call FB201211C00410000 0.07 ... {'contractSymbol': 'FB201211C00410000', 'strik...
425.0 2020-12-11 call FB201211C00425000 0.06 ... {'contractSymbol': 'FB201211C00425000', 'strik...
[62 rows x 15 columns]
We can also pass in arguments to the get_call_data method to get call options that expire on a certain month. To do this all we need to do is pass in a month and year argument.
FB.get_call_data(month =2 , year = 2021)
#Strike Expiry Type Symbol ...
#125.0 2021-02-19 call FB210219C00125000 152.35 ... {'contractSymbol': 'FB210219C00125000', 'strik...
#130.0 2021-02-19 call FB210219C00130000 156.25 ... {'contractSymbol': 'FB210219C00130000', 'strik...
#135.0 2021-02-19 call FB210219C00135000 140.00 ... {'contractSymbol': 'FB210219C00135000', 'strik...
#140.0 2021-02-19 call FB210219C00140000 121.68 ... {'contractSymbol': 'FB210219C00140000', 'strik...
#145.0 2021-02-19 call FB210219C00145000 130.65 ... {'contractSymbol': 'FB210219C00145000', 'strik...
Alternatively we can pass in an expiry argument or list of expiries. Below we show how to download every call option at all expiries, we make use of the property we mentioned at the beginning of the document. Notice that this returns a MultiIndex dataframe. To change it to a regular index we can use the reset index command.
allcalls = FB.get_call_data(expiry= FB.expiry_dates)
allcalls.index
#MultiIndex([( 5.0, '2021-01-15', 'call', 'FB210115C00005000'),
# ( 5.0, '2021-03-19', 'call', 'FB210319C00005000'),
# ( 5.0, '2021-06-18', 'call', 'FB210618C00005000'),
# ( 5.0, '2022-01-21', 'call', 'FB220121C00005000'),
# ( 10.0, '2021-01-15', 'call', 'FB210115C00010000'),
# ( 10.0, '2021-03-19', 'call', 'FB210319C00010000'),
# ( 10.0, '2021-06-18', 'call', 'FB210618C00010000'),
# ( 10.0, '2022-01-21', 'call', 'FB220121C00010000'),
# ( 15.0, '2021-01-15', 'call', 'FB210115C00015000'),
# ( 15.0, '2021-03-19', 'call', 'FB210319C00015000'),
allcalls.reset_index(inplace=True)
We can use the exact same command for getting put options, get replace get_call_data with get_put_data and everything else is exactlly the same.
Get all Options Data
It is very easy to get all options data from the Yahoo Finance api, in this seciton we will also show how to create a the mid-price for an option, which we will use in future articles on pricing and volatility. Again this returns a MultiIndex dataframe, here we reset the index as it is easier to work with in the regular format.
alloptions = FB.get_all_data()
alloptions.reset_index(inplace=True)
alloptions['mid_price'] = (alloptions.Ask + alloptions.Bid) / 2
This dataframe will have the following columns. Below we give a short description of each column along with the datatype.
Full Python Code
import pandas as pd
import pandas_datareader.data as web
import numpy as np
FB = web.YahooOptions('FB')
#showing available expiries
for exp in FB.expiry_dates:
print(exp.isoformat())
# get call data
calls = FB.get_call_data()
calls
#get put data
puts = FB.get_put_data()
puts
#get call data based on specific expiry
FB.get_call_data(month =2 , year = 2021)
# getting all call data, can also pass in a datetime to the expiry below
allcalls = FB.get_call_data(expiry= FB.expiry_dates)
#notice index is in multiindex
allcalls.index
#changing to regular index
allcalls.reset_index(inplace=True)
#get all available data for puts and calls at every expiration
alloptions = FB.get_all_data()
alloptions.reset_index(inplace=True)
# perform calculate on the data.
alloptions['mid_price'] = (alloptions.Ask - alloptions.Bid) / 2