Collect Stock and Options Data Easily using Python and Ally Financial API — 3 Example Queries | by Eric Kleppen | Towards Data Science

For a period of my life, I was obsessed with financial markets and wanted to be a day trader. I worked nights, so it was easy to spend my mornings surrounded by computer monitors displaying everything from stocks, options, news and trade chat-rooms. Spoiler alert... I gave up on day trading, but not on investing. Ultimately, I learned that I loved analyzing data more than trading, and then I put my self on a path to learn data analysis and get into Data Science.
When I was exploring ways to collect stock and options data, I checked out the API offered by one of my brokers, Ally Financial. It was free to use and easy to code. This is the cheat-sheet I put together for using the Ally Financial API to collect the following:
Time and Sales for Stocks
Options Market Depth
Options Extended Quote
If you’re not familiar with an API, check out some of these resources. It is possible to automate trades through their API, but I never got that far into it. Explore all the functionality in their documentation.
www.ally.com
You can find the complete cheat sheet at the bottom of the article or on my GitHub!
github.com
On to the code!
Connecting to the API uses OAuth1. You can find a list of OAuth clients on the OAuth site here. I use the OAuth library requests_oauthlib. Use pip install requests-oauthlib as needed.
import requestsfrom requests_oauthlib import OAuth1from config import (api_key, secret, oath_token, oath_secret)import pandas as pdimport sqlalchemyimport numpy as npimport sqlite3from sqlite3 import Errorimport matplotlib.pyplot as pltimport datetime as dt
Notice I use a config file to import api_key, secret, oath_token, oath_secret. That way I don’t need to include those personal tokens in the code.
#authentication auth = OAuth1(api_key, secret, oath_token, oath_secret)
I pass the imported tokens to OAuth1. This will be used when we make the request to the API.
This API call will return time and sales quote data based on a symbol passed as a query parameter. For a list of all the query parameters, check out the documentation. The example URL consists of the base url, api route, and query.
Base url: https://api.tradeking.com/Route: v1/market/timesales.jsonQuery: ?symbols=MSFT&startdate=2019–05–03&interval=1min
Documentation: https://www.ally.com/api/invest/documentation/market-timesales-get/
#url call to the apiurl = 'https://api.tradeking.com/v1/market/timesales.json?symbols=MSFT&startdate=2019-05-03&interval=1min'#api requestresponse = requests.get(url, auth = auth).json()
Notice I pass the URL and oAuth values into requests and return the response as json. This is an example of the response:
I put the quote data into a Panda’s DataFrame and format the data types.
#send to data frame and format data typesdf = pd.DataFrame(response["response"]["quotes"]["quote"])df = df.sort_values(['datetime'], ascending = False)df['date'] = pd.to_datetime(df['date'])df['datetime'] = pd.to_datetime(df['datetime'],  utc=False).dt.tz_convert('US/Central')df['hi'] = df["hi"].astype(float)df['incr_vol'] = df["incr_vl"].astype(float)df['last'] = df["last"].astype(float)df['lo'] = df["lo"].astype(float)df['opn'] = df["opn"].astype(float)df['vl'] = df['vl'].astype(float)df.head()
The date time values need to be converted so they can be resampled. Resampling allows you to manipulate the frequency of a time series. According to the documentation, the Object must have a datetime-like index (DatetimeIndex, PeriodIndex, or TimedeltaIndex), or pass datetime-like values to the on or level keyword.
#resample the time value to be greater than 1 min as needed. Example: 30 min resample for last pricedf.set_index(df['datetime'], inplace = True)df.head()df_resample30 = df.resample(rule = '30min', label = 'right').last()df_resample30.head()
Notice the datetime increments by 30 minutes instead of 1 minute after the resampling.
This api call provides market depth for options. This call will return the full list of available option strikes for a given symbol. While this request type is GET, POST can also be used and is recommended for longer queries.
Documentation: https://www.ally.com/api/invest/documentation/market-options-search-get-post/
Base url: https://api.tradeking.com/Route: v1/market/timesales.jsonQuery: ?symbol=MSFT&query=xyear-eq%3A2019%20AND%20xmonth-eq%3A06%20AND%20strikeprice-eq%3A140
expiration year equals 2019:xyear-eq%3A 2019
and:%20AND%20
expiration month equals 06:xmonth-eq%3A 06
and strike price equals 140:%20AND%20 strikeprice -eq%3A 140
lt : less thangt : greater thangte : greater than or equal tolte : less than or equal toeq : equal to
url = 'https://api.tradeking.com/v1/market/options/search.json?symbol=MSFT&query=xyear-eq%3A2019%20AND%20xmonth-eq%3A06%20AND%20strikeprice-eq%3A140'#api callresponse = requests.get(url, auth = auth).json()#load the response into the dataframedf = pd.DataFrame(response["response"]["quotes"]["quote"])df
This route works for stocks, but this is an example of an option call since they are a bit more complex. This call will return quotes for a symbol or list of symbols passed as a query parameter.
Documentation: https://www.ally.com/api/invest/documentation/market-ext-quotes-get-post/Base url: https://api.tradeking.com/Route: v1/market/ext/quotes.jsonQuery: ?symbols=MSFT190607C00140000
Underlying symbol — MSFT2 digit expiration year — 192 digit expiration month — 062 digit expiration day — 07“C” for Call or “P” for Put — C8 digit strike price — 00140000Specify desired fields in the query as needed using fids:i.e. fids=ask,bid,vol
Although the naming convention has several components, it is fairly straight forward after a few examples. In the mean time, use the example image provided in the documentation or this cheat-sheet!
url = 'https://api.tradeking.com/v1/market/ext/quotes.json?symbols=MSFT190607C00140000'#api callresponse = requests.get(url, auth = auth).json()#load the response into the dataframedf = pd.DataFrame(response["response"]["quotes"]["quote"], index = [0])df
Using Pandas, it is easy to save the data to CSV or an SQL database. If you’re not familiar with SQLite, it is extremely easy to use. To quote the documentation:
SQLite is a C library that provides a lightweight disk-based database that doesn’t require a separate server process and allows accessing the database using a nonstandard variant of the SQL query language.
conn = sqlite3.connect('stockdata.sqlite')df.to_sql(table_name, conn)
Using these three queries, it is easy to start collecting stock and options data using the Ally Financial API. Putting the data into a Panda’s dataframe makes it easy to understand the JSON information and store the data as a CSV or SQLite file. If you want to explore other APIs for stock data, check out Alphavantage too.
Find the cheat sheet with documentation on my github!
import requestsfrom requests_oauthlib import OAuth1from config import (api_key, secret, oath_token, oath_secret)import pandas as pdimport sqlalchemyimport numpy as npimport sqlite3from sqlite3 import Errorimport matplotlib.pyplot as pltimport datetime as dt#authentication auth = OAuth1(api_key, secret, oath_token, oath_secret)#url url = 'https://api.tradeking.com/v1/market/timesales.json?symbols=MSFT&startdate=2019-05-03&interval=1min'#api requestresponse = requests.get(url, auth = auth).json()#send to data frame and format data typesdf = pd.DataFrame(response["response"]["quotes"]["quote"])df = df.sort_values(['datetime'], ascending = False)df['date'] = pd.to_datetime(df['date'])df['datetime'] = pd.to_datetime(df['datetime'],  utc=False).dt.tz_convert('US/Central')df['hi'] = df["hi"].astype(float)df['incr_vol'] = df["incr_vl"].astype(float)df['last'] = df["last"].astype(float)df['lo'] = df["lo"].astype(float)df['opn'] = df["opn"].astype(float)df['vl'] = df['vl'].astype(float)df.head()#resample the time value to be greater than 1 min as needed. Example: 30 min resample for last pricedf.set_index(df['datetime'], inplace = True)df.head()df_resample30 = df.resample(rule = '30min', label = 'right').last()df_resample30.head()#Options Search Exampleurl = 'https://api.tradeking.com/v1/market/options/search.json?symbol=MSFT&query=xyear-eq%3A2019%20AND%20xmonth-eq%3A06%20AND%20strikeprice-eq%3A140' response = requests.get(url, auth = auth).json()  df = pd.DataFrame(response["response"]["quotes"]["quote"]) df.head()#Extended Quote Exampleurl = 'https://api.tradeking.com/v1/market/ext/quotes.json?symbols=MSFT190607C00140000'response = requests.get(url, auth = auth).json()df = pd.DataFrame(response["response"]["quotes"]["quote"], index = [0])df.head()
If you enjoyed this, follow me on Medium for more
Get FULL ACCESS and help support my content by subscribing
Let’s connect on LinkedIn
Analyze Data using Python? Check out my website
— Eric Kleppen
Check out my other tutorials for more python and sql!