24/7 Crypto Monitoring: Building Always-On Analysis Systems
Build a monitoring system that watches crypto markets around the clock, detects significant moves, and sends alerts when conditions match your criteria.
Crypto Never Sleeps
Unlike forex which closes on weekends, crypto markets run 24/7/365. Major moves happen at 3 AM on a Sunday. If your monitoring system is not always on, you will miss opportunities and fail to react to risks.
This tutorial builds a lightweight monitoring daemon that runs on a VPS, checks indicators on a schedule, and sends alerts via Telegram or Discord when your conditions are met.
Architecture
VPS (Ubuntu, $5/mo)
|
[Python Daemon]
|-- Every 5 min: check indicators for watchlist
|-- Compare against alert rules
|-- If triggered: send notification
|-- Log everything to file
|
v
Telegram Bot / Discord Webhook / Email
Define Alert Rules
from dataclasses import dataclass
from enum import Enum
class Condition(Enum):
ABOVE = "above"
BELOW = "below"
CROSSES_ABOVE = "crosses_above"
CROSSES_BELOW = "crosses_below"
@dataclass
class AlertRule:
symbol: str
indicator: str
timeframe: str
condition: Condition
threshold: float
message: str
cooldown_minutes: int = 60 # Don't re-alert within this window
# Example rules
RULES = [
AlertRule("BTCUSD", "RSI_14", "H4", Condition.ABOVE, 80,
"BTC H4 RSI overbought: {'{'+'value:.1f'+'}'}"),
AlertRule("BTCUSD", "RSI_14", "H4", Condition.BELOW, 25,
"BTC H4 RSI oversold: {'{'+'value:.1f'+'}'}"),
AlertRule("ETHUSD", "RSI_14", "H4", Condition.BELOW, 30,
"ETH H4 RSI oversold: {'{'+'value:.1f'+'}'}"),
AlertRule("BTCUSD", "MACD", "D1", Condition.CROSSES_ABOVE, 0,
"BTC Daily MACD bullish crossover!"),
AlertRule("XAUUSD", "RSI_14", "D1", Condition.ABOVE, 75,
"Gold Daily RSI overbought: {'{'+'value:.1f'+'}'}"),
] The Monitoring Engine
import requests
import time
import logging
from datetime import datetime, timedelta
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s %(levelname)s %(message)s",
handlers=[
logging.FileHandler("monitor.log"),
logging.StreamHandler(),
],
)
logger = logging.getLogger("crypto_monitor")
API_KEY = "YOUR_API_KEY"
BASE_URL = "https://tickatlas.com/v1"
class CryptoMonitor:
def __init__(self, rules: list[AlertRule]):
self.rules = rules
self.last_alert: dict[str, datetime] = {}
self.previous_values: dict[str, float] = {}
def fetch_value(self, symbol: str, indicator: str, tf: str) -> float:
resp = requests.get(
f"{BASE_URL}/indicator",
headers={"X-API-Key": API_KEY},
params={"symbol": symbol, "indicator": indicator, "timeframe": tf},
)
resp.raise_for_status()
data = resp.json()["data"]["values"]
# Return the first numeric value
for v in data.values():
if isinstance(v, (int, float)):
return v
return 0.0
def check_condition(self, rule: AlertRule, value: float) -> bool:
key = f"{rule.symbol}:{rule.indicator}:{rule.timeframe}"
prev = self.previous_values.get(key)
self.previous_values[key] = value
if rule.condition == Condition.ABOVE:
return value > rule.threshold
elif rule.condition == Condition.BELOW:
return value < rule.threshold
elif rule.condition == Condition.CROSSES_ABOVE:
return prev is not None and prev <= rule.threshold < value
elif rule.condition == Condition.CROSSES_BELOW:
return prev is not None and prev >= rule.threshold > value
return False
def is_cooled_down(self, rule: AlertRule) -> bool:
key = f"{rule.symbol}:{rule.indicator}:{rule.condition.value}"
last = self.last_alert.get(key)
if last is None:
return True
return datetime.utcnow() - last > timedelta(minutes=rule.cooldown_minutes)
def run_cycle(self) -> list[str]:
triggered = []
for rule in self.rules:
try:
value = self.fetch_value(rule.symbol, rule.indicator, rule.timeframe)
if self.check_condition(rule, value) and self.is_cooled_down(rule):
msg = rule.message.format(value=value)
triggered.append(msg)
key = f"{rule.symbol}:{rule.indicator}:{rule.condition.value}"
self.last_alert[key] = datetime.utcnow()
logger.info(f"ALERT: {msg}")
except Exception as e:
logger.error(f"Error checking {rule.symbol} {rule.indicator}: {e}")
return triggered Sending Alerts via Telegram
TELEGRAM_TOKEN = "YOUR_BOT_TOKEN"
TELEGRAM_CHAT_ID = "YOUR_CHAT_ID"
def send_telegram(message: str):
url = f"https://api.telegram.org/bot{TELEGRAM_TOKEN}/sendMessage"
requests.post(url, json={
"chat_id": TELEGRAM_CHAT_ID,
"text": f"🔔 {message}",
"parse_mode": "HTML",
})
# Main loop
monitor = CryptoMonitor(RULES)
logger.info("Crypto monitor started. Checking every 5 minutes.")
while True:
alerts = monitor.run_cycle()
for alert in alerts:
send_telegram(alert)
time.sleep(300) # 5 minutes Deploying on a VPS
# On your VPS (Ubuntu)
sudo apt install python3-pip
pip3 install requests
# Create a systemd service
sudo tee /etc/systemd/system/crypto-monitor.service > /dev/null << 'EOF'
[Unit]
Description=Crypto Market Monitor
After=network.target
[Service]
ExecStart=/usr/bin/python3 /opt/monitor/crypto_monitor.py
WorkingDirectory=/opt/monitor
Restart=always
RestartSec=30
User=monitor
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl enable crypto-monitor
sudo systemctl start crypto-monitor
sudo systemctl status crypto-monitor
Related Reading
Try this with live data
Every account gets $2.50 in free PAYG credits. No card required — paste your API key and run the code above against live broker data.
Keep reading
All articles- Tutorial 12 min read
How to Build an AI Market Analyst That Runs 24/7
Build a production-ready AI market analyst that monitors forex and crypto markets around the clock, generates daily briefings, and alerts you to opportunities via Telegram.
March 28, 2026
- Tutorial 10 min read
Using ATR for Dynamic Stop-Loss Placement
Learn how to use Average True Range (ATR) to set volatility-adjusted stop losses that adapt to market conditions, with full code examples.
March 28, 2026
- Tutorial 11 min read
How to Backtest a Trading Strategy with Historical API Data
Learn how to backtest your trading strategy using historical OHLC and indicator data from the TickAtlas API. Includes a complete Python backtesting framework.
March 28, 2026