Overview
So you have a new trading algorithm. You've looked at the intervals api (candlesticks) but that isn't good enough. You need to know tick by tick, quote by quote what happened on a given trading day. Using the trades api is perfect for staying up to date with current market tick data. However, that endpoint only has trades and only for the previous 7 days. Enter Intrinio's replay client. You can play back a full trading day from the SIP (100% market volume) to test exactly how your algorithm would perform. Alternatively upload some or all of the trades and quotes into a database for further analysis.
For this guide I will be using Python but the same principles apply to .Net, Java, and Javascript. This guide assumes that you already have an account with Intrinio and have been provisioned to the delayed SIP product. We're also going to take a look at a recently delisted stock VRM and detect moments of major volatility. November 15th was a very bad day for VRM, where it lost 24% of its value a few days before it delisted. Let's run some code and see what we find.
Procedure
First clone the repository. Then find the example_app.py file. We will be adding the following code sections of code to this file.
import threading
import signal
import time
import sys
from datetime import datetime
from threading import Timer,Thread,Event
from intriniorealtime.replay_client import IntrinioReplayClient
# Close for VRM on 2024-11-14
# Grabbed from https://docs.intrinio.com/documentation/web_api/get_security_stock_prices_v2
# Code omitted for simplicity
previous_trade = 6.56
previous_bid = 6.56
Next we will add the quote and trade event handlers that we will use to determine what to do on a given trade. We've pulled the close price from the previous day to bootstrap this example. See this api to get it yourself.
def on_quote(quote, backlog):
global previous_bid
if(backlog == 0):
exit()
dt = datetime.fromtimestamp(quote.timestamp / 1000000000)
if quote.type == 'bid' and quote.price != 0:
bid_percent_change = ((quote.price - previous_bid) / previous_bid) * 100
if bid_percent_change > 1 or bid_percent_change < -1:
previous_bid = quote.price
print(f'{dt} - {quote.symbol}: {quote.type.upper()}: ${round(quote.price, 4)} - % Change: {round(bid_percent_change, 4)}')
def on_trade(trade, backlog):
global previous_trade
if(backlog == 0):
exit()
dt = datetime.fromtimestamp(trade.timestamp / 1000000000)
trade_percent_change = ((trade.price - previous_trade) / previous_trade) * 100
if trade_percent_change > 1 or trade_percent_change < -1:
print(f'{dt} - {trade.symbol}: TRADE: ${round(trade.price, 4)} - % Change: {round(trade_percent_change, 4)}')
previous_trade = trade.price
Now we'll add the rest of the configuration. Make sure to replace your api key.
date_string = "2024-11-15"
date_format = "%Y-%m-%d"
date_object = datetime.strptime(date_string, date_format).date()
options = {
'api_key': 'YOUR_API_KEY',
'provider': 'DELAYED_SIP', # REALTIME or DELAYED_SIP or NASDAQ_BASIC
'replay_date': date_object,
'with_simulated_delay': False, # This plays back the events at the same rate they happened in market.
'delete_file_when_done': False,
'write_to_csv': False, # needed for ReplayClient
'csv_file_path': 'data.csv' # needed for ReplayClient
}
client = IntrinioReplayClient(options, on_trade, on_quote)
stop_event = Event()
def on_kill_process(sig, frame):
print("Stopping")
sys.exit(0)
exit()
signal.signal(signal.SIGINT, on_kill_process)
client.join(['VRM'])
client.connect()
while not stop_event.is_set():
time.sleep(1)
Now run the app!
docker compose up --build
For simplicitly's sake we looked at only symbol on only one day. However, to get all symbols for a given day, simply join to the lobby instead of a ticker.
Conclusion
The application will download that day's file and replay the the day's trades and quotes logging moments of high volatility. While it is a somewhat contrived example, It demonstrates the power of the replay client for testing market strategies at various times in history.