📡 MONITORING: Tu Bot Siempre Bajo Control

Prometheus, Grafana y alertas por Telegram/Discord ” visibilidad total 24/7

Semanas 11-12: Operaciones y Monitoreo
Prometheus metrics Grafana dashboards Telegram bot Discord webhook
📡 Piénsalo así: Un bot de trading sin monitoring es como un avión sin instrumentos. El piloto podría estar volando bien¦ o en caída libre, y nunca lo sabría. Prometheus es la caja negra que registra todo (PNL, trades, latencia, errores) cada segundo. Grafana convierte esos datos en el tablero de instrumentos. Telegram/Discord es el copiloto que te llama cuando las alarmas suenan. El objetivo: que nunca descubras un problema revisando manualmente ” el sistema te avisa.
📚 Refs: Prometheus Docs ” instrumenting Python apps · python-telegram-bot library · Grafana dashboards for trading
Dashboard en Vivo
Prometheus
Alertas Bot
Grafana Config

Simulador de Dashboard en Tiempo Real

Feed de Alertas

Instrumentación Python con prometheus_client

from prometheus_client import (
  Counter, Gauge, Histogram, Summary,
  start_http_server
)
import time

# === MÉTRICAS DEL BOT ===

# Contadores (solo suben)
TRADES_TOTAL = Counter(
  'bot_trades_total',
  'Número total de trades',
  ['symbol', 'side', 'strategy']
)
ERRORS_TOTAL = Counter('bot_errors_total', 'Errores acumulados', ['type'])

# Gauges (suben y bajan)
PORTFOLIO_VALUE = Gauge('bot_portfolio_value_usd', 'Valor total del portfolio')
OPEN_POSITIONS = Gauge('bot_open_positions', 'Posiciones abiertas actualmente')
DAILY_PNL    = Gauge('bot_daily_pnl_pct', 'PNL del día en %')
LAST_PRICE   = Gauge('bot_last_price', 'Último precio', ['symbol'])

# Histogramas (distribución de valores)
TRADE_DURATION = Histogram(
  'bot_trade_duration_seconds',
  'Duración de trades',
  buckets=[60, 300, 900, 3600, 86400]
)
API_LATENCY = Histogram(
  'bot_api_latency_ms',
  'Latencia de llamadas al exchange'
)

# === USO EN EL BOT ===

def on_trade_executed(symbol, side, pnl):
  TRADES_TOTAL.labels(symbol=symbol, side=side, strategy='rsi_mean').inc()
  PORTFOLIO_VALUE.set(portfolio.total_value())
  DAILY_PNL.set(pnl)

with API_LATENCY.time(): # Context manager para latencia
  response = exchange.fetch_ticker('BTC/USDT')

# Exponer métricas en puerto 8080
start_http_server(8080)
# Prometheus scrapeará http://bot:8080/metrics cada 15s

prometheus.yml ” Configuración de Scraping

global:
 scrape_interval: 15s
 evaluation_interval: 15s

scrape_configs:
 - job_name: 'trading_bot'
  static_configs:
   - targets: ['bot:8080'] # nombre del servicio Docker
  relabel_configs:
   - source_labels: [__address__]
    target_label: instance
    replacement: 'bot-prod-1'

 - job_name: 'postgres'
  static_configs:
   - targets: ['postgres_exporter:9187']

alerting:
 alertmanagers:
  - static_configs:
    - targets: ['alertmanager:9093']

rule_files:
 - '/etc/prometheus/alerts.yml'

Bot de Telegram ” Alertas Automáticas

import asyncio
from telegram import Bot
from telegram.constants import ParseMode
import os

TELEGRAM_TOKEN = os.getenv("TELEGRAM_TOKEN")
TELEGRAM_CHAT  = os.getenv("TELEGRAM_CHAT_ID")
bot = Bot(token=TELEGRAM_TOKEN)

async def send_alert(msg: str, level="INFO"):
  icons = {"INFO":"¹ï¸", "WARN":" ï¸",
       "ERROR":"🚨", "TRADE":"💹"}
  text = f"{icons.get(level,'¢')} *[{level}]* {msg}"
  await bot.send_message(
    chat_id=TELEGRAM_CHAT,
    text=text,
    parse_mode=ParseMode.MARKDOWN
  )

# Alerta de trade ejecutado
async def notify_trade(side, symbol, price, pnl):
  emoji = "🟢" if pnl > 0 else "🔴"
  msg = (
    f"{emoji} *TRADE {side.upper()}*\n"
    f"Par: `{symbol}`\n"
    f"Precio: `{price:,.2f} USDT`\n"
    f"PNL: `{pnl:+.2f}%`"
  )
  await send_alert(msg, level="TRADE")

# Alerta de drawdown crítico
async def check_drawdown(current_dd):
  if current_dd > 0.05: # 5% drawdown
    await send_alert(
      f"Drawdown crítico: {current_dd:.1%}",
      level="WARN"
    )
# Discord Webhook ” alternativa
import requests

DISCORD_WH = os.getenv("DISCORD_WEBHOOK")

def discord_alert(title, desc, color=0x00dc64):
  payload = {
    "embeds": [{
      "title": title,
      "description": desc,
      "color": color,
      "footer": {
        "text": f"TradingBot · {datetime.now():%Y-%m-%d %H:%M}"
      }
    }]
  }
  requests.post(DISCORD_WH, json=payload)

# Uso:
discord_alert(
  "💹 Trade Ejecutado",
  f"BTC/USDT BUY @ $65,420\nPNL: +2.3%",
  color=0x00dc64 # verde
)
discord_alert(
  "🚨 ERROR CRÍTICO",
  "Exchange timeout - 3 reintentos fallidos",
  color=0xff4040 # rojo
)

# prometheus alertmanager ” alerts.yml
# groups:
#  - name: bot_alerts
#   rules:
#   - alert: HighDrawdown
#    expr: bot_daily_pnl_pct < -0.05
#    for: 1m
#    labels: {severity: critical}

Configuración de Grafana Dashboard

# grafana/datasources/prometheus.yml
apiVersion: 1
datasources:
 - name: Prometheus
  type: prometheus
  url: http://prometheus:9090
  isDefault: true
  access: proxy

# Queries PromQL para el dashboard

# PNL acumulado (línea)
sum(bot_daily_pnl_pct)

# Trades por hora
rate(bot_trades_total[1h]) * 3600

# Latencia P95 de la API
histogram_quantile(0.95,
 rate(bot_api_latency_ms_bucket[5m]))

# Errores por tipo
sum by(type) (bot_errors_total)

# Uptime del bot
up{job="trading_bot"}
# grafana/dashboards/bot.json (fragmento)
{
 "panels": [
  {
   "title": "💰 Portfolio Value",
   "type": "stat",
   "targets": [{
    "expr": "bot_portfolio_value_usd"
   }],
   "fieldConfig": {
    "defaults": {
     "unit": "currencyUSD",
     "thresholds": {
      "steps": [
       {"value": null, "color": "red"},
       {"value": 9000, "color": "yellow"},
       {"value": 10000, "color": "green"}
      ]
     }
    }
   }
  }
 ]
}
💡 Tip: Importa el dashboard ID 13659 desde grafana.com ” es el dashboard de Prometheus para Python apps más popular. Personalízalo con tus métricas de trading.
📡 Explora cada pestaña: inicia el stream en vivo, revisa el código de Prometheus y configura alertas.