How to Get Telegram Crypto Alerts from Your Local AI Agent
Your AI agent runs analysis 24/7. Your phone is with you 24/7. The missing piece is a reliable bridge between the two. Telegram is that bridge — free, instant, and surprisingly powerful for crypto alerts.
This guide walks you through building a complete Telegram alerting system that integrates with OpenClaw. By the end, you'll receive formatted price alerts, RSI signals, regime change notifications, and daily summaries — all delivered to your phone by a local AI agent that never sleeps.
Not financial advice. Paper trading only.
Why Telegram for Crypto Alerts?
You have options: email, SMS, push notifications, Discord. Telegram wins for several reasons:
It's free forever. No API costs. No monthly limits. The Telegram Bot API is completely free with generous rate limits (30 messages/second to different users).
It has a real Bot API. Unlike email (complex SMTP), Telegram bots are trivially easy to create and control via HTTP.
It supports rich formatting. Markdown, bold, code blocks, inline buttons — your alerts can be beautifully formatted, not just plain text.
It's cross-platform. Desktop, iOS, Android — your alerts follow you everywhere.
It's private. Your bot messages go directly to you. No shared Discord server where your signals are public.
Step 1: Create Your Telegram Bot
This takes 2 minutes:
- Open Telegram and search for
@BotFather - Send
/newbot - Choose a name (e.g., "CryptoWatch Agent")
- Choose a username ending in
bot(e.g.,cryptowatch_agent_bot) - BotFather gives you a token — copy it, keep it safe
Your token looks like: 6782456789:AAEtKnX8YVmP...
Get Your Chat ID
Next you need your personal chat ID (so the bot knows where to send messages):
- Start a conversation with your new bot
- Send
/start - Visit:
https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates - Find
"chat": {"id": YOUR_CHAT_ID}in the JSON response
Store both values:
# Windows
set TELEGRAM_BOT_TOKEN=6782456789:AAEtKnX8YVmP...
set TELEGRAM_CHAT_ID=123456789
# Or store in a .env file
echo TELEGRAM_BOT_TOKEN=6782456789:AAEtKnX8YVmP... > .env
echo TELEGRAM_CHAT_ID=123456789 >> .env
Step 2: Build the Alert Functions
# telegram_alerts.py
import json
import urllib.request
import urllib.error
from datetime import datetime
TELEGRAM_API = "https://api.telegram.org/bot{token}/{method}"
def send_message(token: str, chat_id: str, text: str,
parse_mode: str = "Markdown") -> bool:
"""Send a Telegram message."""
url = TELEGRAM_API.format(token=token, method="sendMessage")
payload = {
"chat_id": chat_id,
"text": text,
"parse_mode": parse_mode,
"disable_web_page_preview": True,
}
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
url, data=data,
headers={"Content-Type": "application/json"}
)
try:
with urllib.request.urlopen(req, timeout=10) as resp:
result = json.loads(resp.read())
return result.get("ok", False)
except urllib.error.HTTPError as e:
print(f"Telegram error: {e.code} — {e.read().decode()}")
return False
except Exception as e:
print(f"Telegram error: {e}")
return False
def send_price_alert(token, chat_id, symbol, price, change_24h, signal=None):
"""Send a formatted price alert."""
direction = "📈" if change_24h > 0 else "📉"
signal_line = f"\n⚡ *Signal:* {signal}" if signal else ""
text = f"""
{direction} *{symbol} Price Alert*
💰 Price: `${price:,.2f}`
📊 24h Change: `{change_24h:+.2f}%`
🕐 Time: `{datetime.utcnow().strftime('%H:%M UTC')}`{signal_line}
""".strip()
return send_message(token, chat_id, text)
def send_rsi_alert(token, chat_id, symbol, rsi, price, condition):
"""Send RSI-based alert."""
if condition == "oversold":
emoji = "🟢"
label = "OVERSOLD (Potential Buy)"
elif condition == "overbought":
emoji = "🔴"
label = "OVERBOUGHT (Potential Sell)"
else:
emoji = "⚪"
label = condition.upper()
text = f"""
{emoji} *RSI Alert — {symbol}*
📊 RSI(14): `{rsi:.1f}` — {label}
💰 Price: `${price:,.2f}`
🕐 Time: `{datetime.utcnow().strftime('%H:%M UTC')}`
_Not financial advice. Paper trading only._
""".strip()
return send_message(token, chat_id, text)
def send_regime_change(token, chat_id, symbol, old_regime, new_regime, analysis):
"""Alert when market regime changes."""
regime_emoji = {
"BULL": "🐂",
"BEAR": "🐻",
"SIDEWAYS": "↔️",
"UNCERTAIN": "❓",
}
old_em = regime_emoji.get(old_regime, "❓")
new_em = regime_emoji.get(new_regime, "❓")
text = f"""
🔄 *Regime Change — {symbol}*
{old_em} {old_regime} → {new_em} *{new_regime}*
📋 Analysis:
_{analysis}_
🕐 Time: `{datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')}`
""".strip()
return send_message(token, chat_id, text)
def send_daily_summary(token, chat_id, portfolio_value, daily_pnl,
signals_today, watchlist_data):
"""Send end-of-day summary."""
pnl_emoji = "✅" if daily_pnl >= 0 else "❌"
watchlist_lines = []
for item in watchlist_data[:5]: # Max 5 in summary
chg = item["change_24h"]
em = "📈" if chg > 0 else "📉"
watchlist_lines.append(f" {em} {item['symbol']}: `${item['price']:,.2f}` ({chg:+.1f}%)")
watchlist_text = "\n".join(watchlist_lines) if watchlist_lines else " No data"
signals_text = signals_today if signals_today else "None today"
text = f"""
📋 *Daily Summary*
━━━━━━━━━━━━━━━━
{pnl_emoji} Portfolio: `${portfolio_value:,.2f}` ({daily_pnl:+.2f}% today)
📊 *Watchlist:*
{watchlist_text}
⚡ *Signals Today:* {signals_text}
🕐 `{datetime.utcnow().strftime('%Y-%m-%d %H:%M UTC')}`
""".strip()
return send_message(token, chat_id, text)
Step 3: Build the Signal Monitor
Now connect the alert functions to real market data:
# signal_monitor.py
import ccxt
import pandas as pd
import ta
import os
import json
import time
from telegram_alerts import send_rsi_alert, send_regime_change, send_daily_summary
from datetime import datetime
TOKEN = os.environ["TELEGRAM_BOT_TOKEN"]
CHAT_ID = os.environ["TELEGRAM_CHAT_ID"]
STATE_FILE = "monitor_state.json"
WATCHLIST = ["BTC/USDT", "ETH/USDT", "SOL/USDT"]
def load_state():
if os.path.exists(STATE_FILE):
with open(STATE_FILE) as f:
return json.load(f)
return {"last_regimes": {}, "last_rsi_alert": {}}
def save_state(state):
with open(STATE_FILE, "w") as f:
json.dump(state, f, indent=2)
def run_monitor():
exchange = ccxt.binance({"enableRateLimit": True})
state = load_state()
watchlist_data = []
for symbol in WATCHLIST:
try:
# Fetch data
raw = exchange.fetch_ohlcv(symbol, "4h", limit=220)
df = pd.DataFrame(raw, columns=["ts","open","high","low","close","volume"])
df["datetime"] = pd.to_datetime(df["ts"], unit="ms")
df.set_index("datetime", inplace=True)
# Calculate indicators
df["rsi"] = ta.momentum.RSIIndicator(df["close"], 14).rsi()
df["ema_200"] = ta.trend.EMAIndicator(df["close"], 200).ema_indicator()
df["ema_21"] = ta.trend.EMAIndicator(df["close"], 21).ema_indicator()
adx_obj = ta.trend.ADXIndicator(df["high"], df["low"], df["close"], 14)
df["adx"] = adx_obj.adx()
df.dropna(inplace=True)
latest = df.iloc[-1]
price = latest["close"]
rsi = latest["rsi"]
# Get 24h change
raw_1d = exchange.fetch_ohlcv(symbol, "1d", limit=2)
change_24h = (raw_1d[-1][4] - raw_1d[-2][4]) / raw_1d[-2][4] * 100
watchlist_data.append({
"symbol": symbol,
"price": price,
"change_24h": change_24h,
})
# RSI alerts (only if not alerted in last 6 hours)
last_rsi = state["last_rsi_alert"].get(symbol, 0)
now_ts = time.time()
if now_ts - last_rsi > 21600: # 6 hours
if rsi < 30:
send_rsi_alert(TOKEN, CHAT_ID, symbol, rsi, price, "oversold")
state["last_rsi_alert"][symbol] = now_ts
elif rsi > 70:
send_rsi_alert(TOKEN, CHAT_ID, symbol, rsi, price, "overbought")
state["last_rsi_alert"][symbol] = now_ts
# Regime detection
if latest["close"] > latest["ema_21"] > latest["ema_200"] and latest["adx"] > 25:
current_regime = "BULL"
elif latest["close"] < latest["ema_21"] < latest["ema_200"] and latest["adx"] > 25:
current_regime = "BEAR"
elif latest["adx"] < 20:
current_regime = "SIDEWAYS"
else:
current_regime = "UNCERTAIN"
old_regime = state["last_regimes"].get(symbol, "UNKNOWN")
if old_regime != current_regime and old_regime != "UNKNOWN":
send_regime_change(TOKEN, CHAT_ID, symbol, old_regime, current_regime,
f"ADX: {latest['adx']:.1f}, RSI: {rsi:.1f}")
state["last_regimes"][symbol] = current_regime
time.sleep(1) # Be nice to the exchange API
except Exception as e:
print(f"Error processing {symbol}: {e}")
save_state(state)
return watchlist_data
if __name__ == "__main__":
data = run_monitor()
print(f"Monitored {len(data)} symbols")
Step 4: Schedule with OpenClaw
Add this to your OpenClaw heartbeat configuration:
# In OpenClaw skill — runs every 4 hours
def crypto_heartbeat():
from signal_monitor import run_monitor
watchlist_data = run_monitor()
print(f"Monitoring complete: {len(watchlist_data)} symbols checked")
Or run it directly as a scheduled task:
# Windows Task Scheduler (every 4 hours)
schtasks /create /tn "CryptoMonitor" /tr "python C:\path\to\signal_monitor.py" /sc hourly /mo 4
Step 5: Add Interactive Commands
Make your bot two-way — send commands to get instant data:
def handle_commands(token, updates):
"""Process incoming Telegram commands."""
for update in updates:
msg = update.get("message", {})
text = msg.get("text", "")
chat_id = msg.get("chat", {}).get("id")
if text == "/price":
# Get current BTC price
exchange = ccxt.binance({"enableRateLimit": True})
ticker = exchange.fetch_ticker("BTC/USDT")
send_message(token, chat_id,
f"BTC: `${ticker['last']:,.2f}` ({ticker['percentage']:+.2f}%)")
elif text == "/status":
state = load_state()
lines = [f"*Current Regimes:*"]
for sym, regime in state["last_regimes"].items():
lines.append(f" {sym}: {regime}")
send_message(token, chat_id, "\n".join(lines))
elif text == "/help":
send_message(token, chat_id,
"*Available commands:*\n/price — BTC price\n/status — Current regimes\n/help — This message")
Alert Fatigue: Less Is More
The biggest risk with a new alert system is alert fatigue — getting so many notifications that you start ignoring them all.
Rules to avoid this:
- RSI alerts: Maximum once per 6 hours per symbol
- Regime alerts: Only on genuine transitions, not minor fluctuations
- Price alerts: Set meaningful thresholds (±5%, not ±1%)
- Daily summary: One message per day, at a fixed time
- No "market is moving" alerts: If you're tracking 10 coins, something is always moving
The goal is that when your phone buzzes with a crypto alert, it means something real.
Get the Full System
The complete Telegram alerting setup — including command handlers, portfolio tracking, multi-coin monitoring, and daily summaries — is in the OpenClaw kit:
👉 OpenClaw Home AI Agent Kit — Full Setup Guide
Your agent runs 24/7. Your alerts should too.
🛠️ Also check out CryptoClaw Skills Hub — browse and install crypto skills for your OpenClaw agent: https://paarthurnax970-debug.github.io/cryptoclawskills/
Not financial advice. Paper trading only. Telegram alerts are for informational purposes. Always make your own trading decisions.
Top comments (0)