Python x Tiingo — A Buttery Smooth API for Stock and Crypto Prices

post date
Oct 23, 2022
level 1 - intern
notion image

Technical skills covered

  • Retrieving historical price data for equity and crypto markets via tiingo api
The bedrock of any quantitative investment analysis is price data. In this post, we’re going to cover the steps for generate a simple api call to pull historical price data from my new favorite source — tiingo.
If you’re like me and don’t/no longer have access to a Bloomberg Terminal, you’ve likely also discovered that it is impossible to replicate. However, for the most mainstream data needs like equities, there are a number of free or reasonably priced options.
  • Yahoo Finance — The OG. Free and full history, but has had some access and stability issues over the years.
  • AlphaVantage — Also free, but easy to run hit rate limit.
  • IEX — Relatively inexpensive (~$9/month), but only 15 years of history.
  • Tiingo — Simple, stable, full history, and generous free tier.
This is not meant to be an exhaustive api comparison, more to just paint broad strokes of one person’s opinion of the major trade-offs and what led to choosing tiingo.

Enough with the chitter chatter, let’s get to the code.

First, we’ll need to register with tiingo and generate our api key. As always, we’ll want to practice good credential hygiene and store our key as an environment variable via the command line.
Next, we install the tiingo python package in our project’s environment. We’ll also make use of pandas, so install that now if needed.
pip install tiingo
Below we’ll break down the process of pulling end-of-day quotes for a ticker’s full history. Two api calls are used — one to pull the metadata for a ticker to determine when its data history begins, and the second to actually pull the time series data.

1. Package imports

import os import pandas as pd from tiingo import TiingoClient

2. Initiate TiingoClient object with your api key.

config = { "api_key":os.environ["TIINGO_API_KEY"], "session":True } client = TiingoClient(config)
The first line creates a simple config dictionary and pulls in our api key from the system’s environment variables. We set "session":True to reuse the same HTTP session for all api calls in the script and improve performance. There are many other possible parameters, but this is sufficient for our purposes. In a project pipeline, this config could be stored in json format in an inputs folder or as a constant in a custom python module/package. We then initialize the TiingoClient to authenticate and manage our session.

3. Ticker Metadata

tickers = ['QQQ', ['ethusd']] ticker_meta = client.get_ticker_metadata(tickers[0]) ticker_start = ticker_meta['startDate']
Note: Crypto pairs need to be passed to the api as lists.🤷🏼‍♂️ Further details can be found in the official api documentation.
Here we’ve passed our symbol to the get_ticker_metadata method on our client object. It returns some useful color on the security in question, but its primary value is the startDate parameter. We then assign this to ticker_start, which we will pass as a parameter in the next api call to pull the full history.
notion image
This is where the approach for traditional and crypto markets diverges. Tiingo has separate endpoint for crypto, so the methods applied to the client object and resulting metadata are slightly different
notion image

4a. Retrieve Time Series — Traditional Markets

First we’ll show the roundabout way. The get_ticker_price method takes the ticker, start/end dates, frequency, and format arguments. In this first example, the time series data is returned in json format, so we wrap it in a pd.DataFrame call and set the index to our date field.
ticker_hist = pd.DataFrame( client.get_ticker_price( tickers[0], startDate=ticker_start, frequency='daily', fmt='json' ) ).set_index('date')
But wait! We can eliminate the pandas step and end get the same result by calling the get_dataframe method.
Optionally, we can also convert the index from timestamp to a more simple date as we did before, since we’re only working at the daily frequency.
ticker_hist = client.get_dataframe(tickers[0], startDate=ticker_start) ticker_hist.index = pd.to_datetime(ticker_hist.index).tz_localize(None) ticker_hist.head()
notion image

4b. Retrieve Time Series — Crypto Markets

ticker_hist = client.get_crypto_price_history( tickers[1], resampleFreq='1day', startDate='2015-01-01', )
Since the crypto metadata does not provide a start date, we’ll have to hard code one. As we can see below, if you plug a date before the data starts for a particular token, it simply returns the full history from the first available date.
notion image
Since the data is returned in json format, we can wrap it in a pandas DataFrame call to return something easier to work with. We can also convert the index from timestamp to a more simple date as we did before, since we’re only working at the daily frequency.
ticker_hist = pd.DataFrame(ticker_hist[0]['priceData']).set_index('date') ticker_hist.index = pd.to_datetime(th.index).tz_localize(None) ticker_hist.tail()
notion image

5. Be Extra — Wrap as function that takes a ticker or list of tickers and returns a dictionary of dataframes, or df of adj close prices

happy tinkering!
p.s. I am not active on social media. If you’d like to be notified of new tutorials when they drop, consider hopping on my mailing list.