1
Fork 0
crypto_bot_training/Session_02/Projects/liquidations.py
2025-06-13 20:00:45 +02:00

148 lines
No EOL
6 KiB
Python

import asyncio
import json
import os
from datetime import datetime
import pytz
from websockets import connect
from rich.console import Console
from rich.text import Text
from rich.panel import Panel
from rich.align import Align
from rich.columns import Columns
from rich.rule import Rule
LIQ_LIMIT = 0
console = Console()
websocket_url = 'wss://fstream.binance.com/ws/!forceOrder@arr'
def format_usd(amount):
"""Format USD amount with appropriate suffixes"""
if amount >= 1_000_000:
return f"${amount/1_000_000:.2f}M"
elif amount >= 1_000:
return f"${amount/1_000:.1f}K"
else:
return f"${amount:.0f}"
async def binance_liquidation(uri):
# Print header
console.print(Rule("[bold cyan]🔥 BINANCE LIQUIDATION MONITOR 🔥[/bold cyan]", style="cyan"))
console.print()
async with connect(uri) as websocket:
while True:
try:
msg = await websocket.recv()
order_data = json.loads(msg)['o']
symbol = order_data['s'].replace('USDT', '')
side = order_data['S']
timestamp = int(order_data['T'])
filled_quantity = float(order_data['z'])
price = float(order_data['p'])
usd_size = filled_quantity * price
est = pytz.timezone("US/Eastern")
time_est = datetime.fromtimestamp(timestamp / 1000, est).strftime('%H:%M:%S')
if usd_size >= LIQ_LIMIT:
liquidation_type = '📈 LONG LIQ' if side == 'SELL' else '📉 SHORT LIQ'
symbol_clean = symbol[:4]
formatted_usd = format_usd(usd_size)
# Choose colors and styling based on liquidation type and size
if side == 'SELL': # Long liquidation
border_color = "bright_green"
text_style = "bright_green"
emoji_prefix = "🟢"
else: # Short liquidation
border_color = "bright_red"
text_style = "bright_red"
emoji_prefix = "🔴"
# Create content sections
type_text = Text(liquidation_type, style=f"bold {text_style}")
symbol_text = Text(f"{symbol_clean}", style="bold yellow")
time_text = Text(f"{time_est}", style="white")
amount_text = Text(formatted_usd, style=f"bold {text_style}")
# Create the main content
content_parts = [
emoji_prefix,
type_text,
symbol_text,
time_text,
amount_text
]
if usd_size > 250000:
# Mega liquidation - very prominent
title = "💎 MEGA LIQUIDATION 💎"
panel = Panel(
Align.center(Columns(content_parts, padding=(0, 2))),
title=title,
title_align="center",
border_style=border_color,
style=f"bold {text_style}",
padding=(1, 2)
)
for _ in range(4):
console.print(panel)
elif usd_size > 100000:
# Large liquidation - prominent
title = "🚨 LARGE LIQUIDATION 🚨"
panel = Panel(
Align.center(Columns(content_parts, padding=(0, 1))),
title=title,
title_align="center",
border_style=border_color,
style=f"bold {text_style}",
padding=(0, 2)
)
for _ in range(2):
console.print(panel)
elif usd_size > 25000:
# Medium liquidation - boxed
panel = Panel(
Columns(content_parts, padding=(0, 1)),
border_style=border_color,
style=f"bold {text_style}",
padding=(0, 1)
)
console.print(panel)
else:
# Small liquidation - simple line
line_content = Text()
for i, part in enumerate(content_parts):
if i > 0:
line_content.append(" ")
line_content.append(part)
console.print(
Panel(
line_content,
border_style=border_color,
style=text_style,
padding=(0, 1),
expand=False
)
)
console.print() # Spacing
except Exception as e:
error_panel = Panel(
f"❌ Connection error: {str(e)}\n⏳ Reconnecting in 5 seconds...",
title="Error",
border_style="yellow",
style="yellow"
)
console.print(error_panel)
await asyncio.sleep(5)
if __name__ == "__main__":
try:
asyncio.run(binance_liquidation(websocket_url))
except KeyboardInterrupt:
console.print(Rule("[bold red]👋 Liquidation monitor stopped[/bold red]", style="red"))