Blog post banner

Realtime stock dashboard with the IEX Trading API

August 12, 2018

Many people were interested in our previous blog post about building a realtime stock dashboard using data from Alpha Vantage. Recently however, we’ve had a better experience with the market data API that is provided by the IEX Group

For that reason we decided to add IEX Apps to the Gridarrow catalog and share a new version of the stock dashboard spreadsheet.

What is Gridarrow?

Gridarrow is the missing server for Excel. It connects just about any data source to Excel with simple Python scripts.
Why is it awesome?
  • It's real-time, so as soon as the data is updated in the Gridarrow App it's updated in Excel, no need to poll or refresh.
  • It's multi-user so your colleagues can connect to the same data at the same time.
  • It simplifies your spreadsheets by moving data retrieval and pre-processing into Python.
Request Demo

If you go to the Gridarrow catalog you’ll see two new apps - IEX Live Prices and IEX Historic Prices.

IEX apps in Gridarrow catalog

As the names suggest, the Live Prices App provides a feed of best quoted bid and offer position in near real time for all securities on IEX’s displayed limit order book, and the Historic Prices gives a feed of daily OHLC prices for the last month, and minutely OHLC prices for the current day.

Click the Add button to install those Apps in your Gridarrow workspaces. Once the Apps have started you can plug the feeds into the sheet, allowing us to build a spreadsheet that looks something like this:

Realtime stock dashboard with IEX data

Data provided for free by IEX. View IEX’s Terms of Use.

The charts are showing monthly prices, but all the data is there to change that to daily prices, if you would prefer that.

Again the spreadsheet is available, and here’s the full code for connecting to the IEX TOPS websocket that’s used in the IEX Live Prices app.

But before you jump into it, remember to:

 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
import json
from datetime import datetime

import pytz
from retry import retry
from socketIO_client_nexus import SocketIO, SocketIONamespace

from gridarrow import Arrow

arrow = Arrow()

# The full list of symbols supported by IEX is available here:
# https://api.iextrading.com/1.0/ref-data/symbols
# enter data as comma separated variables, with no spaces.
SYMBOLS = 'AAPL,AMZN,FB,NFLX,USO,NKE,YUM,GE,INTC'

TIME_ZONE = pytz.timezone('America/New_York')


@arrow.initialize
def initialize():
    cols = ['symbol', 'marketPercent', 'volume', 'bidPrice',
            'bidSize', 'askSize', 'askPrice',
            'lastSalePrice', 'lastSaleSize', 'lastSaleTime',
            'sector', 'securityType']

    tops = arrow.grid('IEX Tops', rows=SYMBOLS.split(','), columns=cols)
    return tops


@arrow.on_start
@retry(IndexError)
def on_start(tops):
    class Namespace(SocketIONamespace):
        def on_message(self, msg):
            data = json.loads(msg)
            symbol = data['symbol']
            dt = datetime.fromtimestamp(data['lastSaleTime'] / 1000, tz=pytz.UTC)
            data['lastSaleTime'] = dt.astimezone(TIME_ZONE).replace(tzinfo=None)
            tops[symbol, tops.columns] = [data[c] for c in tops.columns]

        def on_connect(self):
            arrow.log.info("iex socket connected")
            self.emit('subscribe', SYMBOLS)

        def on_reconnect(self):
            arrow.log.info("iex socket reconnected")
            self.emit('subscribe', SYMBOLS)

        def on_disconnect(self):
            arrow.log.warn("iex socket disconnected")

        def on_error(self, data):
            arrow.log.error(f"iex socket errored {data}")

    socket = SocketIO('https://ws-api.iextrading.com', 443)
    socket.define(Namespace, '/1.0/tops')
    socket.wait()