Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dharmatech/7b8135785ec22a4e68062ccc8feb99f6 to your computer and use it in GitHub Desktop.
Save dharmatech/7b8135785ec22a4e68062ccc8feb99f6 to your computer and use it in GitHub Desktop.
# ----------------------------------------------------------------------
# Uses the polygon-api-client package:
# https://github.com/polygon-io/client-python
# Start the script like this:
# python -i polygon-io-websocket-trades-show-if-higher-filtered-table-release.py
# If you want to capture all the options websocket data for the day, start it before the market opens.
# All the options data is put into the `data` array. Only filtered trades are shown on the console.
# Use ctrl-c to stop script at the end of the day (or in the middle of the day for whatever reason).
# Use `save()` to save the options data to disk.
# If you stop the script in the middle of the day and want to continue collecting data, you can run these lines:
# ws = WebSocketClient(feed='socket.polygon.io', market='options', subscriptions=["T.*"], api_key=api_key)
# ws.run(handle_msg=handle_msg)
# You'll need the 'Advanced' options subscription on polygon-io to run this script. Currently $199/month.
# https://polygon.io/pricing?product=options
# So unless you have a need to dig into the low level data, you're better off going with Unusual Whales which is much cheaper.
# ----------------------------------------------------------------------
import os
import json
from polygon import WebSocketClient
from polygon.websocket.models import WebSocketMessage
from typing import List
from datetime import datetime
import re
import pandas as pd
import jsonpickle
from polygon import RESTClient
import time
import colorama
from colorama import Fore, Style
import locale
locale.setlocale(locale.LC_ALL, '')
# ----------------------------------------------------------------------
api_key = os.environ['POLYGON_IO_API_KEY']
data = []
filtered_table = {}
# ----------------------------------------------------------------------
def save():
frozen = jsonpickle.encode(data)
path = "data-{}.json".format(datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))
file = open(path, "w")
n = file.write(frozen)
file.close()
# ----------------------------------------------------------------------
def hyperlink(url, text):
return f'\u001b]8;;{url}\u001b\{text}\u001b]8;;\u001b\\'
def uw_flow_link(symbol):
return hyperlink(f'https://unusualwhales.com/stock/{symbol}/flow-overview', symbol).ljust(67 + len(symbol))
def uw_live_options_flow(contract, symbol, strike, exp):
return hyperlink(f'https://unusualwhales.com/live-options-flow?type=C&expiry_dates[]={exp}&min_strike={strike}&max_strike={strike}&ticker_symbol={symbol}', contract).ljust(156 + len(contract))
def uw_live_options_flow(contract):
result = re.search(r'O:(.+)(\d\d)(\d\d)(\d\d)([CP])0*(\d+)$', contract)
symbol, year, month, day, contract_type, strike = result.groups()
exp = f'20{year}-{month}-{day}'
strike = int(strike) / 1000
link = hyperlink(f'https://unusualwhales.com/live-options-flow?type={contract_type}&expiry_dates[]={exp}&min_strike={strike}&max_strike={strike}&ticker_symbol={symbol}', contract)
return link.ljust(15+len(link)-len(symbol))
# ----------------------------------------------------------------------
client = RESTClient(api_key=api_key)
result_conditions = client.list_conditions(asset_class='options', limit=1000)
conditions = list(result_conditions)
conditions_table = {}
for condition in conditions:
conditions_table[condition.id] = condition
# ----------------------------------------------------------------------
def print_trade (trade):
symbol = re.sub(r'^O:', r'', trade.symbol) # remove before symbol
symbol = re.sub(r'2.+$', r'', symbol) # remove after symbol
result = re.search(r'(\d\d\d\d\d\d)[CP]', trade.symbol)
exp = result.group(1)
result = re.search(r'\d\d\d\d\d\d[CP]0*(\d+)', trade.symbol)
strike = result.group(1)
strike = int(strike) / 1000
result = re.search(r'(\d\d\d\d\d\d)([CP])0*(\d+)', trade.symbol)
contract_type = result.group(2)
premium = int(trade.price * trade.size * 100)
condition_names = [conditions_table[id].name for id in trade.conditions]
condition_abbreviations = [conditions_table[id].abbreviation for id in trade.conditions]
time = datetime.fromtimestamp(trade.timestamp / 1000)
bid_price = ''
ask_price = ''
side = ''
flag = ''
if hasattr(trade, 'bid_price'):
bid_price = f'{trade.bid_price:6.2f}'
else:
bid_price = ' '
if hasattr(trade, 'ask_price'):
ask_price = f'{trade.ask_price:6.2f}'
else:
ask_price = ' '
if hasattr(trade, 'bid_price'):
spread = trade.ask_price - trade.bid_price
mid = (trade.ask_price + trade.bid_price) / 2
if trade.price > mid + spread * 0.1:
side = 'ask'
elif trade.price < mid - spread * 0.1:
side = 'bid'
else:
side = 'mid'
bullish = f'{Fore.GREEN}bullish{Style.RESET_ALL}'
bearish = f'{Fore.RED}bearish{Style.RESET_ALL}'
neutral = f'{Fore.BLUE}neutral{Style.RESET_ALL}'
if contract_type == 'C':
if side == 'ask':
flag = bullish
elif side == 'bid':
flag = bearish
elif side == 'mid':
flag = neutral
elif contract_type == 'P':
if side == 'ask':
flag = bearish
elif side == 'bid':
flag = bullish
elif side == 'mid':
flag = neutral
if contract_type == 'C':
contract_type = f'{Fore.GREEN}{contract_type}{Style.RESET_ALL}'
elif contract_type == 'P':
contract_type = f'{Fore.RED}{contract_type}{Style.RESET_ALL}'
if side == 'ask':
side = f'{Fore.GREEN}{side}{Style.RESET_ALL}'
elif side == 'bid':
side = f'{Fore.RED}{side}{Style.RESET_ALL}'
else:
side = f'{Fore.BLUE}{side}{Style.RESET_ALL}'
symbol = uw_flow_link(symbol)
contract = uw_live_options_flow(trade.symbol)
# contract = trade.symbol
print(f'{time:%H:%M:%S.%f}', f'{symbol:5}', f'{exp[0:2]}-{exp[2:4]}-{exp[4:6]}', f'{contract_type:2}', f'{strike:8.2f}',
# f'{trade.symbol:25}',
f'{contract}'
f'{bid_price}', f'{trade.price:6.2f}', f'{ask_price}', f'{side:4}',
f'{trade.size:7n}', f'{premium:15n}', flag, f'{condition_abbreviations[0]}', f'{len(condition_abbreviations)}', f'{condition_names[0]}')
def print_trade_highlight (trade):
premium = int(trade.price * trade.size * 100)
print(trade.timestamp, f'{Fore.YELLOW}{trade.symbol:30}{Style.RESET_ALL}', f'{premium:15n}')
thresholds = {
'SPX' : 2000000,
'SPXW' : 2000000,
'NVDA' : 500000,
'QQQ' : 350000,
'META' : 800000,
'NFLX' : 300000,
'TSLA' : 400000,
'PLTR' : 150000,
'SPY' : 500000,
'NDXP' : 200000,
'GOOGL' : 150000,
'NDX' : 200000,
'RUT' : 150000,
'RUTW' : 150000,
'IWM' : 500000,
'AMD' : 200000,
'MSFT' : 200000,
'AMZN' : 150000,
'BABA' : 150000,
'SOFI' : 100000,
'ROKU' : 200000,
'AI' : 50000,
'RTX' : 30000,
'FXI' : 30000,
'ONON' : 30000,
'TRUP' : 40000,
'PINS' : 20000,
'ATVI' : 20000,
'INTU' : 20000,
'AAPL' : 2000000
}
# ----------------------------------------------------------------------
from threading import Thread
def handle_trade(trade):
print('handle_trade start')
print(trade)
time.sleep(3)
print('handle_trade complete')
def handle_msg_test(msg: List[WebSocketMessage]):
for m in msg:
thread = Thread(target=handle_trade, args=(m,))
thread.start()
# ----------------------------------------------------------------------
def handle_msg(msg: List[WebSocketMessage]):
for m in msg:
data.append(m)
symbol = re.sub(r'^O:', r'', m.symbol) # remove before symbol
symbol = re.sub(r'2.+$', r'', symbol) # remove after symbol
premium = m.price * m.size * 100
# --------------------------------------------------
if symbol not in filtered_table:
filtered_table[symbol] = []
filtered = filtered_table[symbol]
# --------------------------------------------------
if premium > thresholds.get(symbol, 100000):
ls = [trade for trade in filtered if symbol in trade.symbol]
if all(premium > trade.price * trade.size * 100 for trade in ls):
# last_quote = client.get_last_quote(ticker=trade.symbol)
# trade.bid_price = last_quote.bid_price
# trade.ask_price = last_quote.ask_price
last_quote = client.get_last_quote(ticker=m.symbol)
m.bid_price = last_quote.bid_price
m.ask_price = last_quote.ask_price
print_trade(m)
filtered.append(m)
# ----------------------------------------------------------------------
ws = WebSocketClient(feed='socket.polygon.io', market='options', subscriptions=["T.*"], api_key=api_key)
ws.run(handle_msg=handle_msg)
# ----------------------------------------------------------------------
def save_items(items):
frozen = jsonpickle.encode(items)
path = "items-{}.json".format(datetime.now().strftime('%Y-%m-%d-%H-%M-%S'))
file = open(path, "w")
n = file.write(frozen)
file.close()
# ----------------------------------------------------------------------
# get trades with a bid_price
# ----------------------------------------------------------------------
# trades = [trade for trade in data if hasattr(trade, 'bid_price')]
# [print_trade(t) for t in trades[:50]] # first 50 elements
# [print_trade(t) for t in trades[-30:]] # last 30 elements
# ----------------------------------------------------------------------
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment