add options flow to discord bot

This commit is contained in:
MuslemRahimi 2025-04-11 14:27:50 +02:00
parent afc9ad884a
commit 1001cf4381

View File

@ -1,26 +1,30 @@
import requests import requests
import time import time
import orjson import orjson
from datetime import datetime, timedelta, timezone from datetime import datetime, timedelta, timezone, date
import pytz
import os import os
from dotenv import load_dotenv from dotenv import load_dotenv
load_dotenv() load_dotenv()
ny_tz = pytz.timezone("America/New_York")
today = datetime.utcnow().date() today = datetime.utcnow().date()
now = datetime.now(timezone.utc) now = datetime.now(timezone.utc)
now_ny = datetime.now(ny_tz)
N_minutes_ago = now - timedelta(minutes=30) N_minutes_ago = now - timedelta(minutes=30)
WEBHOOK_URL = os.getenv("DISCORD_DARK_POOL_WEBHOOK") DARK_POOL_WEBHOOK_URL = os.getenv("DISCORD_DARK_POOL_WEBHOOK")
OPTIONS_FLOW_WEBHOOK_URL = os.getenv("DISCORD_OPTIONS_FLOW_WEBHOOK")
def save_json(data): def save_json(data):
directory = "json/discord" directory = "json/discord"
try:
os.makedirs(directory, exist_ok=True) os.makedirs(directory, exist_ok=True)
with open(directory+"/dark_pool.json", 'wb') as file: with open(directory+"/dark_pool.json", 'wb') as file:
file.write(orjson.dumps(data)) file.write(orjson.dumps(data))
except Exception as e:
print(f"An error occurred while saving data: {e}")
def format_number(num, decimal=False): def format_number(num, decimal=False):
@ -118,7 +122,7 @@ def dark_pool_flow():
"embeds": [embed] "embeds": [embed]
} }
response = requests.post(WEBHOOK_URL, json=payload) response = requests.post(DARK_POOL_WEBHOOK_URL, json=payload)
if response.status_code in (200, 204): if response.status_code in (200, 204):
seen_list.append({'date': result['date'], 'trackingID': result['trackingID']}) seen_list.append({'date': result['date'], 'trackingID': result['trackingID']})
@ -133,5 +137,126 @@ def dark_pool_flow():
else: else:
print("Dark pool already sent!") print("Dark pool already sent!")
def options_flow():
now_ny = datetime.now(ny_tz)
N_minutes_ago = now_ny - timedelta(minutes=5)
today = now_ny.date()
# Load seen entries
try:
with open("json/discord/options_flow.json", "rb") as file:
seen_list = orjson.loads(file.read())
today_iso = today.isoformat()
seen_list = [item for item in seen_list if item['date'] == today_iso]
except FileNotFoundError:
seen_list = []
except Exception as e:
print(f"Error loading seen list: {e}")
seen_list = []
# Load current data
try:
with open("json/options-flow/feed/data.json", "rb") as file:
res_list = orjson.loads(file.read())
except Exception as e:
print(f"Error loading data.json: {e}")
res_list = []
# Process and filter entries
filtered = []
for item in res_list:
try:
# Validate required fields
if float(item.get('cost_basis', 0)) < 1E5:
continue
item_date = datetime.fromisoformat(item['date']).date()
if item_date != today:
continue
item_time = datetime.strptime(item['time'], "%H:%M:%S").time()
item_dt = ny_tz.localize(datetime.combine(item_date, item_time))
if item_dt < N_minutes_ago:
filtered.append(item)
except Exception as e:
print(f"Error processing item {item.get('id')}: {e}")
continue
if not filtered:
print("No recent valid entries found")
return
# Find best order
best_order = max(filtered, key=lambda x: float(x['cost_basis']))
result = {
k: best_order[k] for k in [
'date', 'sentiment', 'option_activity_type', 'ticker', 'id',
'strike_price', 'date_expiration', 'size', 'cost_basis',
'execution_estimate', 'volume', 'open_interest', 'put_call'
]
}
# Check duplicates
seen_ids = {item['id'] for item in seen_list}
if result['id'] in seen_ids:
print("Options Flow data already sent!")
return
# Prepare message
try:
symbol = result['ticker']
size = format_number(result['size'])
premium = format_number(result['cost_basis'])
strike = result['strike_price']
side = result['execution_estimate']
volume = format_number(result['volume'])
open_interest = format_number(result['open_interest'])
put_call = result['put_call'].replace('Calls', 'Call').replace('Puts', 'Put')
option_activity_type = result['option_activity_type']
sentiment = result['sentiment']
date_expiration = datetime.strptime(result['date_expiration'], "%Y-%m-%d").strftime("%d/%m/%Y")
message_timestamp = int(now_ny.timestamp())
color = 0x39FF14 if sentiment == 'Bullish' else 0xFF0000 if sentiment == 'Bearish' else 0xFFA500
embed = {
"color": color,
"thumbnail": {"url": "https://stocknear.com/pwa-64x64.png"},
"description": f"{put_call} {option_activity_type} ({sentiment})",
"fields": [
{"name": "Symbol", "value": symbol, "inline": True},
{"name": "Strike", "value": str(strike), "inline": True},
{"name": "Expiration", "value": date_expiration, "inline": True},
{"name": "Call/Put", "value": put_call, "inline": True},
{"name": "Side", "value": str(side), "inline": True},
{"name": "Size", "value": str(size), "inline": True},
{"name": "Premium", "value": f"${premium}", "inline": True},
{"name": "Volume", "value": str(volume), "inline": True},
{"name": "OI", "value": str(open_interest), "inline": True},
{"name": f"Data by Stocknear - <t:{message_timestamp}:R> - Delayed by 5 min",
"value": "", "inline": False}
],
"footer": {"text": ""}
}
payload = {"content": "", "embeds": [embed]}
# Send to Discord
response = requests.post(OPTIONS_FLOW_WEBHOOK_URL, json=payload)
response.raise_for_status()
# Update seen list
seen_list.append({'date': result['date'], 'id': result['id']})
with open("json/discord/options_flow.json", "wb") as file:
file.write(orjson.dumps(seen_list))
print("Embed sent successfully!")
except Exception as e:
print(f"Error sending message: {e}")
if __name__ == "__main__": if __name__ == "__main__":
options_flow()
dark_pool_flow() dark_pool_flow()