Real-Time Execution Monitoring with WebSockets and LiquidView
Build a real-time execution cost monitor with alerts. Detect cost spikes, send notifications to Telegram/Discord, and monitor DEX health.
Why Real-Time Execution Monitoring Matters
Execution costs on DEX perpetuals are not static. They respond to market conditions, exchange infrastructure health, market maker behavior, and trading volume — all of which can shift dramatically within minutes. An exchange that offered the cheapest execution cost at 9:00 AM may have seen its spreads widen to three times normal by 9:15 AM due to a sudden market move. Without real-time monitoring, you will not know this has happened until you submit a trade and receive a worse-than-expected fill.
Real-time execution monitoring solves this by continuously observing cost data and surfacing anomalies the moment they occur. A well-built monitoring system will alert you when spreads spike above a threshold, when an exchange's cost ranking changes significantly, or when overall market liquidity conditions suggest heightened caution. This transforms execution cost from something you check manually before large trades into something you are always passively aware of.
This guide builds a complete real-time execution monitoring system using the LiquidView API, from a basic polling implementation to a full alert system with Telegram and Discord notifications. No WebSocket server-side infrastructure is required — LiquidView's REST API, polled efficiently, provides sufficient data freshness for all but the most latency-sensitive use cases.
True WebSocket streams for execution cost data would require infrastructure on both the LiquidView side and your side. For the monitoring cadences that matter for trading decisions — alerting on cost spikes that persist for more than 30–60 seconds — efficient REST polling is functionally equivalent and dramatically simpler to build and maintain.
Polling vs. Webhooks vs. WebSockets: Choosing the Right Approach
There are three common architectural patterns for building real-time data pipelines. Understanding the trade-offs helps you choose the right approach for your monitoring use case.
- REST polling: Your application calls the LiquidView API on a fixed schedule (e.g., every 10 seconds) and processes the response. This is the simplest architecture — no persistent connections, no special server setup, and trivially resumable after failures. The limitation is that you will always be up to poll-interval seconds behind real-time. For execution cost monitoring, where meaningful changes typically persist for at least 30–60 seconds, a 10-second poll interval captures virtually all actionable events.
- Webhooks: A remote service calls your server when data changes, rather than you calling it on a schedule. This eliminates polling overhead and delivers data only when something changes. However, webhooks require you to run a publicly accessible HTTP server to receive calls. For a trading bot running on a private VPS, this adds infrastructure complexity. LiquidView does not currently offer webhook-push for cost data — polling is the supported approach.
- WebSockets: A persistent, bidirectional connection streams data continuously. Provides the lowest latency and most efficient bandwidth usage for high-frequency data. Requires both a WebSocket server (on the data provider side) and persistent connection management on the client side. Best suited for order book streaming and tick-level price data rather than aggregated execution cost metrics.
For execution cost monitoring with LiquidView, polling is the correct choice. It is simple, reliable, and well-matched to the update frequency of the underlying data. The rest of this guide builds a polling-based monitor.
Building a Polling-Based Execution Monitor
The core of a real-time monitor is a loop that fetches data, compares it to the previous state, and triggers any configured alerts when conditions are met. In Python, this is implemented as an infinite loop with a sleep between iterations. The loop runs continuously until the script is interrupted.
- import requests, os, time, json, datetime
- from dotenv import load_dotenv
- load_dotenv()
- API_KEY = os.environ["LIQUIDVIEW_API_KEY"]
- HEADERS = {"Authorization": f"Bearer {API_KEY}"}
- BASE_URL = "https://api.liquidview.io/v1"
- def fetch_costs(token: str, size: float = 10000) -> dict:
- resp = requests.get(
- f"{BASE_URL}/token/{token}",
- headers=HEADERS,
- params={"size": size},
- timeout=5
- )
- resp.raise_for_status()
- return resp.json()
- def run_monitor(tokens: list, poll_interval: int = 10):
- """Main monitoring loop."""
- previous_state = {}
- print(f"Starting monitor for {tokens}, polling every {poll_interval}s")
- while True:
- for token in tokens:
- try:
- data = fetch_costs(token)
- check_alerts(token, data, previous_state)
- previous_state[token] = data
- except Exception as e:
- print(f"[{datetime.datetime.utcnow().isoformat()}] Error fetching {token}: {e}")
- time.sleep(poll_interval)
The previous_state dictionary stores the last successful fetch for each token. The check_alerts function (implemented in the next section) receives both the current data and the previous state, allowing it to detect changes rather than just absolute threshold violations. This is what enables "cost spike" detection — identifying rapid increases in cost, not just high absolute values.
Log every fetch result to a file even when no alerts are triggered. This historical record is invaluable for investigating what was happening at the time of a bad fill or a missed trade opportunity. Store logs in JSONL format for easy loading into pandas later.
Setting Up Intelligent Alerts: Cost Spike Detection
The check_alerts function is where your monitoring intelligence lives. It compares the current state to both the previous state and configured thresholds to identify conditions that warrant attention. Three alert types cover the vast majority of actionable situations.
- Absolute threshold alert: Triggered when any exchange's total cost exceeds a fixed basis point threshold. Example: alert when BTC execution cost on any exchange exceeds 10 bps. This catches conditions where the market is broadly expensive and you should either delay trading or switch to a cheaper venue.
- Relative spike alert: Triggered when an exchange's cost increases by more than a configured percentage compared to the previous observation. Example: alert when any exchange's cost increases by more than 50% in a single poll cycle. This catches sudden liquidity events before they grow into sustained disruptions.
- Ranking change alert: Triggered when the cheapest exchange changes. Example: alert when Hyperliquid is no longer the cheapest option for BTC. This is actionable routing intelligence — it tells your bot to update its default routing decision.
- ABSOLUTE_THRESHOLD_BPS = 10.0 # Alert when any exchange exceeds this
- SPIKE_THRESHOLD_PCT = 50.0 # Alert on cost increase > 50% in one cycle
- def check_alerts(token: str, current: dict, previous_state: dict):
- prev = previous_state.get(token)
- current_exchanges = {e["name"]: e for e in current["exchanges"]}
- for name, ex in current_exchanges.items():
- cost = ex["total_cost_bps"]
- # Absolute threshold check
- if cost > ABSOLUTE_THRESHOLD_BPS:
- fire_alert(f"HIGH COST: {token} on {name} = {cost:.1f} bps (threshold: {ABSOLUTE_THRESHOLD_BPS})")
- # Spike detection (requires previous data)
- if prev:
- prev_exchanges = {e["name"]: e for e in prev["exchanges"]}
- if name in prev_exchanges:
- prev_cost = prev_exchanges[name]["total_cost_bps"]
- if prev_cost > 0:
- pct_change = (cost - prev_cost) / prev_cost * 100
- if pct_change > SPIKE_THRESHOLD_PCT:
- fire_alert(f"COST SPIKE: {token} on {name}: {prev_cost:.1f} -> {cost:.1f} bps (+{pct_change:.0f}%)")
- # Ranking change check
- if prev:
- current_cheapest = current["exchanges"][0]["name"]
- prev_cheapest = prev["exchanges"][0]["name"]
- if current_cheapest != prev_cheapest:
- new_cost = current["exchanges"][0]["total_cost_bps"]
- fire_alert(f"ROUTING CHANGE: {token} cheapest exchange changed from {prev_cheapest} to {current_cheapest} ({new_cost:.1f} bps)")
Telegram and Discord Notification Integration
Console output is sufficient during development, but for a production monitor running on a server, you need notifications delivered to wherever you are actually paying attention. Telegram and Discord are both excellent choices — both support bot APIs with Python libraries, and both work well on mobile, making it easy to receive execution cost alerts anywhere.
Telegram integration using the python-telegram-bot library:
- # pip install python-telegram-bot
- import asyncio
- from telegram import Bot
- TELEGRAM_TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
- TELEGRAM_CHAT_ID = os.environ["TELEGRAM_CHAT_ID"]
- async def send_telegram(message: str):
- bot = Bot(token=TELEGRAM_TOKEN)
- await bot.send_message(chat_id=TELEGRAM_CHAT_ID, text=message)
- def fire_alert(message: str):
- timestamp = datetime.datetime.utcnow().strftime("%H:%M:%S UTC")
- full_message = f"[LiquidView Monitor {timestamp}]\n{message}"
- print(full_message)
- asyncio.run(send_telegram(full_message))
Discord integration using the requests library (no extra SDK required):
- DISCORD_WEBHOOK_URL = os.environ["DISCORD_WEBHOOK_URL"]
- def send_discord(message: str):
- payload = {"content": message, "username": "LiquidView Monitor"}
- requests.post(DISCORD_WEBHOOK_URL, json=payload, timeout=5)
- # To get a Discord webhook URL:
- # 1. Open Discord channel settings
- # 2. Go to Integrations > Webhooks
- # 3. Create a new webhook and copy the URL
- # 4. Set it as the DISCORD_WEBHOOK_URL environment variable
Add a cooldown mechanism to your fire_alert function. Without it, a sustained cost spike (which may last several minutes) will generate a new notification every poll cycle — potentially dozens of messages that drown out other notifications. Implement a per-alert-type cooldown (e.g., no more than one alert per exchange per 5-minute window) to keep notifications actionable rather than noisy.
Putting It All Together: The Complete Monitoring Script
The components above combine into a complete, production-ready monitoring script. To deploy it: copy the script to your server, install dependencies (pip install requests python-telegram-bot python-dotenv), create a .env file with your API key and notification credentials, and run it with nohup python monitor.py & to keep it running after you disconnect.
- # Start the monitor for BTC and ETH, polling every 10 seconds
- if __name__ == "__main__":
- TOKENS_TO_MONITOR = ["BTC", "ETH", "SOL"]
- POLL_INTERVAL_SECONDS = 10
- run_monitor(TOKENS_TO_MONITOR, POLL_INTERVAL_SECONDS)
For a long-running production deployment, use a process manager rather than a raw nohup command. The pm2 process manager (Node.js based but works with Python) or systemd (on Linux) will automatically restart the monitor if it crashes, log output persistently, and allow you to check status and restart with simple commands. A monitor that runs reliably 24/7 without intervention is far more valuable than one that requires periodic manual restarts.
Over time, tune your alert thresholds based on what you observe. If you receive too many false-positive alerts, raise your absolute threshold or increase the spike detection percentage. If important events are slipping through without triggering alerts, lower the thresholds. Your initial configuration is a starting point — the right thresholds for your trading style and the tokens you trade will emerge from a few weeks of real-world observation.
Consider adding a daily summary notification that fires at a fixed time (e.g., 08:00 UTC) showing the average cost for each exchange over the past 24 hours. This periodic digest provides a high-level view of trends without requiring you to review logs manually, and serves as a confirmation that the monitor has been running correctly.
See it in action
Compare execution costs across 9+ DEX perpetuals in real-time with LiquidView.
Related Articles
How to Integrate Execution Cost Data Into Your Trading Strategy
A practical guide to making execution cost data a first-class input in your trading strategy — pre-trade analysis, real-time routing, post-trade review, and full API integration.
Building a Smart Order Router in JavaScript
Step-by-step guide to building a smart order router in Node.js using the LiquidView API. Full code, error handling, caching, and deployment included.
Comparing DEX APIs: Data Quality and Coverage
A comprehensive comparison of DEX data APIs — what data is available, the limitations of direct exchange APIs, aggregator options, and why execution cost data is uniquely hard to get.
How LiquidView Collects Execution Cost Data
An inside look at LiquidView's data pipeline — how order book simulation works, what data is stored, the architecture behind the API, and the accuracy and limitations of the approach.
